2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.components.impl;
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;
71 import java.util.ArrayList;
72 import java.util.Arrays;
73 import java.util.List;
75 import java.util.function.Function;
77 import static org.apache.commons.collections.CollectionUtils.isEmpty;
79 public abstract class BaseBusinessLogic {
81 private static final Logger log = LoggerFactory.getLogger(BaseBusinessLogic.class);
83 private static final String EMPTY_VALUE = null;
85 protected ComponentsUtils componentsUtils;
88 protected IUserBusinessLogic userAdmin;
91 protected IGraphLockOperation graphLockOperation;
94 protected TitanDao titanDao;
97 protected TitanGenericDao titanGenericDao;
100 protected IElementOperation elementDao;
103 protected IGroupOperation groupOperation;
106 protected IGroupInstanceOperation groupInstanceOperation;
109 protected IGroupTypeOperation groupTypeOperation;
112 protected GroupBusinessLogic groupBusinessLogic;
115 protected PolicyTypeOperation policyTypeOperation;
117 @javax.annotation.Resource
118 protected ArtifactsOperations artifactToscaOperation;
121 protected PropertyOperation propertyOperation;
124 protected ApplicationDataTypeCache applicationDataTypeCache;
127 protected ToscaOperationFacade toscaOperationFacade;
130 protected ApplicationDataTypeCache dataTypeCache;
133 protected ForwardingPathOperation forwardingPathOperation;
135 @javax.annotation.Resource
136 private UserValidations userValidations;
138 protected DataTypeValidatorConverter dataTypeValidatorConverter = DataTypeValidatorConverter.getInstance();
141 public void setUserAdmin(UserBusinessLogic userAdmin) {
142 this.userAdmin = userAdmin;
145 public void setUserValidations(UserValidations userValidations) {
146 this.userValidations = userValidations;
149 public void setComponentsUtils(ComponentsUtils componentsUtils) {
150 this.componentsUtils = componentsUtils;
153 public void setGraphLockOperation(IGraphLockOperation graphLockOperation) {
154 this.graphLockOperation = graphLockOperation;
157 public void setToscaOperationFacade(ToscaOperationFacade toscaOperationFacade) {
158 this.toscaOperationFacade = toscaOperationFacade;
161 public void setForwardingPathOperation(ForwardingPathOperation forwardingPathOperation){
162 this.forwardingPathOperation = forwardingPathOperation;
165 public void setPolicyTypeOperation(PolicyTypeOperation policyTypeOperation) {
166 this.policyTypeOperation = policyTypeOperation;
170 public void setDataTypeCache(ApplicationDataTypeCache dataTypeCache) {
171 this.dataTypeCache = dataTypeCache;
174 public void setPropertyOperation(PropertyOperation propertyOperation) {
175 this.propertyOperation = propertyOperation;
178 protected Either<User, ResponseFormat> validateUserNotEmpty(User user, String ecompErrorContext) {
179 return userValidations.validateUserNotEmpty(user, ecompErrorContext);
182 protected Either<User, ResponseFormat> validateUserExists(User user, String ecompErrorContext, boolean inTransaction) {
183 return userValidations.validateUserExists(user.getUserId(), ecompErrorContext, inTransaction);
186 protected void validateUserExist(String userId, String ecompErrorContext, Wrapper<ResponseFormat> errorWrapper) {
187 userValidations.validateUserExist(userId, ecompErrorContext, errorWrapper);
190 public Either<User, ActionStatus> validateUserExistsActionStatus(String userId, String ecompErrorContext) {
191 return userValidations.validateUserExistsActionStatus(userId, ecompErrorContext);
194 public Either<User, ResponseFormat> validateUserExists(String userId, String ecompErrorContext, boolean inTransaction) {
195 return userValidations.validateUserExists(userId, ecompErrorContext, inTransaction);
198 protected Either<Boolean, ResponseFormat> validateUserRole(User user, List<Role> roles) {
199 return userValidations.validateUserRole(user, roles);
202 protected Either<Boolean, ResponseFormat> lockComponent(Component component, String ecompErrorContext) {
203 return lockComponent(component.getUniqueId(), component, ecompErrorContext);
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);
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);
216 if (lockResourceStatus.equals(StorageOperationStatus.OK)) {
217 return Either.left(true);
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);
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()) {
238 graphLockOperation.unlockComponent(component.getUniqueId(), nodeType);
241 protected void unlockComponent(Either<?, ?> either, Component component) {
242 unlockComponent(either, component, false);
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);
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));
256 return Either.left(true);
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));
266 return Either.left(componentTypeEnum);
270 protected Either<Component, ResponseFormat> validateComponentExists(String componentId, ComponentTypeEnum componentType, ComponentParametersView filter) {
271 if (filter == null) {
272 filter = new ComponentParametersView();
274 return toscaOperationFacade.getToscaElement(componentId, filter)
276 .map(err -> handleGetComponentError(componentId, componentType, err))
278 .bind(cmpt -> validateComponentType(cmpt, componentType));
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));
287 return Either.left(cmpt);
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))));
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);
303 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
304 SchemaDefinition def = property.getSchema();
306 log.debug("Schema doesn't exists for property of type {}", type);
307 return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE)));
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)));
314 innerType = propDef.getType();
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))));
325 Object object = isValid.left().value();
326 if (object != null) {
327 newValue = object.toString();
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))));
337 return Either.left(newValue);
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());
347 // verify userId is not null
348 if (userId == null) {
349 log.debug("Current user userId is null");
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);
360 // verify resource is not deleted
361 if (Boolean.TRUE.equals(component.getIsDeleted())) {
362 log.debug("Component {} is marked as deleted", component.getUniqueId());
366 return Either.left(true);
369 public ComponentTypeEnum getComponentTypeByParentComponentType(ComponentTypeEnum parentComponentType) {
370 switch (parentComponentType) {
372 return ComponentTypeEnum.RESOURCE;
374 return ComponentTypeEnum.RESOURCE;
376 return ComponentTypeEnum.SERVICE;
384 public void setTitanGenericDao(TitanDao titanDao) {
385 this.titanDao = titanDao;
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));
396 BeEcompErrorManager.getInstance().logInternalFlowError("FetchDataTypes", "Failed to fetch data types", ErrorSeverity.ERROR);
397 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
400 return Either.left(allDataTypes.left().value());
403 protected Either<Boolean, ResponseFormat> validatePropertyDefaultValue(IComplexDefaultValue property, Map<String, DataTypeDefinition> dataTypes) {
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);
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);
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());
427 responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_DEFAULT_VALUE, property.getName(), type, property.getDefaultValue());
429 return Either.right(responseFormat);
432 return Either.left(true);
436 protected void handleDefaultValue(IComplexDefaultValue newAttributeDef, Map<String, DataTypeDefinition> dataTypes) {
438 ToscaPropertyType type = ToscaPropertyType.isValidType(newAttributeDef.getType());
439 PropertyValueConverter converter = type.getConverter();
441 String innerType = null;
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();
451 String convertedValue = null;
452 if (newAttributeDef.getDefaultValue() != null) {
453 convertedValue = converter.convert(newAttributeDef.getDefaultValue(), innerType, dataTypes);
454 newAttributeDef.setDefaultValue(convertedValue);
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));
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));
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)));
484 protected ToscaPropertyType getType(String propertyType) {
485 return ToscaPropertyType.isValidType(propertyType);
488 protected void commitOrRollback(Either<? extends Object, ResponseFormat> result) {
489 if (result == null || result.isRight()) {
490 log.warn("operation failed. do rollback");
493 log.debug("operation success. do commit");
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);
503 if (lockResourceStatus.equals(StorageOperationStatus.OK)) {
504 return Either.left(true);
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);
514 protected Either<Component, ResponseFormat> validateComponentExistsByFilter(String componentId, ComponentTypeEnum componentType, ComponentParametersView componentParametersView) {
515 return toscaOperationFacade.getToscaElement(componentId, componentParametersView)
517 .map(err -> handleGetComponentError(componentId, componentType, err));
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;
528 protected Either<GroupProperty, ResponseFormat> validateFreeText(GroupProperty groupPropertyToUpdate) {
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()));
541 ret = Either.left(groupPropertyToUpdate);
545 ret = Either.left(groupPropertyToUpdate);
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);
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);
561 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
562 SchemaDefinition def = property.getSchema();
564 log.debug("Schema doesn't exists for property of type {}", type);
565 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT));
567 PropertyDataDefinition propDef = def.getProperty();
568 if (propDef == null) {
569 log.debug("Property in Schema Definition inside property of type {} doesn't exist", type);
571 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT));
573 innerType = propDef.getType();
576 Either<Object, Boolean> isValid = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, allDataTypes);
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));
585 Object object = isValid.left().value();
586 if (object != null) {
587 newValue = object.toString();
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));
598 return Either.left(newValue);
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);
605 if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
606 SchemaDefinition def = property.getSchema();
608 log.debug("Schema doesn't exists for property of type {}", type);
609 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT));
611 PropertyDataDefinition propDef = def.getProperty();
612 if (propDef == null) {
613 log.debug("Property in Schema Definition inside property of type {} doesn't exist", type);
615 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(TitanOperationStatus.ILLEGAL_ARGUMENT));
617 innerType = propDef.getType();
620 Either<Object, Boolean> isValid = validateAndUpdatePropertyValue(propertyType, value, isValidate, innerType, allDataTypes);
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));
629 Object object = isValid.left().value();
630 if (object != null) {
631 newValue = object.toString();
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));
642 return Either.left(newValue);
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);
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);
658 JsonElement jsonElement = validateResult.left;
659 String valueFromJsonElement = getValueFromJsonElement(jsonElement);
660 return Either.left(valueFromJsonElement);
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);
669 Object convertedValue = value;
670 if (!isEmptyValue(value) && isValidate) {
671 PropertyValueConverter converter = type.getConverter();
672 convertedValue = converter.convert(value, innerType, dataTypes);
674 return Either.left(convertedValue);
677 public ImmutablePair<String, Boolean> validateAndUpdateRules(String propertyType, List<PropertyRule> rules, String innerType, Map<String, DataTypeDefinition> dataTypes, boolean isValidate) {
679 if (rules == null || rules.isEmpty()) {
680 return ImmutablePair.of(null, true);
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);
692 String newValue = null;
693 Object object = updateResult.left().value();
694 if (object != null) {
695 newValue = object.toString();
697 rule.setValue(newValue);
701 return ImmutablePair.of(null, true);
704 protected boolean isValidValue(ToscaPropertyType type, String value, String innerType, Map<String, DataTypeDefinition> dataTypes) {
705 if (isEmptyValue(value)) {
709 PropertyTypeValidator validator = type.getValidator();
711 return validator.isValid(value, innerType, dataTypes);
714 public boolean isEmptyValue(String value) {
721 public boolean isNullParam(String value) {
728 public void addRulesToNewPropertyValue(PropertyValueData propertyValueData, ComponentInstanceProperty resourceInstanceProperty, String resourceInstanceId) {
730 List<PropertyRule> rules = resourceInstanceProperty.getRules();
732 PropertyRule propertyRule = buildRuleFromPath(propertyValueData, resourceInstanceProperty, resourceInstanceId);
733 rules = new ArrayList<>();
734 rules.add(propertyRule);
736 rules = sortRules(rules);
739 propertyValueData.setRules(rules);
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
746 // Update could be done on one level only, thus we can use this
747 // operation to avoid migration.
749 path = new ArrayList<>();
750 path.add(resourceInstanceId);
752 PropertyRule propertyRule = new PropertyRule();
753 propertyRule.setRule(path);
754 propertyRule.setValue(propertyValueData.getValue());
758 private List<PropertyRule> sortRules(List<PropertyRule> rules) {
760 // TODO: sort the rules by size and binary representation.
761 // (x, y, .+) --> 110 6 priority 1
762 // (x, .+, z) --> 101 5 priority 2
767 protected String getValueFromJsonElement(JsonElement jsonElement) {
770 if (jsonElement == null || jsonElement.isJsonNull()) {
773 if (jsonElement.toString().isEmpty()) {
776 value = jsonElement.toString();