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