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