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