2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.components.lifecycle;
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;
56 import javax.annotation.PostConstruct;
57 import java.util.HashMap;
60 @org.springframework.stereotype.Component("lifecycleBusinessLogic")
61 public class LifecycleBusinessLogic {
63 private static final String COMMENT = "comment";
66 private IGraphLockOperation graphLockOperation = null;
69 private ArtifactsBusinessLogic artifactsBusinessLogic;
72 private TitanDao titanDao;
75 private CapabilityOperation capabilityOperation;
77 private static final Logger log = Logger.getLogger(LifecycleBusinessLogic.class);
79 @javax.annotation.Resource
80 private ComponentsUtils componentUtils;
82 @javax.annotation.Resource
83 private ToscaElementLifecycleOperation lifecycleOperation;
84 @javax.annotation.Resource
85 ArtifactsBusinessLogic artifactsManager;
87 @javax.annotation.Resource
88 private ServiceDistributionArtifactsBuilder serviceDistributionArtifactsBuilder;
90 @javax.annotation.Resource
91 private ServiceBusinessLogic serviceBusinessLogic;
93 @javax.annotation.Resource
94 private ResourceBusinessLogic resourceBusinessLogic;
96 @javax.annotation.Resource
97 private ProductBusinessLogic productBusinessLogic;
100 private ToscaExportHandler toscaExportUtils;
103 ICacheMangerOperation cacheManagerOperation;
106 ToscaOperationFacade toscaOperationFacade;
109 NodeTemplateOperation nodeTemplateOperation;
111 private Map<String, LifeCycleTransition> stateTransitions;
112 private static volatile boolean isInitialized = false;
117 if (!isInitialized) {
118 synchronized (this) {
119 if (!isInitialized) {
120 initStateOperations();
121 isInitialized = true;
127 private void initStateOperations() {
128 stateTransitions = new HashMap<>();
130 LifeCycleTransition checkoutOp = new CheckoutTransition(componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
131 stateTransitions.put(checkoutOp.getName().name(), checkoutOp);
133 UndoCheckoutTransition undoCheckoutOp = new UndoCheckoutTransition(componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
134 undoCheckoutOp.setArtifactsBusinessLogic(artifactsBusinessLogic);
135 stateTransitions.put(undoCheckoutOp.getName().name(), undoCheckoutOp);
137 LifeCycleTransition checkinOp = new CheckinTransition(componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
138 stateTransitions.put(checkinOp.getName().name(), checkinOp);
140 LifeCycleTransition certificationRequest = new CertificationRequestTransition(componentUtils, lifecycleOperation, serviceBusinessLogic, toscaOperationFacade,
142 stateTransitions.put(certificationRequest.getName().name(), certificationRequest);
144 LifeCycleTransition startCertification = new StartCertificationTransition(componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
145 stateTransitions.put(startCertification.getName().name(), startCertification);
147 LifeCycleTransition failCertification = new CertificationChangeTransition(LifeCycleTransitionEnum.FAIL_CERTIFICATION, componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
148 stateTransitions.put(failCertification.getName().name(), failCertification);
150 LifeCycleTransition cancelCertification = new CertificationChangeTransition(LifeCycleTransitionEnum.CANCEL_CERTIFICATION, componentUtils, lifecycleOperation, toscaOperationFacade, titanDao);
151 stateTransitions.put(cancelCertification.getName().name(), cancelCertification);
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);
159 public LifeCycleTransition getLifecycleTransition(LifeCycleTransitionEnum transitionEnum) {
160 return stateTransitions.get(transitionEnum.name());
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);
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);
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)) {
182 public Either<? extends Component, ResponseFormat> changeComponentState(ComponentTypeEnum componentType, String componentId, User modifier, LifeCycleTransitionEnum transitionEnum, LifecycleChangeInfoWithAction changeInfo, boolean inTransaction,
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);
191 Component component = null;
192 log.debug("get resource from graph");
193 ResponseFormat errorResponse;
195 Either<? extends Component, ResponseFormat> eitherResourceResponse = getComponentForChange(componentType, componentId, modifier, lifeCycleTransition, changeInfo);
196 if (eitherResourceResponse.isRight()) {
197 return eitherResourceResponse;
199 component = eitherResourceResponse.left().value();
200 String resourceCurrVersion = component.getVersion();
201 LifecycleStateEnum resourceCurrState = component.getLifecycleState();
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)
217 log.error("lock component {} failed", componentId);
218 return Either.right(errorResponse);
220 log.debug("after lock component {}", componentId);
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)
232 changeInfo.getUserRemarks());
233 return Either.right(errorResponse);
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());
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;
247 component = changeResourceResponse.left().value();
249 return changeState(component, lifeCycleTransition, componentType, modifier, changeInfo, inTransaction);
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);
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
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;
284 updatedComponent = actionResponse.left().value();
285 oldState = updatedComponent.getLifecycleState();
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;
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;
298 updatedComponent = actionResponse.left().value();
300 if(oldState == LifecycleStateEnum.CERTIFIED){
301 failOnAlreadyCertifiedResource(component);
304 return Either.left(updatedComponent);
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];
317 throw new ComponentException(ActionStatus.COMPONENT_ALREADY_CERTIFIED,
319 component.getComponentType().name().toLowerCase(),
322 component.getLastUpdaterUserId());
325 private Either<? extends Component, ResponseFormat> changeState(Component component, LifeCycleTransition lifeCycleTransition, ComponentTypeEnum componentType, User modifier, LifecycleChangeInfoWithAction changeInfo, boolean inTransaction) {
326 ResponseFormat errorResponse;
328 LifecycleStateEnum oldState = component.getLifecycleState();
329 String resourceCurrVersion = component.getVersion();
330 ComponentBusinessLogic bl = getComponentBL(componentType);
332 Either<User, ResponseFormat> ownerResult = lifeCycleTransition.getComponentOwner(component, componentType);
333 if (ownerResult.isRight()) {
334 return Either.right(ownerResult.right().value());
336 User owner = ownerResult.left().value();
337 log.info("owner of resource {} is {}", component.getUniqueId(), owner.getUserId());
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())
349 changeInfo.getUserRemarks());
350 return Either.right(errorResponse);
353 Either<? extends Component, ResponseFormat> operationResult = lifeCycleTransition.changeState(componentType, component, bl, modifier, owner, false, inTransaction);
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)
364 return Either.right(errorResponse);
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)
373 changeInfo.getUserRemarks());
374 return operationResult;
379 private Either<? extends Component, ResponseFormat> getComponentForChange(ComponentTypeEnum componentType, String componentId, User modifier, LifeCycleTransition lifeCycleTransition, LifecycleChangeInfoWithAction changeInfo) {
381 Either<? extends Component, StorageOperationStatus> eitherResourceResponse = toscaOperationFacade.getToscaElement(componentId);
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());
391 return Either.right(errorResponse);
393 return Either.left(eitherResourceResponse.left().value());
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)
407 return Either.right(errorResponse);
409 return Either.left(true);
412 private Either<Boolean, ResponseFormat> lockComponent(ComponentTypeEnum componentType, Component component) {
413 NodeTypeEnum nodeType = componentType.getNodeType();
414 StorageOperationStatus lockResourceStatus = graphLockOperation.lockComponent(component.getUniqueId(), nodeType);
416 if (lockResourceStatus.equals(StorageOperationStatus.OK)) {
417 return Either.left(true);
419 ActionStatus actionStatus = componentUtils.convertFromStorageResponse(lockResourceStatus);
420 ResponseFormat responseFormat = componentUtils.getResponseFormat(actionStatus, component.getComponentMetadataDefinition().getMetadataDataDefinition().getName());
421 return Either.right(responseFormat);
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
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);
439 comment = ValidationUtils.removeNoneUtf8Chars(comment);
440 comment = ValidationUtils.removeHtmlTags(comment);
441 comment = ValidationUtils.normaliseWhitespace(comment);
442 comment = ValidationUtils.stripOctets(comment);
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)));
448 if (!ValidationUtils.validateIsEnglish(comment)) {
449 return Either.right(componentUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
452 return Either.left(comment);
455 private ComponentBusinessLogic getComponentBL(ComponentTypeEnum componentTypeEnum) {
456 ComponentBusinessLogic businessLogic;
457 switch (componentTypeEnum) {
459 businessLogic = this.resourceBusinessLogic;
462 businessLogic = this.serviceBusinessLogic;
465 businessLogic = this.productBusinessLogic;
468 throw new IllegalArgumentException("Illegal component type:" + componentTypeEnum.getValue());
470 return businessLogic;
473 public Either<Component, ResponseFormat> getLatestComponentByUuid(ComponentTypeEnum componentTypeEnum, String uuid) {
475 Either<Component, StorageOperationStatus> latestVersionEither = toscaOperationFacade.getLatestComponentByUuid(uuid);
477 if (latestVersionEither.isRight()) {
479 return Either.right(componentUtils.getResponseFormat(componentUtils.convertFromStorageResponse(latestVersionEither.right().value(), componentTypeEnum), uuid));
482 Component latestComponent = latestVersionEither.left().value();
484 return Either.left(latestComponent);
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
493 * @param lifecycleChangeInfo
494 * @param inTransaction
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));
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));
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());
517 log.info("after lock component {}", resource.getUniqueId());
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));
528 if (result == null) {
529 result = Either.left(ModelConverter.convertFromToscaElement(certifyResourceRes.left().value()));
532 log.info("unlock component {}", resource.getUniqueId());
533 if (!inTransaction) {
534 if (result.isLeft()) {
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);
549 public boolean isFirstCertification(String previousVersion) {
550 return previousVersion.split("\\.")[0].equals("0");