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