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