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