db03c7277852fcddbba6fd0364fd4f1721980127
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / BaseBusinessLogic.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  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22 package org.openecomp.sdc.be.components.impl;
23
24 import static org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR;
25
26 import com.google.gson.JsonElement;
27 import fj.data.Either;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.function.Function;
34 import org.apache.commons.lang3.ArrayUtils;
35 import org.apache.commons.lang3.StringUtils;
36 import org.apache.commons.lang3.tuple.ImmutablePair;
37 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
38 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
39 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
40 import org.openecomp.sdc.be.components.validation.UserValidations;
41 import org.openecomp.sdc.be.config.BeEcompErrorManager;
42 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
43 import org.openecomp.sdc.be.dao.api.ActionStatus;
44 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
45 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
46 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
47 import org.openecomp.sdc.be.datamodel.utils.ArtifactUtils;
48 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
49 import org.openecomp.sdc.be.datatypes.elements.PropertyRule;
50 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
51 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
52 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
53 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
54 import org.openecomp.sdc.be.impl.ComponentsUtils;
55 import org.openecomp.sdc.be.model.ArtifactDefinition;
56 import org.openecomp.sdc.be.model.Component;
57 import org.openecomp.sdc.be.model.ComponentInstInputsMap;
58 import org.openecomp.sdc.be.model.ComponentInstOutputsMap;
59 import org.openecomp.sdc.be.model.ComponentInstance;
60 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
61 import org.openecomp.sdc.be.model.ComponentParametersView;
62 import org.openecomp.sdc.be.model.DataTypeDefinition;
63 import org.openecomp.sdc.be.model.IComplexDefaultValue;
64 import org.openecomp.sdc.be.model.IPropertyInputCommon;
65 import org.openecomp.sdc.be.model.LifecycleStateEnum;
66 import org.openecomp.sdc.be.model.PolicyDefinition;
67 import org.openecomp.sdc.be.model.PropertyConstraint;
68 import org.openecomp.sdc.be.model.PropertyDefinition;
69 import org.openecomp.sdc.be.model.User;
70 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
71 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
72 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation;
73 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
74 import org.openecomp.sdc.be.model.operations.StorageException;
75 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
76 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
77 import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation;
78 import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
79 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
80 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
81 import org.openecomp.sdc.be.model.operations.impl.AttributeOperation;
82 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
83 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
84 import org.openecomp.sdc.be.model.operations.impl.PolicyTypeOperation;
85 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
86 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
87 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
88 import org.openecomp.sdc.be.model.tosca.ToscaType;
89 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
90 import org.openecomp.sdc.be.model.tosca.validators.DataTypeValidatorConverter;
91 import org.openecomp.sdc.be.model.tosca.validators.PropertyTypeValidator;
92 import org.openecomp.sdc.be.user.Role;
93 import org.openecomp.sdc.be.user.UserBusinessLogic;
94 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
95 import org.openecomp.sdc.common.datastructure.Wrapper;
96 import org.openecomp.sdc.common.log.wrappers.Logger;
97 import org.openecomp.sdc.exception.ResponseFormat;
98 import org.springframework.beans.factory.annotation.Autowired;
99
100 public abstract class BaseBusinessLogic {
101
102     private static final String FAILED_TO_LOCK_COMPONENT_ERROR = "Failed to lock component {} error - {}";
103     private static final Logger log = Logger.getLogger(BaseBusinessLogic.class);
104     private static final String EMPTY_VALUE = null;
105     private static final String SCHEMA_DOESN_T_EXISTS_FOR_PROPERTY_OF_TYPE = "Schema doesn't exists for property of type {}";
106     private static final String PROPERTY_IN_SCHEMA_DEFINITION_INSIDE_PROPERTY_OF_TYPE_DOESN_T_EXIST = "Property in Schema Definition inside property of type {} doesn't exist";
107     private static final String ADD_PROPERTY_VALUE = "Add property value";
108     private static final String THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID = "The value {} of property from type {} is invalid";
109     protected IGroupTypeOperation groupTypeOperation;
110     protected InterfaceOperation interfaceOperation;
111     protected IElementOperation elementDao;
112     protected ComponentsUtils componentsUtils;
113     protected UserBusinessLogic userAdmin;
114     protected IGraphLockOperation graphLockOperation;
115     protected JanusGraphDao janusGraphDao;
116     protected JanusGraphGenericDao janusGraphGenericDao;
117     protected PropertyOperation propertyOperation;
118     protected AttributeOperation attributeOperation;
119     protected ApplicationDataTypeCache applicationDataTypeCache;
120     protected ToscaOperationFacade toscaOperationFacade;
121     protected IGroupOperation groupOperation;
122     protected IGroupInstanceOperation groupInstanceOperation;
123     protected InterfaceLifecycleOperation interfaceLifecycleTypeOperation;
124     protected PolicyTypeOperation policyTypeOperation;
125     protected ArtifactsOperations artifactToscaOperation;
126     protected UserValidations userValidations;
127     DataTypeValidatorConverter dataTypeValidatorConverter = DataTypeValidatorConverter.getInstance();
128
129     protected BaseBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
130                                 IGroupTypeOperation groupTypeOperation, InterfaceOperation interfaceOperation,
131                                 InterfaceLifecycleOperation interfaceLifecycleTypeOperation, ArtifactsOperations artifactToscaOperation) {
132         this.elementDao = elementDao;
133         this.groupOperation = groupOperation;
134         this.groupInstanceOperation = groupInstanceOperation;
135         this.groupTypeOperation = groupTypeOperation;
136         this.interfaceOperation = interfaceOperation;
137         this.interfaceLifecycleTypeOperation = interfaceLifecycleTypeOperation;
138         this.artifactToscaOperation = artifactToscaOperation;
139     }
140
141     @SafeVarargs
142     static <T extends Enum<T>> boolean enumHasValueFilter(String name, Function<String, T> enumGetter, T... enumValues) {
143         T enumFound = enumGetter.apply(name);
144         return Arrays.asList(enumValues).contains(enumFound);
145     }
146
147     @Autowired
148     public void setUserAdmin(UserBusinessLogic userAdmin) {
149         this.userAdmin = userAdmin;
150     }
151
152     @Autowired
153     public void setUserValidations(UserValidations userValidations) {
154         this.userValidations = userValidations;
155     }
156
157     @Autowired
158     public void setComponentsUtils(ComponentsUtils componentsUtils) {
159         this.componentsUtils = componentsUtils;
160     }
161
162     @Autowired
163     public void setJanusGraphDao(JanusGraphDao janusGraphDao) {
164         this.janusGraphDao = janusGraphDao;
165     }
166
167     @Autowired
168     public void setApplicationDataTypeCache(ApplicationDataTypeCache applicationDataTypeCache) {
169         this.applicationDataTypeCache = applicationDataTypeCache;
170     }
171
172     @Autowired
173     public void setJanusGraphGenericDao(JanusGraphGenericDao janusGraphGenericDao) {
174         this.janusGraphGenericDao = janusGraphGenericDao;
175     }
176
177     @Autowired
178     public void setGraphLockOperation(IGraphLockOperation graphLockOperation) {
179         this.graphLockOperation = graphLockOperation;
180     }
181
182     @Autowired
183     public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) {
184         this.toscaOperationFacade = toscaOperationFacade;
185     }
186
187     @Autowired
188     void setPolicyTypeOperation(PolicyTypeOperation policyTypeOperation) {
189         this.policyTypeOperation = policyTypeOperation;
190     }
191
192     @Autowired
193     public void setPropertyOperation(PropertyOperation propertyOperation) {
194         this.propertyOperation = propertyOperation;
195     }
196
197     @Autowired
198     public void setAttributeOperation(AttributeOperation attributeOperation) {
199         this.attributeOperation = attributeOperation;
200     }
201
202     User validateUserNotEmpty(User user, String ecompErrorContext) {
203         return userValidations.validateUserNotEmpty(user, ecompErrorContext);
204     }
205
206     protected User validateUserExists(String userId) {
207         return userValidations.validateUserExists(userId);
208     }
209
210     public User validateUserExists(User user) {
211         return userValidations.validateUserExists(user);
212     }
213
214     ActionStatus validateUserExistsActionStatus(String userId) {
215         return userValidations.validateUserExistsActionStatus(userId);
216     }
217
218     protected void validateUserRole(User user, List<Role> roles) {
219         userValidations.validateUserRole(user, roles);
220     }
221
222     protected void lockComponent(Component component, String ecompErrorContext) {
223         lockComponent(component.getUniqueId(), component, ecompErrorContext);
224     }
225
226     protected boolean isVolumeGroup(List<String> artifactsInGroup, List<ArtifactDefinition> deploymentArtifacts) {
227         for (String artifactId : artifactsInGroup) {
228             ArtifactDefinition artifactDef = ArtifactUtils.findArtifactInList(deploymentArtifacts, artifactId);
229             if (artifactDef != null && artifactDef.getArtifactType().equalsIgnoreCase(ArtifactTypeEnum.HEAT_VOL.getType())) {
230                 return true;
231             }
232         }
233         return false;
234     }
235
236     protected void lockComponent(Component component, boolean shouldLock, String ecompErrorContext) {
237         if (shouldLock) {
238             lockComponent(component.getUniqueId(), component, ecompErrorContext);
239         }
240     }
241
242     protected void lockComponent(String componentId, Component component, String ecompErrorContext) {
243         ActionStatus lock = lockElement(componentId, component, ecompErrorContext);
244         if (lock != ActionStatus.OK) {
245             logAndThrowComponentException(lock, component.getUniqueId(), component.getName());
246         }
247     }
248
249     protected void lockComponent(String componentId, Component component, boolean needLock, String ecompErrorContext) {
250         if (needLock) {
251             lockComponent(componentId, component, ecompErrorContext);
252         }
253     }
254
255     private ResponseFormat logAndThrowComponentException(ActionStatus status, String componentId, String name) {
256         log.debug(FAILED_TO_LOCK_COMPONENT_ERROR, componentId, status);
257         throw new ByActionStatusComponentException(status, name);
258     }
259
260     private ActionStatus lockElement(String componentId, Component component, String ecompErrorContext) {
261         ComponentTypeEnum componentType = component.getComponentType();
262         NodeTypeEnum nodeType = componentType.getNodeType();
263         StorageOperationStatus lockResourceStatus = graphLockOperation.lockComponent(componentId, nodeType);
264         if (lockResourceStatus == StorageOperationStatus.OK) {
265             return ActionStatus.OK;
266         } else {
267             BeEcompErrorManager.getInstance().logBeFailedLockObjectError(ecompErrorContext, nodeType.getName(), componentId);
268             return componentsUtils.convertFromStorageResponse(lockResourceStatus, componentType);
269         }
270     }
271
272     protected void unlockComponent(boolean failed, Component component, boolean inTransaction) {
273         if (component != null) {
274             ComponentTypeEnum componentType = component.getComponentType();
275             NodeTypeEnum nodeType = componentType.getNodeType();
276             if (!inTransaction) {
277                 if (failed) {
278                     janusGraphDao.rollback();
279                 } else {
280                     janusGraphDao.commit();
281                 }
282             }
283             // unlock resource
284             graphLockOperation.unlockComponent(component.getUniqueId(), nodeType);
285         } else {
286             log.debug("component is NULL");
287         }
288     }
289
290     protected void unlockComponent(boolean failed, Component component) {
291         unlockComponent(failed, component, false);
292     }
293
294     void unlockComponentById(boolean failed, String componentId) {
295         Either<Component, StorageOperationStatus> component = toscaOperationFacade.getToscaElement(componentId);
296         if (component.isLeft()) {
297             unlockComponent(failed, component.left().value(), false);
298         }
299     }
300
301     <T> Boolean validateJsonBody(T bodyObject, Class<T> clazz) {
302         if (bodyObject == null) {
303             log.debug("Invalid JSON received for object of type {}", clazz.getSimpleName());
304             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
305         } else {
306             return true;
307         }
308     }
309
310     ComponentTypeEnum validateComponentType(String componentType) {
311         ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
312         if (componentTypeEnum == null) {
313             log.debug("Invalid component type {}", componentType);
314             throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR, componentType);
315         } else {
316             return componentTypeEnum;
317         }
318     }
319
320     Component validateComponentExists(String componentId, ComponentTypeEnum componentType, ComponentParametersView filter) {
321         Either<Component, StorageOperationStatus> toscaElement = toscaOperationFacade
322             .getToscaElement(componentId, filter == null ? new ComponentParametersView() : filter);
323         if (toscaElement.isRight()) {
324             handleGetComponentError(componentId, componentType, toscaElement.right().value());
325         }
326         return validateComponentType(toscaElement.left().value(), componentType);
327     }
328
329     private Component validateComponentType(Component cmpt, ComponentTypeEnum componentType) {
330         if (componentType != cmpt.getComponentType()) {
331             log.debug("component {} is not of requested type {}", cmpt.getUniqueId(), componentType);
332             throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND, componentType));
333         }
334         return cmpt;
335     }
336
337     <T extends PropertyDataDefinition> String updateInputPropertyObjectValue(T property) {
338         String propertyType = property.getType();
339         String innerType = getInnerType(property);
340         // Specific Update Logic
341         Either<Object, Boolean> isValid = propertyOperation
342             .validateAndUpdatePropertyValue(propertyType, property.getValue(), true, innerType,
343                 componentsUtils.getAllDataTypes(applicationDataTypeCache, property.getModel()));
344         String newValue = property.getValue();
345         if (isValid.isRight()) {
346             Boolean res = isValid.right().value();
347             if (Boolean.FALSE.equals(res)) {
348                 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(
349                     DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)));
350             }
351         } else {
352             Object object = isValid.left().value();
353             if (object != null) {
354                 newValue = object.toString();
355             }
356         }
357         return newValue;
358     }
359
360     <T extends PropertyDataDefinition> String getInnerType(T property) {
361         ToscaPropertyType type = ToscaPropertyType.isValidType(property.getType());
362         log.debug("#getInnerType - The type of the property {} is {}", property.getUniqueId(), property.getType());
363         String innerType = null;
364         if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
365             if (property.getSchema() == null) {
366                 log.debug(SCHEMA_DOESN_T_EXISTS_FOR_PROPERTY_OF_TYPE, type);
367                 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE));
368             }
369             PropertyDataDefinition innerProperty = property.getSchema().getProperty();
370             if (innerProperty == null) {
371                 log.debug(PROPERTY_IN_SCHEMA_DEFINITION_INSIDE_PROPERTY_OF_TYPE_DOESN_T_EXIST, type);
372                 throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE));
373             }
374             innerType = innerProperty.getType();
375         }
376         return innerType;
377     }
378
379     public void validateCanWorkOnComponent(Component component, String userId) {
380         ActionStatus actionStatus = ActionStatus.RESTRICTED_OPERATION;
381         // verify resource is not archived
382         if (Boolean.TRUE.equals(component.isArchived())) {
383             actionStatus = ActionStatus.COMPONENT_IS_ARCHIVED;
384             throw new ByActionStatusComponentException(actionStatus, component.getName());
385         }
386         if (component.getLifecycleState() != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT) {
387             log.debug("Component {} is not checked-out", component.getName());
388             throw new ByActionStatusComponentException(actionStatus);
389         }
390         // verify userId is not null
391         if (userId == null) {
392             log.debug("Current user userId is null");
393             throw new ByActionStatusComponentException(actionStatus);
394         }
395         // verify component last update user is the current user
396         String lastUpdaterUserId = component.getLastUpdaterUserId();
397         if (!userId.equals(lastUpdaterUserId)) {
398             log.debug("Current user is not last updater, last updater userId: {}, current user userId: {}", lastUpdaterUserId, userId);
399             throw new ByActionStatusComponentException(actionStatus);
400         }
401         // verify resource is not deleted
402         if (Boolean.TRUE.equals(component.getIsDeleted())) {
403             log.debug("Component {} is marked as deleted", component.getUniqueId());
404             throw new ByActionStatusComponentException(actionStatus);
405         }
406     }
407
408     ComponentTypeEnum getComponentTypeByParentComponentType(ComponentTypeEnum parentComponentType) {
409         switch (parentComponentType) {
410             case SERVICE:
411             case RESOURCE:
412                 return ComponentTypeEnum.RESOURCE;
413             case PRODUCT:
414                 return ComponentTypeEnum.SERVICE;
415             default:
416                 break;
417         }
418         return null;
419     }
420
421     Either<Boolean, ResponseFormat> validatePropertyDefaultValue(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
422         String type;
423         String innerType = null;
424         if (!propertyOperation.isPropertyTypeValid(property, null)) {
425             log.info("Invalid type for property '{}' type '{}'", property.getName(), property.getType());
426             ResponseFormat responseFormat = componentsUtils
427                 .getResponseFormat(ActionStatus.INVALID_PROPERTY_TYPE, property.getType(), property.getName());
428             return Either.right(responseFormat);
429         }
430         type = property.getType();
431         if (type.equals(ToscaPropertyType.LIST.getType()) || type.equals(ToscaPropertyType.MAP.getType())) {
432             ImmutablePair<String, Boolean> propertyInnerTypeValid = propertyOperation.isPropertyInnerTypeValid(property, dataTypes);
433             innerType = propertyInnerTypeValid.getLeft();
434             if (Boolean.FALSE.equals(propertyInnerTypeValid.getRight())) {
435                 log.info("Invalid inner type for property '{}' type '{}', dataTypeCount '{}'", property.getName(), property.getType(),
436                     dataTypes.size());
437                 ResponseFormat responseFormat = componentsUtils
438                     .getResponseFormat(ActionStatus.INVALID_PROPERTY_INNER_TYPE, innerType, property.getName());
439                 return Either.right(responseFormat);
440             }
441         }
442         if (!propertyOperation.isPropertyDefaultValueValid(property, dataTypes)) {
443             log.info("Invalid default value for property '{}' type '{}'", property.getName(), property.getType());
444             ResponseFormat responseFormat;
445             if (type.equals(ToscaPropertyType.LIST.getType()) || type.equals(ToscaPropertyType.MAP.getType())) {
446                 responseFormat = componentsUtils
447                     .getResponseFormat(ActionStatus.INVALID_COMPLEX_DEFAULT_VALUE, property.getName(), type, innerType, property.getDefaultValue());
448             } else {
449                 responseFormat = componentsUtils
450                     .getResponseFormat(ActionStatus.INVALID_DEFAULT_VALUE, property.getName(), type, property.getDefaultValue());
451             }
452             return Either.right(responseFormat);
453         }
454         return Either.left(true);
455     }
456
457     void validateComponentTypeEnum(ComponentTypeEnum componentTypeEnum, String errorContext, Wrapper<ResponseFormat> errorWrapper) {
458         if (componentTypeEnum == null) {
459             BeEcompErrorManager.getInstance().logInvalidInputError(errorContext, "invalid component type", ErrorSeverity.INFO);
460             errorWrapper.setInnerElement(componentsUtils.getResponseFormat(ActionStatus.NOT_ALLOWED));
461         }
462     }
463
464     protected void validateCanWorkOnComponent(String componentId, ComponentTypeEnum componentTypeEnum, String userId,
465                                               Wrapper<ResponseFormat> errorWrapper) {
466         if (!ComponentValidationUtils.canWorkOnComponent(componentId, toscaOperationFacade, userId)) {
467             log.info("Restricted operation for user {} on {} {}", userId, componentTypeEnum.getValue(), componentId);
468             errorWrapper.setInnerElement(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
469         }
470     }
471
472     void validateComponentLock(String componentId, ComponentTypeEnum componentTypeEnum, Wrapper<ResponseFormat> errorWrapper) {
473         StorageOperationStatus lockStatus = graphLockOperation.lockComponent(componentId, componentTypeEnum.getNodeType());
474         if (lockStatus != StorageOperationStatus.OK) {
475             log.debug("Failed to lock {} {}", componentTypeEnum.getValue(), componentId);
476             errorWrapper.setInnerElement(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(lockStatus)));
477         }
478     }
479
480     protected ToscaPropertyType getType(String propertyType) {
481         return ToscaPropertyType.isValidType(propertyType);
482     }
483
484     void commitOrRollback(Either<?, ResponseFormat> result) {
485         if (result == null || result.isRight()) {
486             log.warn("operation failed. do rollback");
487             janusGraphDao.rollback();
488         } else {
489             log.debug("operation success. do commit");
490             janusGraphDao.commit();
491         }
492     }
493
494     protected Either<Boolean, ResponseFormat> lockComponentByName(String name, Component component, String ecompErrorContext) {
495         ComponentTypeEnum componentType = component.getComponentType();
496         NodeTypeEnum nodeType = componentType.getNodeType();
497         StorageOperationStatus lockResourceStatus = graphLockOperation.lockComponentByName(name, nodeType);
498         if (lockResourceStatus == StorageOperationStatus.OK) {
499             return Either.left(true);
500         } else {
501             BeEcompErrorManager.getInstance().logBeFailedLockObjectError(ecompErrorContext, nodeType.getName(), name);
502             ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(lockResourceStatus, componentType);
503             ResponseFormat responseFormat = componentsUtils.getResponseFormat(actionStatus, component.getName());
504             log.debug(FAILED_TO_LOCK_COMPONENT_ERROR, name, actionStatus);
505             return Either.right(responseFormat);
506         }
507     }
508
509     protected Component validateComponentExistsByFilter(String componentId, ComponentTypeEnum componentType,
510                                                         ComponentParametersView componentParametersView) {
511         return toscaOperationFacade.getToscaElement(componentId, componentParametersView).left()
512             .on(err -> handleGetComponentError(componentId, componentType, err));
513     }
514
515     private Component handleGetComponentError(String componentId, ComponentTypeEnum componentType, StorageOperationStatus getComponentError) {
516         ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getComponentError, componentType);
517         log.debug("error fetching component with id {}. error status: {}", componentId, getComponentError);
518         throw new ByActionStatusComponentException(actionStatus, componentId);
519     }
520
521     String validatePropValueBeforeCreate(IPropertyInputCommon property, String value, boolean isValidate,
522                                          Map<String, DataTypeDefinition> allDataTypes) {
523         String propertyType = property.getType();
524         String updatedInnerType = updateInnerType(property);
525         Either<Object, Boolean> isValid = validateAndUpdatePropertyValue(propertyType, value, isValidate, updatedInnerType, allDataTypes);
526         String newValue = value;
527         if (isValid.isRight()) {
528             Boolean res = isValid.right().value();
529             if (Boolean.FALSE.equals(res)) {
530                 throw new StorageException(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT));
531             }
532         } else {
533             Object object = isValid.left().value();
534             if (object != null) {
535                 newValue = object.toString();
536             }
537         }
538         ImmutablePair<String, Boolean> pair = validateAndUpdateRules(propertyType, property.getRules(), updatedInnerType, allDataTypes, isValidate);
539         log.trace("After validateAndUpdateRules. pair = {}", pair);
540         if (Boolean.FALSE.equals(pair.getRight())) {
541             BeEcompErrorManager.getInstance().logBeInvalidValueError(ADD_PROPERTY_VALUE, pair.getLeft(), property.getName(), propertyType);
542             throw new StorageException(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT));
543         }
544         return newValue;
545     }
546
547     private String updateInnerType(IPropertyInputCommon property) {
548         ToscaPropertyType type = ToscaPropertyType.isValidType(property.getType());
549         if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
550             SchemaDefinition def = property.getSchema();
551             if (def == null) {
552                 log.debug(SCHEMA_DOESN_T_EXISTS_FOR_PROPERTY_OF_TYPE, type);
553                 failOnIllegalArgument();
554             }
555             PropertyDataDefinition propDef = def.getProperty();
556             if (propDef == null) {
557                 log.debug(PROPERTY_IN_SCHEMA_DEFINITION_INSIDE_PROPERTY_OF_TYPE_DOESN_T_EXIST, type);
558                 failOnIllegalArgument();
559             }
560             return propDef.getType();
561         }
562         return null;
563     }
564
565     private void failOnIllegalArgument() {
566         throw new ByActionStatusComponentException(componentsUtils
567             .convertFromStorageResponse(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.ILLEGAL_ARGUMENT)));
568     }
569
570     public Either<Object, Boolean> validateAndUpdatePropertyValue(String propertyType, String value, boolean isValidate, String innerType,
571                                                                   Map<String, DataTypeDefinition> dataTypes) {
572         log.trace("Going to validate property value and its type. type = {}, value = {}", propertyType, value);
573         ToscaPropertyType type = getType(propertyType);
574         if (isValidate) {
575             if (type == null) {
576                 DataTypeDefinition dataTypeDefinition = dataTypes.get(propertyType);
577                 ImmutablePair<JsonElement, Boolean> validateResult = dataTypeValidatorConverter
578                     .validateAndUpdate(value, dataTypeDefinition, dataTypes);
579                 if (Boolean.FALSE.equals(validateResult.right)) {
580                     log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, propertyType);
581                     return Either.right(false);
582                 }
583                 JsonElement jsonElement = validateResult.left;
584                 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
585                 return Either.left(valueFromJsonElement);
586             }
587             log.trace("before validating property type {}", propertyType);
588             boolean isValidProperty = isValidValue(type, value, innerType, dataTypes);
589             if (!isValidProperty) {
590                 log.debug(THE_VALUE_OF_PROPERTY_FROM_TYPE_IS_INVALID, value, type);
591                 return Either.right(false);
592             }
593         }
594         Object convertedValue = value;
595         if (!isEmptyValue(value) && isValidate) {
596             PropertyValueConverter converter = type.getConverter();
597             convertedValue = converter.convert(value, innerType, dataTypes);
598         }
599         return Either.left(convertedValue);
600     }
601
602     private ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType,
603                                                                   Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
604         if (rules == null || rules.isEmpty()) {
605             return ImmutablePair.of(null, true);
606         }
607         for (PropertyRule rule : rules) {
608             String value = rule.getValue();
609             Either<Object, Boolean> updateResult = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, dataTypes);
610             if (updateResult.isRight()) {
611                 Boolean status = updateResult.right().value();
612                 if (Boolean.FALSE.equals(status)) {
613                     return ImmutablePair.of(value, status);
614                 }
615             } else {
616                 String newValue = null;
617                 Object object = updateResult.left().value();
618                 if (object != null) {
619                     newValue = object.toString();
620                 }
621                 rule.setValue(newValue);
622             }
623         }
624         return ImmutablePair.of(null, true);
625     }
626
627     protected boolean isValidValue(ToscaPropertyType type, String value, String innerType, Map<String, DataTypeDefinition> dataTypes) {
628         if (isEmptyValue(value)) {
629             return true;
630         }
631         PropertyTypeValidator validator = type.getValidator();
632         return validator.isValid(value, innerType, dataTypes);
633     }
634
635     public boolean isEmptyValue(String value) {
636         return value == null;
637     }
638
639     protected String getValueFromJsonElement(JsonElement jsonElement) {
640         if (jsonElement == null || jsonElement.isJsonNull()) {
641             return EMPTY_VALUE;
642         }
643         if (jsonElement.toString().isEmpty()) {
644             return "";
645         }
646         return jsonElement.toString();
647     }
648
649     protected void rollbackWithException(ActionStatus actionStatus, String... params) {
650         janusGraphDao.rollback();
651         throw new ByActionStatusComponentException(actionStatus, params);
652     }
653
654     public <T extends ToscaDataDefinition> Either<List<T>, ResponseFormat> declareProperties(final String userId, final String componentId,
655                                                                                              final ComponentTypeEnum componentTypeEnum,
656                                                                                              final ComponentInstInputsMap componentInstInputsMap) {
657         return Either.left(new ArrayList<>());
658     }
659
660     public <T extends ToscaDataDefinition> Either<List<T>, ResponseFormat> declareAttributes(final String userId, final String componentId,
661                                                                                              final ComponentTypeEnum componentTypeEnum,
662                                                                                              final ComponentInstOutputsMap componentInstOutputsMap) {
663         return Either.left(new ArrayList<>());
664     }
665
666     public <T extends PropertyDataDefinition> List<PropertyConstraint> setInputConstraint(T inputDefinition) {
667         if (StringUtils.isNotBlank(inputDefinition.getParentPropertyType()) && StringUtils.isNotBlank(inputDefinition.getSubPropertyInputPath())) {
668             return setConstraint(inputDefinition);
669         }
670         return Collections.emptyList();
671     }
672
673     private <T extends PropertyDataDefinition> List<PropertyConstraint> setConstraint(T inputDefinition) {
674         List<PropertyConstraint> constraints = new ArrayList<>();
675         String[] inputPathArr = inputDefinition.getSubPropertyInputPath().split("#");
676         if (inputPathArr.length > 1) {
677             inputPathArr = ArrayUtils.remove(inputPathArr, 0);
678         }
679         final Map<String, DataTypeDefinition> dataTypeDefinitionMap =
680             componentsUtils.getAllDataTypes(applicationDataTypeCache, inputDefinition.getModel());
681         String propertyType = inputDefinition.getParentPropertyType();
682         for (String anInputPathArr : inputPathArr) {
683             if (ToscaType.isPrimitiveType(propertyType)) {
684                 constraints.addAll(dataTypeDefinitionMap.get(propertyType).getConstraints());
685             } else if (!ToscaType.isCollectionType(propertyType)) {
686                 propertyType = setConstraintForComplexType(dataTypeDefinitionMap, propertyType, anInputPathArr, constraints);
687             }
688         }
689         return constraints;
690     }
691
692     private String setConstraintForComplexType(Map<String, DataTypeDefinition> dataTypeDefinitionMap, String propertyType, String anInputPathArr,
693                                                List<PropertyConstraint> constraints) {
694         String type = null;
695         List<PropertyDefinition> propertyDefinitions = dataTypeDefinitionMap.get(propertyType).getProperties();
696         for (PropertyDefinition propertyDefinition : propertyDefinitions) {
697             if (propertyDefinition.getName().equals(anInputPathArr)) {
698                 if (ToscaType.isPrimitiveType(propertyDefinition.getType())) {
699                     constraints.addAll(propertyDefinition.safeGetConstraints());
700                 } else {
701                     type = propertyDefinition.getType();
702                 }
703                 break;
704             }
705         }
706         return type;
707     }
708
709     protected void unlockRollbackWithException(Component component, RuntimeException e) {
710         janusGraphDao.rollback();
711         graphLockOperation.unlockComponent(component.getUniqueId(), component.getComponentType().getNodeType());
712         throw e;
713     }
714
715     protected void unlockWithCommit(Component component) {
716         ComponentTypeEnum componentType = component.getComponentType();
717         NodeTypeEnum nodeType = componentType.getNodeType();
718         janusGraphDao.commit();
719         graphLockOperation.unlockComponent(component.getUniqueId(), nodeType);
720     }
721
722     protected ComponentInstance componentInstanceException(StorageOperationStatus storageOperationStatus) {
723         throw new StorageException(storageOperationStatus);
724     }
725
726     protected Component componentException(StorageOperationStatus storageOperationStatus) {
727         throw new StorageException(storageOperationStatus);
728     }
729
730     protected PolicyDefinition componentExceptionPolicyDefinition(ResponseFormat responseFormat) {
731         throw new ByResponseFormatComponentException(responseFormat);
732     }
733
734     protected List<ComponentInstanceProperty> componentInstancePropertyListException(StorageOperationStatus storageOperationStatus) {
735         throw new StorageException(storageOperationStatus);
736     }
737
738     protected Component getComponent(final String componentId) throws BusinessLogicException {
739         final Either<Component, StorageOperationStatus> result = toscaOperationFacade.getToscaElement(componentId);
740         if (result.isRight()) {
741             final StorageOperationStatus errorStatus = result.right().value();
742             log.error(BUSINESS_PROCESS_ERROR, this.getClass().getName(), "Failed to fetch component information by component id, error {}",
743                 errorStatus);
744             throw new BusinessLogicException(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus)));
745         }
746         return result.left().value();
747     }
748
749     public String getComponentModelByComponentId(final String componentId) throws BusinessLogicException {
750         return getComponent(componentId).getModel();
751     }
752 }