Merge "Add proxy support"
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / lifecycle / LifecycleBusinessLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.components.lifecycle;
22
23 import java.util.EnumMap;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import javax.annotation.PostConstruct;
28
29 import org.openecomp.sdc.be.components.distribution.engine.ServiceDistributionArtifactsBuilder;
30 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
31 import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic;
32 import org.openecomp.sdc.be.components.impl.ProductBusinessLogic;
33 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
34 import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
35 import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction.LifecycleChanceActionEnum;
36 import org.openecomp.sdc.be.config.BeEcompErrorManager;
37 import org.openecomp.sdc.be.dao.api.ActionStatus;
38 import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
39 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
40 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
41 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
42 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
43 import org.openecomp.sdc.be.impl.ComponentsUtils;
44 import org.openecomp.sdc.be.model.Component;
45 import org.openecomp.sdc.be.model.LifeCycleTransitionEnum;
46 import org.openecomp.sdc.be.model.LifecycleStateEnum;
47 import org.openecomp.sdc.be.model.Resource;
48 import org.openecomp.sdc.be.model.Service;
49 import org.openecomp.sdc.be.model.User;
50 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
51 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaElementLifecycleOperation;
52 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
53 import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter;
54 import org.openecomp.sdc.be.model.operations.api.ICacheMangerOperation;
55 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
56 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
57 import org.openecomp.sdc.be.model.operations.impl.CapabilityOperation;
58 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
59 import org.openecomp.sdc.be.tosca.ToscaExportHandler;
60 import org.openecomp.sdc.common.api.Constants;
61 import org.openecomp.sdc.common.config.EcompErrorName;
62 import org.openecomp.sdc.common.datastructure.AuditingFieldsKeysEnum;
63 import org.openecomp.sdc.common.util.ValidationUtils;
64 import org.openecomp.sdc.exception.ResponseFormat;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67 import org.springframework.beans.factory.annotation.Autowired;
68
69 import fj.data.Either;
70
71 @org.springframework.stereotype.Component("lifecycleBusinessLogic")
72 public class LifecycleBusinessLogic {
73
74         private static final String COMMENT = "comment";
75
76         @Autowired
77         private IGraphLockOperation graphLockOperation = null;
78
79         @Autowired
80         private ArtifactsBusinessLogic artifactsBusinessLogic;
81
82         @Autowired
83         private TitanDao titanDao;
84
85         @Autowired
86         private CapabilityOperation capabilityOperation;
87
88         private static Logger log = LoggerFactory.getLogger(LifecycleBusinessLogic.class.getName());
89
90         @javax.annotation.Resource
91         private ComponentsUtils componentUtils;
92
93         @javax.annotation.Resource
94         private ToscaElementLifecycleOperation lifecycleOperation;
95         @javax.annotation.Resource
96         ArtifactsBusinessLogic artifactsManager;
97
98         @javax.annotation.Resource
99         private ServiceDistributionArtifactsBuilder serviceDistributionArtifactsBuilder;
100
101         @javax.annotation.Resource
102         private ServiceBusinessLogic serviceBusinessLogic;
103
104         @javax.annotation.Resource
105         private ResourceBusinessLogic resourceBusinessLogic;
106
107         @javax.annotation.Resource
108         private ProductBusinessLogic productBusinessLogic;
109
110         @Autowired
111         private ToscaExportHandler toscaExportUtils;
112
113         @Autowired
114         ICacheMangerOperation cacheManagerOperation;
115         
116         @Autowired
117         ToscaOperationFacade toscaOperationFacade;
118
119         private Map<String, LifeCycleTransition> stateTransitions;
120         private static volatile boolean isInitialized = false;
121
122         @PostConstruct
123         public void init() {
124                 // init parameters
125                 if (!isInitialized) {
126                         synchronized (this) {
127                                 if (!isInitialized) {
128                                         initStateOperations();
129                                         isInitialized = true;
130                                 }
131                         }
132                 }
133         }
134
135         private void initStateOperations() {
136                 stateTransitions = new HashMap<String, LifeCycleTransition>();
137
138                 LifeCycleTransition checkoutOp = new CheckoutTransition(componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
139                 stateTransitions.put(checkoutOp.getName().name(), checkoutOp);
140
141                 UndoCheckoutTransition undoCheckoutOp = new UndoCheckoutTransition(componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
142                 undoCheckoutOp.setArtifactsBusinessLogic(artifactsBusinessLogic);
143                 stateTransitions.put(undoCheckoutOp.getName().name(), undoCheckoutOp);
144
145                 LifeCycleTransition checkinOp = new CheckinTransition(componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
146                 stateTransitions.put(checkinOp.getName().name(), checkinOp);
147
148                 LifeCycleTransition certificationRequest = new CertificationRequestTransition(componentUtils, lifecycleOperation, serviceDistributionArtifactsBuilder, serviceBusinessLogic, capabilityOperation, toscaExportUtils, toscaOperationFacade, titanDao);
149                 stateTransitions.put(certificationRequest.getName().name(), certificationRequest);
150
151                 LifeCycleTransition startCertification = new StartCertificationTransition(componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
152                 stateTransitions.put(startCertification.getName().name(), startCertification);
153
154                 LifeCycleTransition failCertification = new CertificationChangeTransition(LifeCycleTransitionEnum.FAIL_CERTIFICATION, componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
155                 stateTransitions.put(failCertification.getName().name(), failCertification);
156
157                 LifeCycleTransition cancelCertification = new CertificationChangeTransition(LifeCycleTransitionEnum.CANCEL_CERTIFICATION, componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
158                 stateTransitions.put(cancelCertification.getName().name(), cancelCertification);
159
160                 CertificationChangeTransition successCertification = new CertificationChangeTransition(LifeCycleTransitionEnum.CERTIFY, componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
161                 successCertification.setArtifactsManager(artifactsBusinessLogic);
162                 stateTransitions.put(successCertification.getName().name(), successCertification);
163         }
164
165         public LifeCycleTransition getLifecycleTransition(LifeCycleTransitionEnum transitionEnum) {
166                 return stateTransitions.get(transitionEnum.name());
167         }
168
169         public Either<Service, ResponseFormat> changeServiceState(String serviceId, User modifier, LifeCycleTransitionEnum transitionEnum, LifecycleChangeInfoWithAction changeInfo, boolean inTransaction, boolean needLock) {
170                 return (Either<Service, ResponseFormat>) changeComponentState(ComponentTypeEnum.SERVICE, serviceId, modifier, transitionEnum, changeInfo, inTransaction, needLock);
171         }
172
173         // TODO: rhalili - should use changeComponentState when possible
174         public Either<Resource, ResponseFormat> changeState(String resourceId, User modifier, LifeCycleTransitionEnum transitionEnum, LifecycleChangeInfoWithAction changeInfo, boolean inTransaction, boolean needLock) {
175                 return (Either<Resource, ResponseFormat>) changeComponentState(ComponentTypeEnum.RESOURCE, resourceId, modifier, transitionEnum, changeInfo, inTransaction, needLock);
176         }
177         
178         private boolean isComponentVFCMT(Component component, ComponentTypeEnum componentType){
179                 if (componentType.equals(ComponentTypeEnum.RESOURCE)){
180                         ResourceTypeEnum resourceType = ((ResourceMetadataDataDefinition)component.getComponentMetadataDefinition().getMetadataDataDefinition()).getResourceType();
181                         if (resourceType.equals(ResourceTypeEnum.VFCMT)){
182                                 return true;                                    
183                         }
184                 }       
185                 return false;
186         }
187
188         public Either<? extends Component, ResponseFormat> changeComponentState(ComponentTypeEnum componentType, String componentId, User modifier, LifeCycleTransitionEnum transitionEnum, LifecycleChangeInfoWithAction changeInfo, boolean inTransaction,
189                         boolean needLock) {
190
191                 LifeCycleTransition lifeCycleTransition = stateTransitions.get(transitionEnum.name());
192                 if (lifeCycleTransition == null) {
193                         log.debug("state operation is not valid. operations allowed are: {}", LifeCycleTransitionEnum.valuesAsString());
194                         ResponseFormat error = componentUtils.getInvalidContentErrorAndAudit(modifier, AuditingActionEnum.CHECKOUT_RESOURCE);
195                         return Either.right(error);
196                 }
197                 Component component = null;
198                 log.info("get resource from graph");
199                 ResponseFormat errorResponse;
200
201                 Either<? extends Component, ResponseFormat> eitherResourceResponse = getComponentForChange(componentType, componentId, modifier, lifeCycleTransition, changeInfo);
202                 if (eitherResourceResponse.isRight()) {
203                         return eitherResourceResponse;
204                 }
205                 component = eitherResourceResponse.left().value();
206                 String resourceCurrVersion = component.getVersion();
207                 LifecycleStateEnum resourceCurrState = component.getLifecycleState();
208
209                 // lock resource
210                 if (inTransaction == false && needLock) {
211                         log.info("lock component {}", componentId);
212                         Either<Boolean, ResponseFormat> eitherLockResource = lockComponent(componentType, component);
213                         if (eitherLockResource.isRight()) {
214                                 errorResponse = eitherLockResource.right().value();
215                                 componentUtils.auditComponent(errorResponse, modifier, component, resourceCurrState.name(), resourceCurrVersion, lifeCycleTransition.getAuditingAction(), componentType, null);
216                                 log.error("lock component {} failed", componentId);
217                                 return Either.right(errorResponse);
218                         }
219                         log.info("after lock component {}", componentId);
220                 }
221                 try {
222                         Either<String, ResponseFormat> commentValidationResult = validateComment(changeInfo, transitionEnum);
223                         if (commentValidationResult.isRight()) {
224                                 errorResponse = commentValidationResult.right().value();
225                                 EnumMap<AuditingFieldsKeysEnum, Object> auditingFields = new EnumMap<>(AuditingFieldsKeysEnum.class);
226                                 auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_COMMENT, changeInfo.getUserRemarks());
227                                 componentUtils.auditComponent(errorResponse, modifier, component, resourceCurrState.name(), resourceCurrVersion, lifeCycleTransition.getAuditingAction(), componentType, auditingFields);
228                                 return Either.right(errorResponse);
229                         }
230                         changeInfo.setUserRemarks(commentValidationResult.left().value());
231                         log.info("after validate component");
232                         Either<Boolean, ResponseFormat> validateHighestVersion = validateHighestVersion(modifier, lifeCycleTransition, component, resourceCurrVersion, componentType);
233                         if (validateHighestVersion.isRight()) {
234                                 return Either.right(validateHighestVersion.right().value());
235                         }
236                         log.info("after validate Highest Version");
237                         if (isComponentVFCMT(component,componentType)){
238                                 Either<? extends Component, ResponseFormat> changeVFCMTStateResponse = changeVFCMTState(componentType, modifier, transitionEnum, changeInfo, inTransaction, component);
239                                 if (changeVFCMTStateResponse.isRight()){
240                                         return changeVFCMTStateResponse;
241                                 }
242                         }
243
244                         return changeState(component, lifeCycleTransition, componentType, modifier, changeInfo, inTransaction);
245                 } finally {
246                         log.info("unlock component {}", componentId);
247                         if (inTransaction == false && needLock && component != null) {
248                                 component.setUniqueId(componentId);
249                                 NodeTypeEnum nodeType = componentType.getNodeType();
250                                                 log.info("During change state, another component {} has been created/updated", componentId);
251                                 graphLockOperation.unlockComponent(componentId, nodeType);
252
253                         }
254                 }
255
256         }
257
258         /*
259          * special case for certification of VFCMT - VFCMT can be certified by Designer or Tester right after checkin
260          * in case the operation "submit for test" / "start testing" is done to "VFCMT" - please return error 400 
261          */
262         private Either<? extends Component, ResponseFormat> changeVFCMTState(ComponentTypeEnum componentType, User modifier,
263                         LifeCycleTransitionEnum transitionEnum, LifecycleChangeInfoWithAction changeInfo, boolean inTransaction,
264                         Component component) {
265                 LifecycleStateEnum oldState = component.getLifecycleState();
266                 if (transitionEnum.equals(LifeCycleTransitionEnum.START_CERTIFICATION) || 
267                                 transitionEnum.equals(LifeCycleTransitionEnum.CERTIFICATION_REQUEST)){
268                         return Either.right(componentUtils.getResponseFormat(
269                                         ActionStatus.RESOURCE_VFCMT_LIFECYCLE_STATE_NOT_VALID, transitionEnum.getDisplayName()));                                       
270                 }       //certify is done directly from checkin 
271                 else if (transitionEnum.equals(LifeCycleTransitionEnum.CERTIFY) && oldState.equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKIN)){
272                         //we will call for submit for testing first and then for certify
273                         Either<? extends Component, ResponseFormat> actionResponse = changeState(component, 
274                                         stateTransitions.get(LifeCycleTransitionEnum.CERTIFICATION_REQUEST.name()), 
275                                         componentType, modifier, changeInfo, inTransaction);
276                         if (actionResponse.isRight()) {
277                                 return actionResponse;
278                         }
279                         actionResponse = changeState(component, 
280                                         stateTransitions.get(LifeCycleTransitionEnum.START_CERTIFICATION.name()), 
281                                         componentType, modifier, changeInfo, inTransaction);
282                         if (actionResponse.isRight()) {
283                                 return actionResponse;
284                         }                                               
285                 }
286                 return Either.left(null);
287         }
288         
289         private Either<? extends Component, ResponseFormat> changeState(Component component, LifeCycleTransition lifeCycleTransition, 
290                         ComponentTypeEnum componentType, User modifier, LifecycleChangeInfoWithAction changeInfo,boolean inTransaction){
291                 ResponseFormat errorResponse;
292                 
293                 LifecycleStateEnum oldState = component.getLifecycleState();
294                 String resourceCurrVersion = component.getVersion();
295                 ComponentBusinessLogic bl = getComponentBL(componentType);
296                 
297                 Either<User, ResponseFormat> ownerResult = lifeCycleTransition.getComponentOwner(component, componentType, inTransaction);
298                 if (ownerResult.isRight()) {
299                         return Either.right(ownerResult.right().value());
300                 }
301                 User owner = ownerResult.left().value();
302                 log.info("owner of resource {} is {}", component.getUniqueId(), owner.getUserId());
303
304                 Either<Boolean, ResponseFormat> stateValidationResult = lifeCycleTransition.validateBeforeTransition(component, componentType, modifier, owner, oldState, changeInfo);
305                 if (stateValidationResult.isRight()) {
306                         log.error("Failed to validateBeforeTransition");
307                         errorResponse = stateValidationResult.right().value();
308                         EnumMap<AuditingFieldsKeysEnum, Object> auditingFields = new EnumMap<>(AuditingFieldsKeysEnum.class);
309                         auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_COMMENT, changeInfo.getUserRemarks());
310                         componentUtils.auditComponent(errorResponse, modifier, component, oldState.name(), resourceCurrVersion, lifeCycleTransition.getAuditingAction(), componentType, auditingFields);
311                         return Either.right(errorResponse);
312                 }
313                 
314                 Either<? extends Component, ResponseFormat> operationResult = lifeCycleTransition.changeState(componentType, component, bl, modifier, owner, false, inTransaction);
315
316                 if (operationResult.isRight()) {
317                         errorResponse = operationResult.right().value();
318                         log.info("audit before sending error response");
319                         componentUtils.auditComponentAdmin(errorResponse, modifier, component, oldState.name(), resourceCurrVersion, lifeCycleTransition.getAuditingAction(), componentType);
320
321                         return Either.right(errorResponse);
322                 }
323                 Component resourceAfterOperation = operationResult.left().value();
324                 EnumMap<AuditingFieldsKeysEnum, Object> auditingFields = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
325                 auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_COMMENT, changeInfo.getUserRemarks());
326                 componentUtils.auditComponent(componentUtils.getResponseFormat(ActionStatus.OK), modifier, resourceAfterOperation, oldState.name(), resourceCurrVersion, lifeCycleTransition.getAuditingAction(), componentType, auditingFields);
327                 return operationResult;
328
329         }
330
331         private Either<? extends Component, ResponseFormat> getComponentForChange(ComponentTypeEnum componentType, String componentId, User modifier, LifeCycleTransition lifeCycleTransition, LifecycleChangeInfoWithAction changeInfo) {
332
333                 Either<? extends Component, StorageOperationStatus> eitherResourceResponse = toscaOperationFacade.getToscaElement(componentId);
334
335                 ResponseFormat errorResponse;
336                 if (eitherResourceResponse.isRight()) {
337                         ActionStatus actionStatus = componentUtils.convertFromStorageResponse(eitherResourceResponse.right().value(), componentType);
338                         errorResponse = componentUtils.getResponseFormat(actionStatus, Constants.EMPTY_STRING);
339                         log.debug("audit before sending response");
340                         EnumMap<AuditingFieldsKeysEnum, Object> auditingFields = new EnumMap<AuditingFieldsKeysEnum, Object>(AuditingFieldsKeysEnum.class);
341                         auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_COMMENT, changeInfo.getUserRemarks());
342                         auditingFields.put(AuditingFieldsKeysEnum.AUDIT_RESOURCE_NAME, componentId);
343                         componentUtils.auditComponent(errorResponse, modifier, null, Constants.EMPTY_STRING, Constants.EMPTY_STRING, lifeCycleTransition.getAuditingAction(), componentType, auditingFields);
344
345                         return Either.right(errorResponse);
346                 }
347                 return Either.left(eitherResourceResponse.left().value());
348         }
349
350         private Either<Boolean, ResponseFormat> validateHighestVersion(User modifier, LifeCycleTransition lifeCycleTransition, Resource resource, String resourceCurrVersion) {
351                 ResponseFormat errorResponse;
352                 if (!resource.isHighestVersion()) {
353                         log.debug("resource version {} is not the last version of resource {}", resource.getVersion(), resource.getName());
354                         errorResponse = componentUtils.getResponseFormat(ActionStatus.COMPONENT_HAS_NEWER_VERSION, resource.getName(), ComponentTypeEnum.RESOURCE.name().toLowerCase());
355                         componentUtils.auditResource(errorResponse, modifier, resource, resource.getLifecycleState().name(), resourceCurrVersion, lifeCycleTransition.getAuditingAction(), null);
356                         return Either.right(errorResponse);
357                 }
358                 return Either.left(true);
359         }
360
361         private Either<Boolean, ResponseFormat> validateResourceNotDeleted(User modifier, LifeCycleTransition lifeCycleTransition, Resource resource, String resourceCurrVersion) {
362
363                 ResponseFormat errorResponse;
364                 if ((resource.getIsDeleted() != null) && (resource.getIsDeleted() == true)) {
365                         ActionStatus actionStatus = ActionStatus.RESOURCE_NOT_FOUND;
366                         errorResponse = componentUtils.getResponseFormatByResource(actionStatus, resource.getName());
367                         log.debug("resource {} {} is marked for delete", resource.getName(), resource.getVersion());
368                         componentUtils.auditResource(errorResponse, modifier, null, "", "", lifeCycleTransition.getAuditingAction(), null);
369
370                         return Either.right(errorResponse);
371                 }
372                 return Either.left(true);
373         }
374
375         private Either<Boolean, ResponseFormat> validateHighestVersion(User modifier, LifeCycleTransition lifeCycleTransition, Component component, String resourceCurrVersion, ComponentTypeEnum componentType) {
376                 ResponseFormat errorResponse;
377                 if (!component.isHighestVersion()) {
378                         log.debug("Component version {} is not the last version of component {}", component.getComponentMetadataDefinition().getMetadataDataDefinition().getVersion(),
379                                         component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
380                         errorResponse = componentUtils.getResponseFormat(ActionStatus.COMPONENT_HAS_NEWER_VERSION, component.getComponentMetadataDefinition().getMetadataDataDefinition().getName(), componentType.getValue().toLowerCase());
381                         componentUtils.auditComponentAdmin(errorResponse, modifier, component, component.getLifecycleState().name(), resourceCurrVersion, lifeCycleTransition.getAuditingAction(), componentType);
382                         return Either.right(errorResponse);
383                 }
384                 return Either.left(true);
385         }
386
387         private Either<Boolean, ResponseFormat> lockComponent(ComponentTypeEnum componentType, Component component) {
388                 NodeTypeEnum nodeType = componentType.getNodeType();
389                 StorageOperationStatus lockResourceStatus = graphLockOperation.lockComponent(component.getUniqueId(), nodeType);
390
391                 if (lockResourceStatus.equals(StorageOperationStatus.OK)) {
392                         return Either.left(true);
393                 } else {
394                         ActionStatus actionStatus = componentUtils.convertFromStorageResponse(lockResourceStatus);
395                         ResponseFormat responseFormat = componentUtils.getResponseFormat(actionStatus, component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
396                         return Either.right(responseFormat);
397                 }
398
399         }
400
401         private Either<String, ResponseFormat> validateComment(LifecycleChangeInfoWithAction changeInfo, LifeCycleTransitionEnum transitionEnum) {
402                 String comment = changeInfo.getUserRemarks();
403                 if (LifeCycleTransitionEnum.CANCEL_CERTIFICATION == transitionEnum || LifeCycleTransitionEnum.CERTIFY == transitionEnum || LifeCycleTransitionEnum.FAIL_CERTIFICATION == transitionEnum || LifeCycleTransitionEnum.CHECKIN == transitionEnum
404                                 || LifeCycleTransitionEnum.CERTIFICATION_REQUEST == transitionEnum
405                 // import?
406                 ) {
407
408                         if (!ValidationUtils.validateStringNotEmpty(comment)) {
409                                 log.debug("user comment cannot be empty or null.");
410                                 ResponseFormat errorResponse = componentUtils.getResponseFormat(ActionStatus.MISSING_DATA, COMMENT);
411                                 return Either.right(errorResponse);
412                         }
413
414                         comment = ValidationUtils.removeNoneUtf8Chars(comment);
415                         comment = ValidationUtils.removeHtmlTags(comment);
416                         comment = ValidationUtils.normaliseWhitespace(comment);
417                         comment = ValidationUtils.stripOctets(comment);
418
419                         if (!ValidationUtils.validateLength(comment, ValidationUtils.COMMENT_MAX_LENGTH)) {
420                                 log.debug("user comment exceeds limit.");
421                                 return Either.right(componentUtils.getResponseFormat(ActionStatus.EXCEEDS_LIMIT, COMMENT, String.valueOf(ValidationUtils.COMMENT_MAX_LENGTH)));
422                         }
423                         if (!ValidationUtils.validateIsEnglish(comment)) {
424                                 return Either.right(componentUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
425                         }
426                 }
427                 return Either.left(comment);
428         }
429
430         private ComponentBusinessLogic getComponentBL(ComponentTypeEnum componentTypeEnum) {
431                 ComponentBusinessLogic businessLogic;
432                 switch (componentTypeEnum) {
433                         case RESOURCE: {
434                                 businessLogic = this.resourceBusinessLogic;
435                                 break;
436                         }
437                         case SERVICE: {
438                                 businessLogic = this.serviceBusinessLogic;
439                                 break;
440                         }
441                         case PRODUCT: {
442                                 businessLogic = this.productBusinessLogic;
443                                 break;
444                         }
445         
446                         default: {
447                                 BeEcompErrorManager.getInstance().processEcompError(EcompErrorName.BeSystemError, "getComponentBL");
448                                 throw new IllegalArgumentException("Illegal component type:" + componentTypeEnum.getValue());
449                         }
450                 }
451                 return businessLogic;
452         }
453         
454         public Either<Component, ResponseFormat> getLatestComponentByUuid(ComponentTypeEnum componentTypeEnum, String uuid) {
455                 
456                 Either<Component, StorageOperationStatus> latestVersionEither = toscaOperationFacade.getLatestComponentByUuid(uuid);    
457                 
458                 if (latestVersionEither.isRight()) {
459                         
460                         return Either.right(componentUtils.getResponseFormat(componentUtils.convertFromStorageResponse(latestVersionEither.right().value(), componentTypeEnum), uuid));
461                 }
462                 
463                 Component latestComponent = latestVersionEither.left().value();         
464                 
465                 return Either.left(latestComponent);
466         }
467
468         public Either<Resource, ResponseFormat> forceResourceCertification(Resource resource, User user, LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean inTransaction, boolean needLock) {
469                 Either<Resource, ResponseFormat> result = null;
470                 Either<ToscaElement, StorageOperationStatus> certifyResourceRes = null;
471                 if(lifecycleChangeInfo.getAction() != LifecycleChanceActionEnum.CREATE_FROM_CSAR){
472                         log.debug("Force certification is not allowed for the action {}. ", lifecycleChangeInfo.getAction().name());
473                         result = Either.right(componentUtils.getResponseFormat(ActionStatus.NOT_ALLOWED));
474                 }
475                 // lock resource
476                 if(result == null && !inTransaction && needLock){
477                         log.info("lock component {}", resource.getUniqueId());
478                         Either<Boolean, ResponseFormat> eitherLockResource = lockComponent(resource.getComponentType(), resource);
479                         if (eitherLockResource.isRight()) {
480                                 log.error("lock component {} failed", resource.getUniqueId());
481                                 result =  Either.right(eitherLockResource.right().value());
482                         }
483                         log.info("after lock component {}", resource.getUniqueId());
484                 }
485                 try{
486                         if(result == null){
487                                 certifyResourceRes = lifecycleOperation.forceCerificationOfToscaElement(resource.getUniqueId(), user.getUserId(), user.getUserId(), resource.getVersion());
488                                 if (certifyResourceRes.isRight()) {
489                                         StorageOperationStatus status = certifyResourceRes.right().value();
490                                         log.debug("Failed to perform a force certification of resource {}. The status is {}. ", resource.getName(), status);
491                                         result = Either.right(componentUtils.getResponseFormatByResource(componentUtils.convertFromStorageResponse(status), resource));
492                                 }
493                         }
494                         if(result == null){
495                                 result = Either.left(ModelConverter.convertFromToscaElement(certifyResourceRes.left().value()));
496                         }
497                 } finally {
498                         log.info("unlock component {}", resource.getUniqueId());
499                         if (!inTransaction) {
500                                 if(result.isLeft()){
501                                         titanDao.commit();
502                                 } else{
503                                         titanDao.rollback();
504                                 }
505                                 if(needLock){
506                                         NodeTypeEnum nodeType = resource.getComponentType().getNodeType();
507                                         log.info("During change state, another component {} has been created/updated", resource.getUniqueId());
508                                         graphLockOperation.unlockComponent(resource.getUniqueId(), nodeType);
509                                 }
510                         }
511                 }
512                 return result;
513         }
514
515 }