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