From 6896c1b309aaa50dca820169b9f1ae3f8af84294 Mon Sep 17 00:00:00 2001 From: siddharth0905 Date: Wed, 10 Apr 2019 17:49:51 +0530 Subject: Apply Valid Value Constraints validation Apply Valid Value Constraints validation for FE and BE in Property Assignment, Input, Service Consumption screen Change-Id: I01c7523bad702f003cd52fd88bc69fe950b2b4f3 Issue-ID: SDC-2224 Signed-off-by: siddharth0905 --- .../sdc/be/components/impl/BaseBusinessLogic.java | 91 ++- .../be/components/impl/ComponentBusinessLogic.java | 40 +- .../impl/ComponentInstanceBusinessLogic.java | 85 ++- .../be/components/impl/InputsBusinessLogic.java | 58 +- .../impl/InterfaceOperationBusinessLogic.java | 21 + .../be/components/impl/ResourceBusinessLogic.java | 107 ++-- .../be/components/impl/ServiceBusinessLogic.java | 108 +++- .../property/DefaultPropertyDeclarator.java | 11 +- .../PropertyValueConstraintValidationUtil.java | 374 +++++++++++ .../sdc/be/servlets/ComponentPropertyServlet.java | 38 +- .../sdc/be/servlets/ServiceConsumptionServlet.java | 87 +-- .../main/resources/config/error-configuration.yaml | 6 + .../PropertyValueConstraintValidationUtilTest.java | 317 ++++++++++ .../src/test/resources/csars/with_groups.csar | Bin 65804 -> 65799 bytes .../resources/types/datatypes/constraintTest.json | 405 ++++++++++++ .../org/openecomp/sdc/be/dao/api/ActionStatus.java | 3 +- .../org/openecomp/sdc/be/model/OperationInput.java | 36 ++ .../openecomp/sdc/be/model/PropertyConstraint.java | 3 + .../jsontitan/operations/ToscaOperationFacade.java | 2 +- .../openecomp/sdc/be/model/tosca/ToscaType.java | 219 +++++-- .../constraints/AbstractPropertyConstraint.java | 24 + .../be/model/tosca/constraints/ConstraintType.java | 12 +- .../be/model/tosca/constraints/ConstraintUtil.java | 32 +- .../model/tosca/constraints/EqualConstraint.java | 60 +- .../constraints/GreaterOrEqualConstraint.java | 6 + .../tosca/constraints/GreaterThanConstraint.java | 11 +- .../model/tosca/constraints/InRangeConstraint.java | 11 +- .../model/tosca/constraints/LengthConstraint.java | 33 +- .../tosca/constraints/LessOrEqualConstraint.java | 6 +- .../tosca/constraints/LessThanConstraint.java | 5 + .../tosca/constraints/MaxLengthConstraint.java | 38 +- .../tosca/constraints/MinLengthConstraint.java | 31 +- .../model/tosca/constraints/PatternConstraint.java | 11 +- .../tosca/constraints/ValidValuesConstraint.java | 12 +- .../models/properties-inputs/property-be-model.ts | 9 +- catalog-ui/src/app/models/properties.ts | 3 - .../logic/inputs-table/inputs-table.component.html | 1 + .../dynamic-property.component.html | 1 + .../service-consumption.component.ts | 2 + .../dynamic-element/dynamic-element.component.ts | 28 +- .../interface-operation.page.component.ts | 2 +- .../properties-assignment.page.component.ts | 7 +- .../property-creator/property-creator.component.ts | 3 +- .../service-consumption-editor.component.html | 1 + .../component-services/component.service.ts | 4 + .../elements/OperationInputDefinition.java | 7 + .../datatypes/elements/PropertyDataDefinition.java | 24 +- .../java/org/openecomp/sdc/ci/tests/api/Urls.java | 1 + .../sdc/ci/tests/datatypes/PropertyReqDetails.java | 53 +- .../ci/tests/execute/inputs/InputsApiTests.java | 230 +++++-- .../tests/execute/property/PropertyApisTest.java | 175 +++--- .../sdc/ci/tests/utils/rest/InputsRestUtils.java | 71 ++- .../sdc/ci/tests/utils/rest/PropertyRestUtils.java | 681 +++++++++++---------- 53 files changed, 2827 insertions(+), 779 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/PropertyValueConstraintValidationUtil.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/datamodel/utils/PropertyValueConstraintValidationUtilTest.java create mode 100644 catalog-be/src/test/resources/types/datatypes/constraintTest.json create mode 100644 catalog-model/src/main/java/org/openecomp/sdc/be/model/OperationInput.java diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java index 8ee1864862..65f1e4981a 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/BaseBusinessLogic.java @@ -21,7 +21,17 @@ package org.openecomp.sdc.be.components.impl; import com.google.gson.JsonElement; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + import fj.data.Either; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.validation.UserValidations; @@ -37,19 +47,33 @@ import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; -import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.IComplexDefaultValue; +import org.openecomp.sdc.be.model.IPropertyInputCommon; +import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.PropertyConstraint; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.jsontitan.operations.ArtifactsOperations; import org.openecomp.sdc.be.model.jsontitan.operations.InterfaceOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.operations.StorageException; -import org.openecomp.sdc.be.model.operations.api.*; +import org.openecomp.sdc.be.model.operations.api.IElementOperation; +import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation; +import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation; +import org.openecomp.sdc.be.model.operations.api.IGroupOperation; +import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; import org.openecomp.sdc.be.model.operations.impl.PolicyTypeOperation; import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; +import org.openecomp.sdc.be.model.tosca.ToscaType; import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter; import org.openecomp.sdc.be.model.tosca.validators.DataTypeValidatorConverter; import org.openecomp.sdc.be.model.tosca.validators.PropertyTypeValidator; @@ -61,11 +85,6 @@ import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.beans.factory.annotation.Autowired; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - public abstract class BaseBusinessLogic { private static final String FAILED_TO_LOCK_COMPONENT_ERROR = "Failed to lock component {} error - {}"; @@ -374,7 +393,6 @@ public abstract class BaseBusinessLogic { ComponentTypeEnum getComponentTypeByParentComponentType(ComponentTypeEnum parentComponentType) { switch (parentComponentType) { case SERVICE: - return ComponentTypeEnum.RESOURCE; case RESOURCE: return ComponentTypeEnum.RESOURCE; case PRODUCT: @@ -666,8 +684,63 @@ public abstract class BaseBusinessLogic { return jsonElement.toString(); } - protected void rollbackWithException(ActionStatus actionStatus, String... params) { + void rollbackWithException(ActionStatus actionStatus, String... params) { titanDao.rollback(); throw new ComponentException(actionStatus, params); } + + public List setInputConstraint(T inputDefinition) { + if (StringUtils.isNotBlank(inputDefinition.getParentPropertyType()) + && StringUtils.isNotBlank(inputDefinition.getSubPropertyInputPath())) { + return setConstraint(inputDefinition); + } + + return Collections.emptyList(); + } + + private List setConstraint(T inputDefinition) { + List constraints = new ArrayList<>(); + String[] inputPathArr = inputDefinition.getSubPropertyInputPath().split("#"); + if (inputPathArr.length > 1) { + inputPathArr = ArrayUtils.remove(inputPathArr, 0); + } + + Map dataTypeDefinitionMap = + applicationDataTypeCache.getAll().left().value(); + + String propertyType = inputDefinition.getParentPropertyType(); + + for (String anInputPathArr : inputPathArr) { + if (ToscaType.isPrimitiveType(propertyType)) { + constraints.addAll( + dataTypeDefinitionMap.get(propertyType).getConstraints()); + } else if (!ToscaType.isCollectionType(propertyType)) { + propertyType = setConstraintForComplexType(dataTypeDefinitionMap, propertyType, anInputPathArr, + constraints); + } + } + + return constraints; + } + + private String setConstraintForComplexType(Map dataTypeDefinitionMap, + String propertyType, + String anInputPathArr, + List constraints) { + String type = null; + List propertyDefinitions = + dataTypeDefinitionMap.get(propertyType).getProperties(); + for (PropertyDefinition propertyDefinition : propertyDefinitions) { + if (propertyDefinition.getName().equals(anInputPathArr)) { + if (ToscaType.isPrimitiveType(propertyDefinition.getType())) { + constraints.addAll(propertyDefinition.getConstraints()); + } else { + type = propertyDefinition.getType(); + } + break; + } + } + + return type; + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java index 6b17d1c8e9..acf28c2455 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java @@ -20,6 +20,13 @@ package org.openecomp.sdc.be.components.impl; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + import fj.data.Either; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -34,9 +41,28 @@ import org.openecomp.sdc.be.dao.utils.MapUtil; import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum; import org.openecomp.sdc.be.datatypes.components.ServiceMetadataDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; -import org.openecomp.sdc.be.datatypes.enums.*; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.FilterKeyEnum; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; -import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.CapReqDef; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceInput; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.GroupDefinition; +import org.openecomp.sdc.be.model.IComponentInstanceConnectedElement; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.Operation; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.cache.ComponentCache; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; @@ -54,13 +80,6 @@ import org.openecomp.sdc.common.util.ValidationUtils; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.beans.factory.annotation.Autowired; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; - public abstract class ComponentBusinessLogic extends BaseBusinessLogic { @Autowired @@ -72,6 +91,9 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { @Autowired private GenericTypeBusinessLogic genericTypeBusinessLogic; + @Autowired + private ComponentInstanceBusinessLogic componentInstanceBusinessLogic; + public void setGenericTypeBusinessLogic(GenericTypeBusinessLogic genericTypeBusinessLogic) { this.genericTypeBusinessLogic = genericTypeBusinessLogic; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java index 1eb50e846a..0c6735f8c1 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java @@ -20,7 +20,26 @@ package org.openecomp.sdc.be.components.impl; +import static org.openecomp.sdc.be.components.property.GetInputUtils.isGetInputValueForInput; + import com.google.common.collect.Sets; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + import fj.data.Either; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -38,41 +57,43 @@ import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUtil; import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; -import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; -import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.impl.ForwardingPathUtils; import org.openecomp.sdc.be.impl.ServiceFilterUtils; import org.openecomp.sdc.be.info.CreateAndAssotiateInfo; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.ArtifactDefinition; import org.openecomp.sdc.be.model.CapabilityDefinition; -import org.openecomp.sdc.be.model.InterfaceDefinition; -import org.openecomp.sdc.be.model.RequirementDefinition; -import org.openecomp.sdc.be.model.Resource; -import org.openecomp.sdc.be.model.Service; -import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceInput; import org.openecomp.sdc.be.model.ComponentInstancePropInput; -import org.openecomp.sdc.be.model.LifecycleStateEnum; -import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DataTypeDefinition; -import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.InterfaceDefinition; +import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames; import org.openecomp.sdc.be.model.RelationshipInfo; import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; -import org.openecomp.sdc.be.model.ComponentInstance; -import org.openecomp.sdc.be.model.ComponentInstanceInput; -import org.openecomp.sdc.be.model.ComponentInstanceProperty; -import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames; +import org.openecomp.sdc.be.model.RequirementDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.jsontitan.operations.ForwardingPathOperation; import org.openecomp.sdc.be.model.jsontitan.operations.NodeFilterOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; @@ -95,24 +116,6 @@ import org.openecomp.sdc.common.util.ValidationUtils; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.beans.factory.annotation.Autowired; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.function.BiConsumer; -import java.util.stream.Collectors; - -import static org.openecomp.sdc.be.components.property.GetInputUtils.isGetInputValueForInput; - @org.springframework.stereotype.Component public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { @@ -131,6 +134,9 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { public static final String FAILED_TO_COPY_COMP_INSTANCE_TO_CANVAS = "Failed to copy the component instance to the canvas"; public static final String COPY_COMPONENT_INSTANCE_OK = "Copy component instance OK"; + @Autowired + private ApplicationDataTypeCache applicationDataTypeCache; + @Autowired private IComponentInstanceOperation componentInstanceOperation; @@ -1673,6 +1679,17 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)); return resultOp; } + + //Validate value and Constraint of property + Either constraintValidatorResponse = + PropertyValueConstraintValidationUtil.getInstance(). + validatePropertyConstraints(properties, applicationDataTypeCache); + if (constraintValidatorResponse.isRight()) { + log.error("Failed validation value and constraint of property: {}", + constraintValidatorResponse.right().value()); + return Either.right(constraintValidatorResponse.right().value()); + } + Either resourceInstanceStatus = getResourceInstanceById(containerComponent, resourceInstanceId); if (resourceInstanceStatus.isRight()) { resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_INSTANCE_NOT_FOUND_ON_SERVICE, resourceInstanceId, componentId)); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java index 357eb14ed0..f3b1b14652 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java @@ -24,15 +24,20 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import fj.data.Either; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.ListUtils; +import org.apache.commons.collections4.MapUtils; import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator; import org.openecomp.sdc.be.components.validation.ComponentValidations; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; import org.openecomp.sdc.be.dao.utils.MapUtil; +import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUtil; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; @@ -44,12 +49,15 @@ import org.openecomp.sdc.be.model.ComponentInstanceProperty; import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.inject.Inject; @@ -71,7 +79,6 @@ public class InputsBusinessLogic extends BaseBusinessLogic { private PropertyDeclarationOrchestrator propertyDeclarationOrchestrator; @Inject private ComponentInstanceBusinessLogic componentInstanceBusinessLogic; - /** * associate inputs to a given component with paging * @@ -124,7 +131,13 @@ public class InputsBusinessLogic extends BaseBusinessLogic { log.debug("Failed to found component instance inputs {}, error: {}", componentInstanceId, actionStatus); return Either.right(componentsUtils.getResponseFormat(actionStatus)); } - Map> ciInputs = Optional.ofNullable(component.getComponentInstancesInputs()).orElse(Collections.emptyMap()); + Map> ciInputs = + Optional.ofNullable(component.getComponentInstancesInputs()).orElse(Collections.emptyMap()); + + // Set Constraints on Input + MapUtils.emptyIfNull(ciInputs).values() + .forEach(inputs -> ListUtils.emptyIfNull(inputs) + .forEach(input -> input.setConstraints(setInputConstraint(input)))); return Either.left(ciInputs.getOrDefault(componentInstanceId, Collections.emptyList())); } @@ -140,7 +153,7 @@ public class InputsBusinessLogic extends BaseBusinessLogic { public Either, ResponseFormat> getComponentInstancePropertiesByInputId(String userId, String componentId, String instanceId, String inputId) { validateUserExists(userId, GET_PROPERTIES_BY_INPUT, false); String parentId = componentId; - org.openecomp.sdc.be.model.Component component = null; + org.openecomp.sdc.be.model.Component component; ComponentParametersView filters = new ComponentParametersView(); filters.disableAll(); filters.setIgnoreComponentInstances(false); @@ -246,6 +259,9 @@ public class InputsBusinessLogic extends BaseBusinessLogic { componentParametersView.disableAll(); componentParametersView.setIgnoreInputs(false); componentParametersView.setIgnoreUsers(false); + componentParametersView.setIgnoreProperties(false); + componentParametersView.setIgnoreComponentInstancesProperties(false); + componentParametersView.setIgnoreComponentInstances(false); Either validateComponent = validateComponentExists(componentId, componentType, componentParametersView); @@ -269,6 +285,14 @@ public class InputsBusinessLogic extends BaseBusinessLogic { return result; } + //Validate value and Constraint of input + Either constraintValidatorResponse = validateInputValueConstraint(component, inputs); + if (constraintValidatorResponse.isRight()) { + log.error("Failed validation value and constraint of property: {}", + constraintValidatorResponse.right().value()); + return Either.right(constraintValidatorResponse.right().value()); + } + Either, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache); if (allDataTypes.isRight()) { result = Either.right(allDataTypes.right().value()); @@ -321,6 +345,29 @@ public class InputsBusinessLogic extends BaseBusinessLogic { } } + private Either validateInputValueConstraint( + org.openecomp.sdc.be.model.Component component, List inputs) { + PropertyValueConstraintValidationUtil propertyValueConstraintValidationUtil = + PropertyValueConstraintValidationUtil.getInstance(); + List inputDefinitions = new ArrayList<>(); + for (InputDefinition inputDefinition : inputs) { + InputDefinition inputDef = new InputDefinition(); + inputDefinition.setDefaultValue(inputDefinition.getDefaultValue()); + inputDefinition.setInputPath(inputDefinition.getSubPropertyInputPath()); + inputDefinition.setType(inputDefinition.getType()); + if (Objects.nonNull(inputDefinition.getParentPropertyType())) { + ComponentInstanceProperty propertyDefinition = new ComponentInstanceProperty(); + propertyDefinition.setType(inputDefinition.getParentPropertyType()); + + inputDefinition.setProperties(Collections.singletonList(propertyDefinition)); + } + + inputDefinitions.add(inputDef); + } + + return propertyValueConstraintValidationUtil.validatePropertyConstraints(inputDefinitions, applicationDataTypeCache); + } + public Either, ResponseFormat> getInputsForComponentInput(String userId, String componentId, String inputId) { validateUserExists(userId, GET_PROPERTIES_BY_INPUT, false); org.openecomp.sdc.be.model.Component component = null; @@ -396,7 +443,7 @@ public class InputsBusinessLogic extends BaseBusinessLogic { .left() .bind(inputsToCreate -> prepareInputsForCreation(userId, componentId, inputsToCreate)) .right() - .map(err -> componentsUtils.getResponseFormat(err)); + .map(componentsUtils::getResponseFormat); return result; @@ -422,6 +469,9 @@ public class InputsBusinessLogic extends BaseBusinessLogic { private Either, StorageOperationStatus> prepareInputsForCreation(String userId, String cmptId, List inputsToCreate) { Map inputsToPersist = MapUtil.toMap(inputsToCreate, InputDefinition::getName); assignOwnerIdToInputs(userId, inputsToPersist); + inputsToPersist.values() + .forEach(input -> input.setConstraints(componentInstanceBusinessLogic.setInputConstraint(input))); + return toscaOperationFacade.addInputsToComponent(inputsToPersist, cmptId) .left() .map(persistedInputs -> inputsToCreate); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java index 7f19e824e5..de2839f653 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InterfaceOperationBusinessLogic.java @@ -450,6 +450,8 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic { operationInput.setToscaDefaultValue(getInputToscaDefaultValue(operationInput, component)); operationInput.setValue(componentInput.getValue()); operationInput.setSchema(componentInput.getSchema()); + operationInput.setParentPropertyType(componentInput.getParentPropertyType()); + operationInput.setSubPropertyInputPath(componentInput.getSubPropertyInputPath()); } //Set the tosca default value for inputs mapped to component inputs as well as other outputs operationInput.setToscaDefaultValue(getInputToscaDefaultValue(operationInput, component)); @@ -460,6 +462,7 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic { Map> defaultInputValue; if (isOperationInputMappedToComponentInput(input, component.getInputs())) { String propertyName = input.getInputId().substring(input.getInputId().indexOf('.') + 1); + setParentPropertyTypeAndInputPath(input, component); defaultInputValue = createMappedInputPropertyDefaultValue(propertyName); } else { //Currently inputs can only be mapped to a declared input or an other operation outputs @@ -468,6 +471,24 @@ public class InterfaceOperationBusinessLogic extends BaseBusinessLogic { return new Gson().toJson(defaultInputValue); } + private void setParentPropertyTypeAndInputPath(OperationInputDefinition input, + org.openecomp.sdc.be.model.Component component) { + if (CollectionUtils.isEmpty(component.getInputs())) { + return; + } + + component.getInputs() + .stream() + .filter(inp -> inp.getUniqueId().equals( + input.getInputId().substring(0, input.getInputId().lastIndexOf('.')))) + .forEach(inp -> { + input.setParentPropertyType(inp.getParentPropertyType()); + if (Objects.nonNull(input.getName())) { + input.setSubPropertyInputPath(input.getName().replaceAll("\\.", "#")); + } + }); + } + private void addOperationToInterface(InterfaceDefinition interfaceDefinition, Operation interfaceOperation) { interfaceOperation.setUniqueId(UUID.randomUUID().toString()); interfaceOperation.setImplementation(createArtifactDefinition(UUID.randomUUID().toString())); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java index 92d26a4eb8..53ed2a4306 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java @@ -8,7 +8,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0getUiComponentDataTransferByComponentId * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -21,10 +21,37 @@ package org.openecomp.sdc.be.components.impl; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.toSet; +import static org.apache.commons.collections.CollectionUtils.isNotEmpty; +import static org.apache.commons.collections.MapUtils.isEmpty; +import static org.apache.commons.collections.MapUtils.isNotEmpty; +import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaStringElement; +import static org.openecomp.sdc.be.components.impl.ImportUtils.getPropertyJsonStringValue; +import static org.openecomp.sdc.be.tosca.CsarUtils.VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.regex.Pattern; + import fj.data.Either; import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; +import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic; @@ -53,6 +80,7 @@ import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.CreatedFrom; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; @@ -130,31 +158,6 @@ import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; import javax.servlet.ServletContext; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; -import java.util.regex.Pattern; - -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; -import static java.util.stream.Collectors.toSet; -import static org.apache.commons.collections.CollectionUtils.isNotEmpty; -import static org.apache.commons.collections.MapUtils.isEmpty; -import static org.apache.commons.collections.MapUtils.isNotEmpty; -import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaStringElement; -import static org.openecomp.sdc.be.components.impl.ImportUtils.getPropertyJsonStringValue; -import static org.openecomp.sdc.be.tosca.CsarUtils.VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN; @org.springframework.stereotype.Component("resourceBusinessLogic") public class ResourceBusinessLogic extends ComponentBusinessLogic { @@ -5207,28 +5210,36 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } @Override - public Either getUiComponentDataTransferByComponentId(String resourceId, List dataParamsToReturn) { - - ComponentParametersView paramsToRetuen = new ComponentParametersView(dataParamsToReturn); - Either resourceResultEither = toscaOperationFacade.getToscaElement(resourceId, - paramsToRetuen); - - if (resourceResultEither.isRight()) { - if (resourceResultEither.right().value().equals(StorageOperationStatus.NOT_FOUND)) { - log.debug("Failed to found resource with id {} ", resourceId); - Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId)); - } - - log.debug("failed to get resource by id {} with filters {}", resourceId, dataParamsToReturn); - return Either.right(componentsUtils.getResponseFormatByResource( - componentsUtils.convertFromStorageResponse(resourceResultEither.right().value()), "")); - } - - Resource resource = resourceResultEither.left().value(); - UiComponentDataTransfer dataTransfer = uiComponentDataConverter.getUiDataTransferFromResourceByParams(resource, - dataParamsToReturn); - return Either.left(dataTransfer); - } + public Either getUiComponentDataTransferByComponentId(String resourceId, + List dataParamsToReturn) { + + ComponentParametersView paramsToRetuen = new ComponentParametersView(dataParamsToReturn); + Either resourceResultEither = + toscaOperationFacade.getToscaElement(resourceId, + paramsToRetuen); + + if (resourceResultEither.isRight()) { + if (resourceResultEither.right().value().equals(StorageOperationStatus.NOT_FOUND)) { + log.debug("Failed to found resource with id {} ", resourceId); + Either + .right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId)); + } + + log.debug("failed to get resource by id {} with filters {}", resourceId, dataParamsToReturn); + return Either.right(componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(resourceResultEither.right().value()), "")); + } + + Resource resource = resourceResultEither.left().value(); + if (dataParamsToReturn.contains(ComponentFieldsEnum.INPUTS.getValue())) { + ListUtils.emptyIfNull(resource.getInputs()) + .forEach(input -> input.setConstraints(setInputConstraint(input))); + } + + UiComponentDataTransfer dataTransfer = uiComponentDataConverter.getUiDataTransferFromResourceByParams(resource, + dataParamsToReturn); + return Either.left(dataTransfer); + } @Override public Either shouldUpgradeToLatestDerived(Component clonedComponent) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java index ba3b8dfc45..364b007ce3 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java @@ -20,13 +20,39 @@ package org.openecomp.sdc.be.components.impl; +import static org.apache.commons.collections.CollectionUtils.isEmpty; +import static org.apache.commons.collections.CollectionUtils.isNotEmpty; +import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationOutputName; +import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToOtherOperationOutput; +import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.UPDATE_SERVICE_METADATA; +import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.SELF; +import static org.openecomp.sdc.be.types.ServiceConsumptionSource.SERVICE_INPUT; +import static org.openecomp.sdc.be.types.ServiceConsumptionSource.STATIC; + import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.gson.Gson; import com.google.gson.GsonBuilder; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.function.Function; +import java.util.stream.Collectors; + import fj.data.Either; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; +import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.components.distribution.engine.IDistributionEngine; @@ -46,6 +72,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.cassandra.AuditCassandraDao; import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; import org.openecomp.sdc.be.datamodel.ServiceRelations; +import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUtil; import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter; import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition; @@ -54,6 +81,7 @@ import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition; import org.openecomp.sdc.be.datatypes.elements.RequirementNodeFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.InstantiationTypes; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; @@ -62,7 +90,24 @@ import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.externalapi.servlet.representation.ServiceDistributionReqInfo; import org.openecomp.sdc.be.impl.ForwardingPathUtils; import org.openecomp.sdc.be.impl.WebAppContextWrapper; -import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceInterface; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.ComponentParametersView; +import org.openecomp.sdc.be.model.DistributionStatusEnum; +import org.openecomp.sdc.be.model.DistributionTransitionEnum; +import org.openecomp.sdc.be.model.GroupInstance; +import org.openecomp.sdc.be.model.GroupInstanceProperty; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.InterfaceDefinition; +import org.openecomp.sdc.be.model.LifecycleStateEnum; +import org.openecomp.sdc.be.model.Operation; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.category.CategoryDefinition; import org.openecomp.sdc.be.model.jsontitan.operations.ForwardingPathOperation; import org.openecomp.sdc.be.model.jsontitan.operations.NodeFilterOperation; @@ -77,7 +122,11 @@ import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; import org.openecomp.sdc.be.model.tosca.validators.PropertyTypeValidator; import org.openecomp.sdc.be.resources.data.ComponentInstanceData; import org.openecomp.sdc.be.resources.data.ComponentMetadataData; -import org.openecomp.sdc.be.resources.data.auditing.*; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.resources.data.auditing.AuditingGenericEvent; +import org.openecomp.sdc.be.resources.data.auditing.DistributionDeployEvent; +import org.openecomp.sdc.be.resources.data.auditing.DistributionNotificationEvent; +import org.openecomp.sdc.be.resources.data.auditing.ResourceAdminEvent; import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo; import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo; import org.openecomp.sdc.be.types.ServiceConsumptionData; @@ -100,20 +149,6 @@ import org.springframework.web.context.WebApplicationContext; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.Callable; -import java.util.function.Function; -import java.util.stream.Collectors; - -import static org.apache.commons.collections.CollectionUtils.isEmpty; -import static org.apache.commons.collections.CollectionUtils.isNotEmpty; -import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.getOperationOutputName; -import static org.openecomp.sdc.be.components.utils.InterfaceOperationUtils.isOperationInputMappedToOtherOperationOutput; -import static org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum.UPDATE_SERVICE_METADATA; -import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.SELF; -import static org.openecomp.sdc.be.types.ServiceConsumptionSource.SERVICE_INPUT; -import static org.openecomp.sdc.be.types.ServiceConsumptionSource.STATIC; @org.springframework.stereotype.Component("serviceBusinessLogic") public class ServiceBusinessLogic extends ComponentBusinessLogic { @@ -365,7 +400,6 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { } OperationInputDefinition operationInputDefinition = inputCandidate.get(); - // add data to operation if(Objects.nonNull(serviceConsumptionData.getValue())) { @@ -441,6 +475,14 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { ServiceConsumptionSource sourceValue = ServiceConsumptionSource.getSourceValue(source); if(STATIC.equals(sourceValue)) { + // Validate constraint on input value + /*Either constraintValidationResult = + validateOperationInputConstraint(operationInputDefinition, serviceConsumptionData); + + if (constraintValidationResult.isRight()) { + return Either.right(constraintValidationResult.right().value()); + }*/ + return handleConsumptionStaticValue(consumptionValue, type, operation, operationInputDefinition); } @@ -612,12 +654,37 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { return Either.right(componentsUtils.getResponseFormat( ActionStatus.INVALID_CONSUMPTION_TYPE, type)); } + + //Validate Constraint and Value + Either constraintValidationResponse = + validateOperationInputConstraint(operationInputDefinition, value, type); + if(constraintValidationResponse.isRight()) { + return Either.right(constraintValidationResponse.right().value()); + } + addStaticValueToInputOperation(value, operation, operationInputDefinition); return Either.left(operation); } - private void addStaticValueToInputOperation(String value, Operation operation, + private Either validateOperationInputConstraint( + OperationInputDefinition operationInputDefinition, String value, String type) { + ComponentInstanceProperty propertyDefinition = new ComponentInstanceProperty(); + propertyDefinition.setType(operationInputDefinition.getParentPropertyType()); + + InputDefinition inputDefinition = new InputDefinition(); + inputDefinition.setDefaultValue(value); + inputDefinition.setInputPath(operationInputDefinition.getSubPropertyInputPath()); + inputDefinition.setType(type); + if (Objects.nonNull(operationInputDefinition.getParentPropertyType())) { + inputDefinition.setProperties(Collections.singletonList(propertyDefinition)); + } + + return PropertyValueConstraintValidationUtil.getInstance() + .validatePropertyConstraints(Collections.singletonList(inputDefinition), applicationDataTypeCache); + } + + private void addStaticValueToInputOperation(String value, Operation operation, OperationInputDefinition operationInputDefinition) { operation.getInputs().delete(operationInputDefinition); operationInputDefinition.setSource(STATIC.getSource()); @@ -2571,6 +2638,11 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { } Service service = serviceResultEither.left().value(); + if (dataParamsToReturn.contains(ComponentFieldsEnum.INPUTS.getValue())) { + ListUtils.emptyIfNull(service.getInputs()) + .forEach(input -> input.setConstraints(setInputConstraint(input))); + } + UiComponentDataTransfer dataTransfer = uiComponentDataConverter.getUiDataTransferFromServiceByParams(service, dataParamsToReturn); return Either.left(dataTransfer); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java index bd7a58c48a..0f76210a1a 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java @@ -156,6 +156,14 @@ public abstract class DefaultPropertyDeclarator dataTypeDefinitionCache; + private static final Logger logger = LoggerFactory.getLogger(PropertyValueConstraintValidationUtil.class); + private ObjectMapper objectMapper = new ObjectMapper(); + private List errorMessages = new ArrayList<>(); + private StringBuilder completePropertyName; + private String completeInputName; + private static final String IGNORE_PROPERTY_VALUE_START_WITH = "{\"get_input\":"; + + public static PropertyValueConstraintValidationUtil getInstance() { + return new PropertyValueConstraintValidationUtil(); + } + + public Either validatePropertyConstraints( + Collection propertyDefinitionList, + ApplicationDataTypeCache applicationDataTypeCache) { + ResponseFormatManager responseFormatManager = getResponseFormatManager(); + dataTypeDefinitionCache = applicationDataTypeCache.getAll().left().value(); + CollectionUtils.emptyIfNull(propertyDefinitionList).stream() + .filter(this::isValuePresent) + .forEach(this::evaluatePropertyTypeForConstraintValidation); + + if (CollectionUtils.isNotEmpty(errorMessages)) { + logger.error("Properties with Invalid Data:", errorMessages); + ResponseFormat inputResponse = responseFormatManager.getResponseFormat(ActionStatus + .INVALID_PROPERTY_VALUES, String.join(",", errorMessages)); + return Either.right(inputResponse); + } + + return Either.left(Boolean.TRUE); + } + + private boolean isValuePresent(PropertyDefinition propertyDefinition) { + if (propertyDefinition instanceof InputDefinition) { + return StringUtils.isNotEmpty(propertyDefinition.getDefaultValue()); + } + + return StringUtils.isNotEmpty(propertyDefinition.getValue()); + } + + private void evaluatePropertyTypeForConstraintValidation(PropertyDefinition propertyDefinition) { + if (Objects.nonNull(propertyDefinition.getType()) + && dataTypeDefinitionCache.containsKey(propertyDefinition.getType())) { + + completeInputName = ""; + completePropertyName = new StringBuilder(); + if (propertyDefinition instanceof InputDefinition) { + completeInputName = propertyDefinition.getName(); + propertyDefinition = getPropertyDefinitionObjectFromInputs(propertyDefinition); + } + + if (Objects.nonNull(propertyDefinition)) { + if (ToscaType.isPrimitiveType(propertyDefinition.getType())) { + propertyDefinition.setConstraints( + org.openecomp.sdc.be.dao.utils.CollectionUtils.merge(propertyDefinition.getConstraints(), + dataTypeDefinitionCache.get(propertyDefinition.getType()).getConstraints())); + evaluateConstraintsOnProperty(propertyDefinition); + } else if (ToscaType.isCollectionType(propertyDefinition.getType())) { + propertyDefinition.setConstraints( + org.openecomp.sdc.be.dao.utils.CollectionUtils.merge(propertyDefinition.getConstraints(), + dataTypeDefinitionCache.get(propertyDefinition.getType()).getConstraints())); + evaluateConstraintsOnProperty(propertyDefinition); + evaluateCollectionTypeProperties(propertyDefinition); + } else { + setCompletePropertyName(propertyDefinition); + evaluateComplexTypeProperties(propertyDefinition); + } + } + } else { + errorMessages.add("\nUnsupported datatype found for property " + getCompletePropertyName(propertyDefinition)); + } + } + + private void setCompletePropertyName(PropertyDefinition propertyDefinition) { + if(StringUtils.isNotBlank(propertyDefinition.getUniqueId())) { + completePropertyName.append( + propertyDefinition.getUniqueId().substring(propertyDefinition.getUniqueId().lastIndexOf('.') + 1)); + } + } + + private void evaluateConstraintsOnProperty(PropertyDefinition propertyDefinition) { + ToscaType toscaType = ToscaType.isValidType(propertyDefinition.getType()); + if (isPropertyNotMappedAsInput(propertyDefinition) + && CollectionUtils.isNotEmpty(propertyDefinition.getConstraints()) + && isValidValueConstraintPresent(propertyDefinition.getConstraints())) { + for (PropertyConstraint propertyConstraint : propertyDefinition.getConstraints()) { + try { + propertyConstraint.initialize(toscaType); + propertyConstraint.validate(toscaType, propertyDefinition.getValue()); + } catch (ConstraintValueDoNotMatchPropertyTypeException | ConstraintViolationException exception) { + errorMessages.add("\n" + propertyConstraint.getErrorMessage( + toscaType, exception, getCompletePropertyName(propertyDefinition))); + } + } + } else if (isPropertyNotMappedAsInput(propertyDefinition) + && ToscaType.isPrimitiveType(propertyDefinition.getType()) + && !toscaType.isValidValue(propertyDefinition.getValue())) { + errorMessages.add(String.format("\nUnsupported value provided for %s property supported value " + + "type is %s.", getCompletePropertyName(propertyDefinition), toscaType.getType())); + } + } + + private boolean isPropertyNotMappedAsInput(PropertyDefinition propertyDefinition) { + return !propertyDefinition.getValue().startsWith(IGNORE_PROPERTY_VALUE_START_WITH); + } + + private void checkAndEvaluatePrimitiveProperty(PropertyDefinition propertyDefinition, + DataTypeDefinition dataTypeDefinition) { + if (ToscaType.isPrimitiveType(dataTypeDefinition.getName()) + && CollectionUtils.isNotEmpty(dataTypeDefinition.getConstraints())) { + + PropertyDefinition definition = new PropertyDefinition(); + definition.setValue(propertyDefinition.getValue()); + definition.setType(dataTypeDefinition.getName()); + definition.setConstraints(dataTypeDefinition.getConstraints()); + + evaluateConstraintsOnProperty(propertyDefinition); + } + } + + private void evaluateComplexTypeProperties(PropertyDefinition propertyDefinition) { + List propertyDefinitions = + dataTypeDefinitionCache.get(propertyDefinition.getType()).getProperties(); + try { + Map valueMap = + MapUtils.emptyIfNull(ConstraintUtil.parseToCollection(propertyDefinition.getValue(), + new TypeReference>() {})); + + if (CollectionUtils.isEmpty(propertyDefinitions)) { + checkAndEvaluatePrimitiveProperty(propertyDefinition, + dataTypeDefinitionCache.get(propertyDefinition.getType())); + } else { + ListUtils.emptyIfNull(propertyDefinitions) + .forEach(prop -> evaluateRegularComplexType(propertyDefinition, prop, valueMap)); + } + } catch (ConstraintValueDoNotMatchPropertyTypeException e) { + logger.debug(e.getMessage(), e); + errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, + getCompletePropertyName(propertyDefinition))); + } + } + + private void evaluateRegularComplexType(PropertyDefinition propertyDefinition, + PropertyDefinition prop, + Map valueMap) { + try { + if (valueMap.containsKey(prop.getName())) { + if (ToscaType.isPrimitiveType(prop.getType())) { + evaluateConstraintsOnProperty(createPropertyDefinition(prop, + String.valueOf(valueMap.get(prop.getName())))); + } else if (ToscaType.isCollectionType(prop.getType())) { + + evaluateCollectionTypeProperties(createPropertyDefinition(prop, + objectMapper.writeValueAsString(valueMap.get(prop.getName())))); + } else { + completePropertyName.append(UNDERSCORE); + completePropertyName.append(prop.getName()); + evaluateComplexTypeProperties( + createPropertyDefinition(prop, objectMapper.writeValueAsString( + valueMap.get(prop.getName())))); + } + } + } catch (IOException e) { + logger.error(e.getMessage(), e); + errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, + getCompletePropertyName(propertyDefinition))); + } + } + + private void evaluateCollectionTypeProperties(PropertyDefinition propertyDefinition) { + ToscaType toscaPropertyType = ToscaType.isValidType(propertyDefinition.getType()); + if (ToscaType.LIST == toscaPropertyType) { + evaluateListType(propertyDefinition); + } else if (ToscaType.MAP == toscaPropertyType) { + evaluateMapType(propertyDefinition); + } + } + + private void evaluateListType(PropertyDefinition propertyDefinition) { + try { + String schemaType = propertyDefinition.getSchemaType(); + List list = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), + new TypeReference>() {}); + evaluateCollectionType(propertyDefinition, list, schemaType); + } catch (ConstraintValueDoNotMatchPropertyTypeException e) { + logger.debug(e.getMessage(), e); + errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, + getCompletePropertyName(propertyDefinition))); + } + } + + private void evaluateMapType(PropertyDefinition propertyDefinition) { + try { + String schemaType = propertyDefinition.getSchemaType(); + Map map = ConstraintUtil.parseToCollection(propertyDefinition.getValue(), + new TypeReference>() { + }); + evaluateCollectionType(propertyDefinition, map.values(), schemaType); + } catch (ConstraintValueDoNotMatchPropertyTypeException e) { + logger.debug(e.getMessage(), e); + errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, + getCompletePropertyName(propertyDefinition))); + } + } + + private void evaluateCollectionPrimitiveSchemaType(PropertyDefinition propertyDefinition, + Object value, + String schemaType) { + if (Objects.nonNull(propertyDefinition.getSchema()) + && propertyDefinition.getSchema().getProperty() instanceof PropertyDefinition) { + propertyDefinition.setConstraints(((PropertyDefinition) propertyDefinition.getSchema() + .getProperty()).getConstraints()); + propertyDefinition.setValue(String.valueOf(value)); + propertyDefinition.setType(schemaType); + evaluateConstraintsOnProperty(propertyDefinition); + } + } + private void evaluateCollectionType(PropertyDefinition propertyDefinition, + Collection valueList, + String schemaType) { + for (Object value : valueList) { + try { + if (ToscaType.isPrimitiveType(schemaType)) { + evaluateCollectionPrimitiveSchemaType(propertyDefinition, value, schemaType); + } else if (ToscaType.isCollectionType(schemaType)) { + propertyDefinition.setValue(objectMapper.writeValueAsString(value)); + propertyDefinition.setType(schemaType); + evaluateCollectionTypeProperties(propertyDefinition); + } else { + propertyDefinition.setValue(objectMapper.writeValueAsString(value)); + propertyDefinition.setType(schemaType); + completePropertyName.append(UNDERSCORE); + completePropertyName.append(propertyDefinition.getName()); + evaluateComplexTypeProperties(propertyDefinition); + } + } catch (IOException e) { + logger.debug(e.getMessage(), e); + errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, + getCompletePropertyName(propertyDefinition))); + } + } + } + + private String getCompletePropertyName(PropertyDefinition propertyDefinition) { + return StringUtils.isNotBlank(completeInputName) ? completeInputName : + StringUtils.isBlank(completePropertyName) ? + propertyDefinition.getName() : completePropertyName + UNDERSCORE + propertyDefinition.getName(); + } + + private PropertyDefinition createPropertyDefinition(PropertyDefinition prop, String value) { + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setName(prop.getName()); + propertyDefinition.setValue(value); + propertyDefinition.setType(prop.getType()); + propertyDefinition.setConstraints(prop.getConstraints()); + propertyDefinition.setSchema(prop.getSchema()); + + return propertyDefinition; + } + + private boolean isValidValueConstraintPresent(List propertyConstraints) { + return propertyConstraints.stream() + .anyMatch(propertyConstraint -> propertyConstraint instanceof ValidValuesConstraint); + } + + private PropertyDefinition getPropertyDefinitionObjectFromInputs( + PropertyDefinition property) { + InputDefinition inputDefinition = (InputDefinition) property; + PropertyDefinition propertyDefinition = null; + + if (CollectionUtils.isEmpty(inputDefinition.getProperties()) + || ToscaType.isPrimitiveType(inputDefinition.getProperties().get(0).getType())) { + propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType(inputDefinition.getType()); + propertyDefinition.setValue(inputDefinition.getDefaultValue()); + propertyDefinition.setName(inputDefinition.getName()); + } else if (Objects.nonNull(inputDefinition.getInputPath())) { + propertyDefinition = evaluateComplexTypeInputs(inputDefinition); + } + + return propertyDefinition; + } + + private PropertyDefinition evaluateComplexTypeInputs(InputDefinition inputDefinition) { + Map inputMap = new HashMap<>(); + PropertyDefinition propertyDefinition = new PropertyDefinition(); + String[] inputPathArr = inputDefinition.getInputPath().split("#"); + if (inputPathArr.length > 1) { + inputPathArr = ArrayUtils.remove(inputPathArr, 0); + } + + try { + Map presentMap = inputMap; + for (int i = 0; i < inputPathArr.length ; i++) { + if (i == inputPathArr.length - 1) { + presentMap.computeIfAbsent(inputPathArr[i], k -> inputDefinition.getDefaultValue()); + } else { + presentMap.computeIfAbsent(inputPathArr[i], k -> new HashMap()); + presentMap = (Map) presentMap.get(inputPathArr[i]); + } + } + + if (CollectionUtils.isNotEmpty(inputDefinition.getProperties())) { + propertyDefinition.setType(inputDefinition.getProperties().get(0).getType()); + } + propertyDefinition.setName(inputDefinition.getName()); + propertyDefinition.setValue(objectMapper.writeValueAsString(inputMap)); + } catch (IOException e) { + logger.error(e.getMessage(), e); + errorMessages.add(String.format(VALUE_PROVIDED_IN_INVALID_FORMAT_FOR_PROPERTY, + inputDefinition.getName())); + } + + return propertyDefinition; + } + + protected ResponseFormatManager getResponseFormatManager() { + return ResponseFormatManager.getInstance(); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentPropertyServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentPropertyServlet.java index 79e63c71b5..38c04a131c 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentPropertyServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentPropertyServlet.java @@ -17,28 +17,45 @@ package org.openecomp.sdc.be.servlets; import com.jcabi.aspects.Loggable; + +import java.util.List; +import java.util.Map; + import fj.data.Either; -import io.swagger.annotations.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic; import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUtil; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.resources.data.EntryData; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.exception.ResponseFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import javax.inject.Singleton; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.util.List; -import java.util.Map; @Loggable(prepend = true, value = Loggable.DEBUG, trim = false) @Path("/v1/catalog") @@ -46,6 +63,9 @@ import java.util.Map; @Singleton public class ComponentPropertyServlet extends BeGenericServlet { + @Autowired + ApplicationDataTypeCache applicationDataTypeCache; + private static final Logger log = LoggerFactory.getLogger(ComponentPropertyServlet.class); private static final String CREATE_PROPERTY = "Create Property"; private static final String DEBUG_MESSAGE = "Start handle request of {} modifier id is {}"; @@ -264,6 +284,16 @@ public class ComponentPropertyServlet extends BeGenericServlet { return buildErrorResponse(responseFormat); } + //Validate value and Constraint of property + Either constraintValidatorResponse = + PropertyValueConstraintValidationUtil.getInstance(). + validatePropertyConstraints(properties.values(), applicationDataTypeCache); + if (constraintValidatorResponse.isRight()) { + log.error("Failed validation value and constraint of property: {}", + constraintValidatorResponse.right().value()); + return buildErrorResponse(constraintValidatorResponse.right().value()); + } + // update property PropertyBusinessLogic businessLogic = getPropertyBL(context); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java index 4ed2f95676..990e3bc356 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceConsumptionServlet.java @@ -44,6 +44,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.model.Operation; +import org.openecomp.sdc.be.model.OperationInput; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.tosca.ToscaFunctions; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; @@ -158,8 +159,7 @@ public class ServiceConsumptionServlet extends BeGenericServlet { } List inputs = inputsEither.left().value(); - updateOperationInputListForUi(inputs); - return buildOkResponse(inputs); + return buildOkResponse(updateOperationInputListForUi(inputs, interfaceOperationBL)); } catch (Exception e) { BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Operation Inputs"); @@ -169,43 +169,52 @@ public class ServiceConsumptionServlet extends BeGenericServlet { } } - private void updateOperationInputListForUi(List inputsList) { - for(OperationInputDefinition input : inputsList) { - - String value = input.getValue(); - // No Additional UI mapping needed for STATIC source - if(StringUtils.isEmpty(value) - || ServiceConsumptionSource.STATIC.getSource().equals(input.getSource())) { - continue; - } - - - // Additional UI mapping needed for other sources - try { - Map valueAsMap = (new Gson()).fromJson(value, Map.class); - String toscaFunction = valueAsMap.keySet().iterator().next(); - Object consumptionValueName = valueAsMap.values().iterator().next(); - if(consumptionValueName instanceof List) { - List toscaFunctionList = (List) consumptionValueName; - String consumptionInputValue = null; - if (ToscaFunctions.GET_PROPERTY.getFunctionName().equals(toscaFunction)) { - consumptionInputValue = String.valueOf(toscaFunctionList.get(1)); - } else if (ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName().equals(toscaFunction)) { - //Return full output name - consumptionInputValue = - toscaFunctionList.get(1) + "." + toscaFunctionList.get(2) + "." +toscaFunctionList.get(3); - } - input.setValue(consumptionInputValue); - } else { - input.setValue(String.valueOf(consumptionValueName)); - } - } - catch(JsonParseException ex){ - log.info("This means it is static value for which no changes are needed"); - } - } - } - + private List updateOperationInputListForUi(List inputsList, + InterfaceOperationBusinessLogic interfaceOperationBL) { + List operationInputs = new ArrayList<>(); + for(OperationInputDefinition input : inputsList) { + + String value = input.getValue(); + + // Additional UI mapping needed for other sources + if (StringUtils.isNotBlank(value) + && !ServiceConsumptionSource.STATIC.getSource().equals(input.getSource())) { + uiMappingForOtherSources(value, input); + } + + // Add Constraint for UI + OperationInput operationInput = new OperationInput(input); + operationInput.setConstraints(interfaceOperationBL.setInputConstraint(input)); + operationInputs.add(operationInput); + } + + return operationInputs; + } + + private void uiMappingForOtherSources(String value, OperationInputDefinition input) { + try { + Map valueAsMap = (new Gson()).fromJson(value, Map.class); + String toscaFunction = valueAsMap.keySet().iterator().next(); + Object consumptionValueName = valueAsMap.values().iterator().next(); + if(consumptionValueName instanceof List) { + List toscaFunctionList = (List) consumptionValueName; + String consumptionInputValue = null; + if (ToscaFunctions.GET_PROPERTY.getFunctionName().equals(toscaFunction)) { + consumptionInputValue = String.valueOf(toscaFunctionList.get(1)); + } else if (ToscaFunctions.GET_OPERATION_OUTPUT.getFunctionName().equals(toscaFunction)) { + //Return full output name + consumptionInputValue = + toscaFunctionList.get(1) + "." + toscaFunctionList.get(2) + "." +toscaFunctionList.get(3); + } + input.setValue(consumptionInputValue); + } else { + input.setValue(String.valueOf(consumptionValueName)); + } + } + catch(JsonParseException ex){ + log.info("This means it is static value for which no changes are needed"); + } + } private Either>, ResponseFormat> getServiceConsumptionData(String data, User user) { diff --git a/catalog-be/src/main/resources/config/error-configuration.yaml b/catalog-be/src/main/resources/config/error-configuration.yaml index d9f8ffc7e4..312d90c307 100644 --- a/catalog-be/src/main/resources/config/error-configuration.yaml +++ b/catalog-be/src/main/resources/config/error-configuration.yaml @@ -2262,4 +2262,10 @@ errors: code: 400, message: "Error: Given value is different than input type. Needs to be %1", messageId: "SVC4725" + } +#---------SVC4726----------------------------- + INVALID_PROPERTY_VALUES: { + code: 400, + message: "Error: Invalid property values provided:\n %1", + messageId: "SVC4735" } \ No newline at end of file diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/datamodel/utils/PropertyValueConstraintValidationUtilTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/datamodel/utils/PropertyValueConstraintValidationUtilTest.java new file mode 100644 index 0000000000..95020b6112 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/datamodel/utils/PropertyValueConstraintValidationUtilTest.java @@ -0,0 +1,317 @@ +package org.openecomp.sdc.be.datamodel.utils; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; + +import java.io.BufferedReader; +import java.io.File; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import fj.data.Either; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.openecomp.sdc.be.components.impl.ResponseFormatManager; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.PropertyConstraint; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; +import org.openecomp.sdc.exception.ResponseFormat; + +public class PropertyValueConstraintValidationUtilTest { + + @Mock + ApplicationDataTypeCache applicationDataTypeCache; + + @Mock + ToscaOperationFacade toscaOperationFacade; + + @Spy + @InjectMocks + PropertyValueConstraintValidationUtil propertyValueConstraintValidationUtil; + + private Map dataTypeDefinitionMap; + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + ResponseFormatManager responseFormatManagerMock = Mockito.mock(ResponseFormatManager.class); + when(responseFormatManagerMock.getResponseFormat(any())).thenReturn(new ResponseFormat()); + when(responseFormatManagerMock.getResponseFormat(any(), any())).thenReturn(new ResponseFormat()); + when(responseFormatManagerMock.getResponseFormat(any(), any(), any())).thenReturn(new ResponseFormat()); + when(propertyValueConstraintValidationUtil.getResponseFormatManager()).thenReturn(responseFormatManagerMock); + + createDataTypeMap(); + } + + @Test + public void primitiveValueSuccessTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType("integer"); + propertyDefinition.setValue("10"); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(propertyDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isLeft()); + } + + @Test + public void primitiveValueFailTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType("integer"); + propertyDefinition.setValue("abcd"); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(propertyDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isRight()); + } + + @Test + public void complexWithValidValueSuccessTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + propertyDefinition.setValue("{\"prefixlen\":\"4\"}"); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(propertyDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isLeft()); + } + + @Test + public void complexWithValidValueFailTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + propertyDefinition.setValue("{\"prefixlen\":\"5\"}"); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(propertyDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isRight()); + } + + @Test + public void complexWithListWithPrimitiveValueSuccessTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + propertyDefinition.setValue("{\"allocation_pools\":[\"slaac\"]}"); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(propertyDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isLeft()); + } + + @Test + public void complexWithListWithPrimitiveValueFailTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + propertyDefinition.setValue("{\"allocation_pools\":[\"value\"]}"); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(propertyDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isRight()); + } + + @Test + public void complexWithMapWithPrimitiveValueSuccessTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + propertyDefinition.setValue("{\"value_specs\":{\"key\":\"slaac\"}}"); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(propertyDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isLeft()); + } + + @Test + public void complexWithMapWithPrimitiveValueFailTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + propertyDefinition.setValue("{\"value_specs\":{\"key\":\"value\"}}"); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(propertyDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isRight()); + } + + @Test + public void inputValidValueSuccessTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + InputDefinition inputDefinition = new InputDefinition(); + inputDefinition.setInputPath("propetyName#ipv6_ra_mode"); + inputDefinition.setDefaultValue("slaac"); + inputDefinition.setType("string"); + ComponentInstanceProperty propertyDefinition = new ComponentInstanceProperty(); + propertyDefinition.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + inputDefinition.setProperties(Collections.singletonList(propertyDefinition)); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(inputDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isLeft()); + } + + @Test + public void inputValidValueFailTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + InputDefinition inputDefinition = new InputDefinition(); + inputDefinition.setInputPath("propetyName#ipv6_ra_mode"); + inputDefinition.setDefaultValue("incorrectValue"); + ComponentInstanceProperty propertyDefinition = new ComponentInstanceProperty(); + propertyDefinition.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + inputDefinition.setProperties(Collections.singletonList(propertyDefinition)); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(inputDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isRight()); + } + + @Test + public void serviceConsumptionValidValueSuccessTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + propertyDefinition.setValue("{\"ipv6_ra_mode\":\"slaac\"}"); + propertyDefinition.setName("ipv6_ra_mode"); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(propertyDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isLeft()); + } + @Test + public void serviceConsumptionValidValueFailTest() { + Either, TitanOperationStatus> either = Either.left(dataTypeDefinitionMap); + Mockito.when(applicationDataTypeCache.getAll()).thenReturn(either); + + PropertyDefinition propertyDefinition = new PropertyDefinition(); + propertyDefinition.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + propertyDefinition.setValue("{\"ipv6_ra_mode\":\"incorrectValue\"}"); + propertyDefinition.setName("ipv6_ra_mode"); + + Either responseEither = + propertyValueConstraintValidationUtil.validatePropertyConstraints( + Collections.singletonList(propertyDefinition), applicationDataTypeCache); + + Assert.assertTrue(responseEither.isRight()); + } + + private void createDataTypeMap() { + Type constraintType = new TypeToken() {}.getType(); + Type typeOfHashMap = new TypeToken>() { }.getType(); + Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, + new PropertyOperation.PropertyConstraintDeserialiser()).create(); + + dataTypeDefinitionMap = gson.fromJson(readFile(), typeOfHashMap); + + DataTypeDefinition dataTypeDefinition = dataTypeDefinitionMap.get("org.openecomp.datatypes.heat.network" + + ".neutron.Subnet"); + + PropertyDefinition mapProperty = null; + PropertyDefinition listProperty = null; + List constraints = null; + for (PropertyDefinition propertyDefinition : dataTypeDefinition.getProperties()) { + if ("value_specs".equals(propertyDefinition.getName())) { + mapProperty = propertyDefinition; + } else if ("allocation_pools".equals(propertyDefinition.getName())) { + listProperty = propertyDefinition; + } else if ("ipv6_ra_mode".equals(propertyDefinition.getName())) { + constraints = propertyDefinition.getConstraints(); + } + } + + PropertyDefinition definition = new PropertyDefinition(mapProperty.getSchema().getProperty()); + definition.setConstraints(constraints); + mapProperty.getSchema().setProperty(definition); + + definition = new PropertyDefinition(listProperty.getSchema().getProperty()); + definition.setConstraints(constraints); + listProperty.getSchema().setProperty(definition); + } + + private static String readFile() { + StringBuilder stringBuilder = new StringBuilder(); + File file = new File(Objects.requireNonNull( + PropertyValueConstraintValidationUtilTest.class.getClassLoader().getResource("types/datatypes" + + "/constraintTest.json")).getFile()); + Path logFile = Paths.get(file.getAbsolutePath()); + try (BufferedReader reader = Files.newBufferedReader(logFile, StandardCharsets.UTF_8)) { + reader.lines().forEach(stringBuilder::append); + } catch (Exception e) { + Assert.fail(e.getMessage()); + e.printStackTrace(); + } + return stringBuilder.toString(); + } + +} diff --git a/catalog-be/src/test/resources/csars/with_groups.csar b/catalog-be/src/test/resources/csars/with_groups.csar index 3859114aa5..3a9e9ab8e0 100644 Binary files a/catalog-be/src/test/resources/csars/with_groups.csar and b/catalog-be/src/test/resources/csars/with_groups.csar differ diff --git a/catalog-be/src/test/resources/types/datatypes/constraintTest.json b/catalog-be/src/test/resources/types/datatypes/constraintTest.json new file mode 100644 index 0000000000..9596e92436 --- /dev/null +++ b/catalog-be/src/test/resources/types/datatypes/constraintTest.json @@ -0,0 +1,405 @@ +{ + "string": { + "derivedFrom": { + "name": "tosca.datatypes.Root", + "uniqueId": "tosca.datatypes.Root.datatype", + "description": "The TOSCA root Data Type all other TOSCA base Data Types derive from", + "creationTime": 1550136563278, + "modificationTime": 1550136563278, + "toscaPresentation": {} + }, + "name": "string", + "uniqueId": "string.datatype", + "derivedFromName": "tosca.datatypes.Root", + "creationTime": 1550136564103, + "modificationTime": 1550136564103, + "toscaPresentation": {} + }, + "org.openecomp.datatypes.heat.network.neutron.Subnet": { + "derivedFrom": { + "name": "tosca.datatypes.Root", + "uniqueId": "tosca.datatypes.Root.datatype", + "description": "The TOSCA root Data Type all other TOSCA base Data Types derive from", + "creationTime": 1550136563278, + "modificationTime": 1550136563278, + "toscaPresentation": {} + }, + "properties": [ + { + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.tenant_id", + "type": "string", + "required": false, + "definition": false, + "description": "The ID of the tenant who owns the network", + "password": false, + "name": "tenant_id", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.enable_dhcp", + "type": "boolean", + "required": false, + "definition": false, + "defaultValue": "true", + "description": "Set to true if DHCP is enabled and false if DHCP is disabled", + "password": false, + "name": "enable_dhcp", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "constraints": [ + { + "validValues": [ + "dhcpv6-stateful", + "dhcpv6-stateless", + "slaac" + ] + } + ], + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.ipv6_address_mode", + "type": "string", + "required": false, + "definition": false, + "description": "IPv6 address mode", + "password": false, + "name": "ipv6_address_mode", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "constraints": [ + { + "validValues": [ + "dhcpv6-stateful", + "dhcpv6-stateless", + "slaac" + ] + } + ], + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.ipv6_ra_mode", + "type": "string", + "required": false, + "definition": false, + "description": "IPv6 RA (Router Advertisement) mode", + "password": false, + "name": "ipv6_ra_mode", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.value_specs", + "type": "map", + "required": false, + "definition": false, + "defaultValue": "{}", + "description": "Extra parameters to include in the request", + "schema": { + "property": { + "constraints": [ + { + "validValues": [ + "dhcpv6-stateful", + "dhcpv6-stateless", + "slaac" + ] + } + ], + "type": "string", + "required": true, + "definition": false, + "password": false, + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + "toscaPresentation": {} + }, + "password": false, + "name": "value_specs", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.allocation_pools", + "type": "list", + "required": false, + "definition": false, + "description": "The start and end addresses for the allocation pools", + "schema": { + "property": { + "type": "string", + "required": true, + "definition": false, + "password": false, + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + "toscaPresentation": {} + }, + "password": false, + "name": "allocation_pools", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.subnetpool", + "type": "string", + "required": false, + "definition": false, + "description": "The name or ID of the subnet pool", + "password": false, + "name": "subnetpool", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.dns_nameservers", + "type": "list", + "required": false, + "definition": false, + "defaultValue": "[]", + "description": "A specified set of DNS name servers to be used", + "schema": { + "property": { + "type": "string", + "required": true, + "definition": false, + "password": false, + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + "toscaPresentation": {} + }, + "password": false, + "name": "dns_nameservers", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.host_routes", + "type": "list", + "required": false, + "definition": false, + "description": "The gateway IP address", + "schema": { + "property": { + "type": "org.openecomp.datatypes.heat.network.subnet.HostRoute", + "required": true, + "definition": false, + "password": false, + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + "toscaPresentation": {} + }, + "password": false, + "name": "host_routes", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "constraints": [ + { + "validValues": [ + "4", + "6" + ] + } + ], + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.ip_version", + "type": "integer", + "required": false, + "definition": false, + "defaultValue": "4", + "description": "The gateway IP address", + "password": false, + "name": "ip_version", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.name", + "type": "string", + "required": false, + "definition": false, + "description": "The name of the subnet", + "password": false, + "name": "name", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "constraints": [ + { + "greaterOrEqual": "0" + }, + { + "validValues": [ + "4", + "6" + ] + } + ], + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.prefixlen", + "type": "integer", + "required": false, + "definition": false, + "description": "Prefix length for subnet allocation from subnet pool", + "password": false, + "name": "prefixlen", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.cidr", + "type": "string", + "required": false, + "definition": false, + "description": "The CIDR", + "password": false, + "name": "cidr", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + { + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.gateway_ip", + "type": "string", + "required": false, + "definition": false, + "description": "The gateway IP address", + "password": false, + "name": "gateway_ip", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + } + ], + "name": "org.openecomp.datatypes.heat.network.neutron.Subnet", + "uniqueId": "org.openecomp.datatypes.heat.network.neutron.Subnet.datatype", + "derivedFromName": "tosca.datatypes.Root", + "description": "A subnet represents an IP address block that can be used for assigning IP addresses to virtual instances", + "creationTime": 1550136564412, + "modificationTime": 1550136564464, + "toscaPresentation": {} + }, + "org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.MacAddress": { + "derivedFrom": { + "name": "tosca.datatypes.Root", + "uniqueId": "tosca.datatypes.Root.datatype", + "description": "The TOSCA root Data Type all other TOSCA base Data Types derive from", + "creationTime": 1550136563278, + "modificationTime": 1550136563278, + "toscaPresentation": {} + }, + "properties": [ + { + "uniqueId": "org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.MacAddress.datatype.mac_address", + "type": "list", + "required": false, + "definition": false, + "description": "Mac Addresses List.", + "schema": { + "property": { + "type": "string", + "required": true, + "definition": false, + "password": false, + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + "toscaPresentation": {} + }, + "password": false, + "name": "mac_address", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + } + ], + "name": "org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.MacAddress", + "uniqueId": "org.openecomp.datatypes.heat.contrailV2.virtual.machine.subInterface.MacAddress.datatype", + "derivedFromName": "tosca.datatypes.Root", + "description": "Virtual Machine Sub Interface Mac Address.", + "creationTime": 1550136565026, + "modificationTime": 1550136565030, + "toscaPresentation": {} + }, + "org.openecomp.datatypes.heat.contrailV2.network.rule.RuleList": { + "derivedFrom": { + "name": "tosca.datatypes.Root", + "uniqueId": "tosca.datatypes.Root.datatype", + "description": "The TOSCA root Data Type all other TOSCA base Data Types derive from", + "creationTime": 1550136563278, + "modificationTime": 1550136563278, + "toscaPresentation": {} + }, + "properties": [ + { + "uniqueId": "org.openecomp.datatypes.heat.contrailV2.network.rule.RuleList.datatype.network_policy_entries_policy_rule", + "type": "list", + "required": false, + "definition": false, + "description": "Contrail network rule", + "schema": { + "property": { + "type": "org.openecomp.datatypes.heat.contrailV2.network.rule.Rule", + "required": true, + "definition": false, + "password": false, + "hidden": false, + "immutable": false, + "toscaPresentation": {} + }, + "toscaPresentation": {} + }, + "password": false, + "name": "network_policy_entries_policy_rule", + "hidden": false, + "immutable": false, + "toscaPresentation": {} + } + ], + "name": "org.openecomp.datatypes.heat.contrailV2.network.rule.RuleList", + "uniqueId": "org.openecomp.datatypes.heat.contrailV2.network.rule.RuleList.datatype", + "derivedFromName": "tosca.datatypes.Root", + "description": "list of policy rules", + "creationTime": 1550136564716, + "modificationTime": 1550136564720, + "toscaPresentation": {} + }, + "integer": { + "derivedFrom": { + "name": "tosca.datatypes.Root", + "uniqueId": "tosca.datatypes.Root.datatype", + "description": "The TOSCA root Data Type all other TOSCA base Data Types derive from", + "creationTime": 1550136563278, + "modificationTime": 1550136563278, + "toscaPresentation": {} + }, + "name": "integer", + "uniqueId": "integer.datatype", + "derivedFromName": "tosca.datatypes.Root", + "creationTime": 1550136564094, + "modificationTime": 1550136564094, + "toscaPresentation": {} + } +} \ No newline at end of file diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java index 49ee297eca..2a36b05189 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java @@ -21,7 +21,8 @@ package org.openecomp.sdc.be.dao.api; public enum ActionStatus { - OK, ACCEPTED, CREATED, NO_CONTENT, GENERAL_ERROR, NOT_ALLOWED, MISSING_INFORMATION, RESTRICTED_OPERATION, RESTRICTED_ACCESS, INVALID_CONTENT, + OK, ACCEPTED, CREATED, NO_CONTENT, GENERAL_ERROR, NOT_ALLOWED, MISSING_INFORMATION, RESTRICTED_OPERATION, + RESTRICTED_ACCESS, INVALID_CONTENT, INVALID_PROPERTY_VALUES, // User related USER_ALREADY_EXIST, USER_INACTIVE, USER_NOT_FOUND, USER_HAS_ACTIVE_ELEMENTS, INVALID_EMAIL_ADDRESS, INVALID_ROLE, DELETE_USER_ADMIN_CONFLICT, UPDATE_USER_ADMIN_CONFLICT, CANNOT_DELETE_USER_WITH_ACTIVE_ELEMENTS, CANNOT_UPDATE_USER_WITH_ACTIVE_ELEMENTS, INVALID_USER_ID, USER_DEFINED, // CapabilityType related diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/OperationInput.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/OperationInput.java new file mode 100644 index 0000000000..e11bf9620b --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/OperationInput.java @@ -0,0 +1,36 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.model; + +import java.util.List; + +import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition; + +public class OperationInput extends OperationInputDefinition { + private List constraints; + + public OperationInput(OperationInputDefinition operationInputDefinition) { + super(operationInputDefinition); + } + + public List getConstraints() { + return constraints; + } + + public void setConstraints(List constraints) { + this.constraints = constraints; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/PropertyConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/PropertyConstraint.java index 9a5c52dde4..ff9a6e5018 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/PropertyConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/PropertyConstraint.java @@ -21,6 +21,7 @@ package org.openecomp.sdc.be.model; import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; @@ -31,4 +32,6 @@ public interface PropertyConstraint { void validate(Object propertyValue) throws ConstraintViolationException; void validate(ToscaType toscaType, String propertyTextValue) throws ConstraintViolationException; + + String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException exception, String propertyName); } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java index 0ee7c9e5bd..10dd919fc7 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java @@ -955,7 +955,7 @@ public class ToscaOperationFacade { } GraphVertex vertex = getVertexEither.left().value(); - Map inputsMap = inputs.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new PropertyDataDefinition(e.getValue()))); + Map inputsMap = inputs.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new PropertyDefinition(e.getValue()))); StorageOperationStatus status = topologyTemplateOperation.addToscaDataToToscaElement(vertex, EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, inputsMap, JsonPresentationFields.NAME); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaType.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaType.java index 92c564cad6..6384146df9 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaType.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/ToscaType.java @@ -20,9 +20,17 @@ package org.openecomp.sdc.be.model.tosca; +import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; +import java.util.List; import java.util.Locale; +import java.util.Map; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; +import org.openecomp.sdc.be.model.tosca.constraints.ConstraintUtil; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; /** * The primitive type that TOSCA YAML supports. @@ -30,31 +38,101 @@ import java.util.Locale; * @author mkv */ public enum ToscaType { - STRING, INTEGER, FLOAT, BOOLEAN, TIMESTAMP, VERSION; - - public boolean isValidValue(String value) { - switch (this) { - case BOOLEAN: - return value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false"); - case FLOAT: - return isFloat(value); - case INTEGER: - return isInteger(value); - case STRING: - return true; - case TIMESTAMP: - try { - DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US).parse(value); - return true; - } catch (ParseException e) { - return false; - } - case VERSION: - return VersionUtil.isValid(value); - default: - return false; - } - } + STRING("string"), + INTEGER("integer"), + FLOAT("float"), + BOOLEAN("boolean"), + TIMESTAMP("timestamp"), + VERSION("version"), + LIST("list"), + MAP("map"), + SCALAR_UNIT("scalar-unit"), + SCALAR_UNIT_SIZE("scalar-unit.size"), + SCALAR_UNIT_TIME("scalar-unit.time"), + SCALAR_UNIT_FREQUENCY("scalar-unit.frequency"); + + private String type; + + ToscaType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public ToscaType getToscaType(String typeName) { + if (typeName == null) { + return null; + } + + for (ToscaType type : ToscaType.values()) { + if (type.getType().equals(typeName)) { + return type; + } + } + return null; + } + + public boolean isValidValue(String value) { + switch (this) { + case BOOLEAN: + return value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false"); + case FLOAT: + return isFloat(value); + case INTEGER: + return isInteger(value); + case STRING: + case SCALAR_UNIT: + case SCALAR_UNIT_SIZE: + case SCALAR_UNIT_TIME: + case SCALAR_UNIT_FREQUENCY: + return true; + case TIMESTAMP: + try { + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US).parse(value); + return true; + } catch (ParseException e) { + return false; + } + case VERSION: + return VersionUtil.isValid(value); + case LIST: + return isList(value); + case MAP: + return isMap(value); + default: + return false; + } + } + + private boolean isList(String value) { + ObjectMapper objectMapper = new ObjectMapper(); + try { + objectMapper.readValue(value, + new TypeReference>() { + }); + + } catch (IOException e) { + return false; + } + + return true; + } + + private boolean isMap(String value) { + ObjectMapper objectMapper = new ObjectMapper(); + try { + objectMapper.readValue(value, + new TypeReference>() { + }); + + } catch (IOException e) { + return false; + } + + return true; + } private boolean isFloat(String value) { try { @@ -74,31 +152,76 @@ public enum ToscaType { return true; } - public Object convert(String value) { - switch (this) { - case STRING: - return value; - case BOOLEAN: - return Boolean.valueOf(value); - case FLOAT: - return Double.valueOf(value); - case INTEGER: - return Long.valueOf(value); - case TIMESTAMP: - try { - return DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US).parse(value); - } catch (ParseException e) { - throw new IllegalArgumentException("Value must be a valid timestamp", e); - } - case VERSION: - return VersionUtil.parseVersion(value); - default: - return null; - } - } + public Object convert(String value) { + switch (this) { + case STRING: + case SCALAR_UNIT: + case SCALAR_UNIT_SIZE: + case SCALAR_UNIT_TIME: + case SCALAR_UNIT_FREQUENCY: + return value; + case BOOLEAN: + return Boolean.valueOf(value); + case FLOAT: + return Double.valueOf(value); + case INTEGER: + return Long.valueOf(value); + case TIMESTAMP: + try { + return DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US).parse(value); + } catch (ParseException e) { + throw new IllegalArgumentException("Value must be a valid timestamp", e); + } + case VERSION: + return VersionUtil.parseVersion(value); + case LIST: + try { + return ConstraintUtil.parseToCollection(value, new TypeReference>() {}); + } catch (ConstraintValueDoNotMatchPropertyTypeException e) { + throw new IllegalArgumentException("Value must be a valid timestamp", e); + } + case MAP: + try { + return ConstraintUtil.parseToCollection(value, new TypeReference>() {}); + } catch (ConstraintValueDoNotMatchPropertyTypeException e) { + throw new IllegalArgumentException("Value must be a valid timestamp", e); + } + default: + return null; + } + } + + public static boolean isPrimitiveType(String dataTypeName) { - @Override + if (!ToscaPropertyType.MAP.getType().equals(dataTypeName) && !ToscaPropertyType.LIST.getType() + .equals(dataTypeName)) { + + return isValidType(dataTypeName) != null; + } + + return false; + } + + public static ToscaType isValidType(String typeName) { + if (typeName == null) { + return null; + } + + for (ToscaType type : ToscaType.values()) { + if (type.getType().equals(typeName)) { + return type; + } + } + return null; + } + + @Override public String toString() { return name().toLowerCase(); } + + public static boolean isCollectionType(String type) { + return ToscaPropertyType.MAP.getType().equals(type) + || ToscaPropertyType.LIST.getType().equals(type); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractPropertyConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractPropertyConstraint.java index fc96373d62..041a86d283 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractPropertyConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/AbstractPropertyConstraint.java @@ -20,13 +20,20 @@ package org.openecomp.sdc.be.model.tosca.constraints; +import java.util.Arrays; + import org.openecomp.sdc.be.model.PropertyConstraint; import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; import org.openecomp.sdc.be.model.tosca.version.ApplicationVersionException; public abstract class AbstractPropertyConstraint implements PropertyConstraint { + private static final String INVALID_VALUE_ERROR_MESSAGE = + "Unsupported value provided for %s property supported value type is %s."; + @Override public void validate(ToscaType toscaType, String propertyTextValue) throws ConstraintViolationException { try { @@ -36,4 +43,21 @@ public abstract class AbstractPropertyConstraint implements PropertyConstraint { "String value [" + propertyTextValue + "] is not valid for type [" + toscaType + "]", e); } } + + public String getErrorMessage(ToscaType toscaType, + ConstraintFunctionalException e, + String propertyName, + String errorMessage, + String... propertyValue) { + if (e instanceof ConstraintViolationException) { + return String.format(errorMessage, propertyName, Arrays.toString(propertyValue)); + } + + return String.format(INVALID_VALUE_ERROR_MESSAGE, propertyName, toscaType.getType()); + } + + @Override + public void initialize(ToscaType propertyType) throws ConstraintValueDoNotMatchPropertyTypeException { + //Initialization not needed for few constraints for now might be needed in future + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintType.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintType.java index 6fb699124a..d1cc766525 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintType.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintType.java @@ -25,9 +25,9 @@ import java.util.List; public enum ConstraintType { - EQUAL("equal", "equal"), + EQUAL("equal", "equal"), - IN_RANGE("inRange"), + IN_RANGE("inRange","in_range"), GREATER_THAN("greaterThan", "greater_than"), @@ -35,11 +35,17 @@ public enum ConstraintType { LESS_OR_EQUAL("lessOrEqual", "less_or_equal"), + LENGTH("length", "length"), + MIN_LENGTH("minLength", "min_length"), + MAX_LENGTH("maxLength", "max_length"), + VALID_VALUES("validValues", "valid_values"), - LESS_THAN("lessThan", "less_than"); + LESS_THAN("lessThan", "less_than"), + + SCHEMA("schema", "schema"); List types; diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintUtil.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintUtil.java index 3c1f0ab711..0bbc0f755f 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintUtil.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ConstraintUtil.java @@ -20,19 +20,26 @@ package org.openecomp.sdc.be.model.tosca.constraints; -import org.openecomp.sdc.be.model.tosca.ToscaType; -import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; - import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; +import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Utility class to validate constraints types. */ public final class ConstraintUtil { + private static final Logger logger = LoggerFactory.getLogger(ConstraintUtil.class); + private ConstraintUtil() { } @@ -46,7 +53,7 @@ public final class ConstraintUtil { * In case the type is not {@link ToscaType#STRING}. */ public static void checkStringType(ToscaType propertyType) throws ConstraintValueDoNotMatchPropertyTypeException { - if (!ToscaType.STRING.equals(propertyType)) { + if (ToscaType.STRING != propertyType) { throw new ConstraintValueDoNotMatchPropertyTypeException( "Invalid property type <" + propertyType.toString() + ">"); } @@ -95,8 +102,7 @@ public final class ConstraintUtil { * if the converted value is not a comparable */ @SuppressWarnings("rawtypes") - public static Comparable convertToComparable(ToscaType propertyType, String value) - throws ConstraintValueDoNotMatchPropertyTypeException { + public static Comparable convertToComparable(ToscaType propertyType, String value) { Object comparableObj = propertyType.convert(value); if (!(comparableObj instanceof Comparable)) { throw new IllegalArgumentException( @@ -142,4 +148,18 @@ public final class ConstraintUtil { throw new IntrospectionException("Cannot retrieve constraint reference " + e.getMessage()); } } + + public static T parseToCollection(String value, TypeReference typeReference) + throws ConstraintValueDoNotMatchPropertyTypeException { + T objectMap; + ObjectMapper objectMapper = new ObjectMapper(); + try { + objectMap = objectMapper.readValue(value, typeReference); + } catch (IOException e) { + logger.error(e.getMessage(), e); + throw new ConstraintValueDoNotMatchPropertyTypeException("The value [" + value + "] is not valid"); + } + + return objectMap; + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/EqualConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/EqualConstraint.java index 7ae64e0ccf..206fc3dc82 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/EqualConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/EqualConstraint.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,34 +20,41 @@ package org.openecomp.sdc.be.model.tosca.constraints; +import java.io.Serializable; + import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; import javax.validation.constraints.NotNull; -public class EqualConstraint extends AbstractPropertyConstraint { - - @NotNull - private String equal; +@SuppressWarnings("serial") +public class EqualConstraint extends AbstractPropertyConstraint implements Serializable { - // @JsonIgnore + @NotNull + private String constraintValue; private Object typed; - public EqualConstraint(String equal) { - super(); - this.equal = equal; - } + public EqualConstraint(String constraintValue) { + super(); + this.constraintValue = constraintValue; + } - @Override - public void initialize(ToscaType propertyType) throws ConstraintValueDoNotMatchPropertyTypeException { - if (propertyType.isValidValue(equal)) { - typed = propertyType.convert(equal); - } else { - throw new ConstraintValueDoNotMatchPropertyTypeException("equal constraint has invalid value <" + equal - + "> property type is <" + propertyType.toString() + ">"); - } - } + public String getConstraintValue() { + return constraintValue; + } + + @Override + public void initialize(ToscaType propertyType) throws ConstraintValueDoNotMatchPropertyTypeException { + if (propertyType.isValidValue(constraintValue)) { + typed = propertyType.convert(constraintValue); + } else { + throw new ConstraintValueDoNotMatchPropertyTypeException( + "constraintValue constraint has invalid value <" + constraintValue + + "> property type is <" + propertyType.toString() + ">"); + } + } @Override public void validate(Object propertyValue) throws ConstraintViolationException { @@ -57,13 +64,20 @@ public class EqualConstraint extends AbstractPropertyConstraint { } } else if (typed == null) { fail(propertyValue); + } else if (typed instanceof Comparable && typed != propertyValue) { + fail(propertyValue); } else if (!typed.equals(propertyValue)) { fail(propertyValue); } } - private void fail(Object propertyValue) throws ConstraintViolationException { - throw new ConstraintViolationException("Equal constraint violation, the reference is <" + equal - + "> but the value to compare is <" + propertyValue + ">"); + private void fail(Object propertyValue) throws ConstraintViolationException { + throw new ConstraintViolationException("Equal constraint violation, the reference is <" + constraintValue + + "> but the value to compare is <" + propertyValue + ">"); + } + + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%s property value must be %s", constraintValue); } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/GreaterOrEqualConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/GreaterOrEqualConstraint.java index 63d7ed8872..6549bbc432 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/GreaterOrEqualConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/GreaterOrEqualConstraint.java @@ -21,6 +21,7 @@ package org.openecomp.sdc.be.model.tosca.constraints; import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; @@ -46,4 +47,9 @@ public class GreaterOrEqualConstraint extends AbstractComparablePropertyConstrai throw new ConstraintViolationException(propertyValue + " <= " + greaterOrEqual); } } + + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%f property value must be >= %f", greaterOrEqual); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/GreaterThanConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/GreaterThanConstraint.java index b599a16a10..a278e8c7b9 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/GreaterThanConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/GreaterThanConstraint.java @@ -21,6 +21,7 @@ package org.openecomp.sdc.be.model.tosca.constraints; import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; @@ -28,13 +29,13 @@ import javax.validation.constraints.NotNull; public class GreaterThanConstraint extends AbstractComparablePropertyConstraint { + @NotNull + private String greaterThan; + public GreaterThanConstraint(String greaterThan) { this.greaterThan = greaterThan; } - @NotNull - private String greaterThan; - @Override public void initialize(ToscaType propertyType) throws ConstraintValueDoNotMatchPropertyTypeException { initialize(greaterThan, propertyType); @@ -55,4 +56,8 @@ public class GreaterThanConstraint extends AbstractComparablePropertyConstraint this.greaterThan = greaterThan; } + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%f property value must be > %f", greaterThan); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/InRangeConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/InRangeConstraint.java index 19a2fe4230..ad3d3525d0 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/InRangeConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/InRangeConstraint.java @@ -21,12 +21,15 @@ package org.openecomp.sdc.be.model.tosca.constraints; import com.google.common.collect.Lists; + +import java.util.List; + import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; import javax.validation.constraints.NotNull; -import java.util.List; public class InRangeConstraint extends AbstractPropertyConstraint { @@ -111,4 +114,10 @@ public class InRangeConstraint extends AbstractPropertyConstraint { } } + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%f property value must be between >= [%s] and <= [%s]", + String.valueOf(min), String.valueOf(max)); + } + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LengthConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LengthConstraint.java index c07ac7e2e3..0c5317b10b 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LengthConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LengthConstraint.java @@ -20,22 +20,42 @@ package org.openecomp.sdc.be.model.tosca.constraints; +import java.util.List; +import java.util.Map; + +import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; import javax.validation.constraints.NotNull; -public class LengthConstraint extends AbstractStringPropertyConstraint { +public class LengthConstraint extends AbstractPropertyConstraint { @NotNull private Integer length; - @Override - protected void doValidate(String propertyValue) throws ConstraintViolationException { - if (propertyValue.length() != length) { + protected void doValidate(Object propertyValue) throws ConstraintViolationException { + if (propertyValue instanceof String && String.valueOf(propertyValue).length() != length) { throw new ConstraintViolationException("The length of the value is not equals to [" + length + "]"); + } else if (propertyValue instanceof List && ((List) propertyValue).size() != length) { + throw new ConstraintViolationException("The size of the list is not equals to [" + length + "]"); + } else if (propertyValue instanceof Map && ((Map) propertyValue).size() != length) { + throw new ConstraintViolationException("The size of the map is not equals to [" + length + "]"); } } + public void validate(Object propertyValue) throws ConstraintViolationException { + if (propertyValue == null) { + throw new ConstraintViolationException("Value to validate is null"); + } + + if(!(propertyValue instanceof String || propertyValue instanceof List || propertyValue instanceof Map)) { + throw new ConstraintViolationException("This constraint can only be applied on String/List/Map value"); + } + + doValidate(propertyValue); + } + public Integer getLength() { return length; } @@ -44,4 +64,9 @@ public class LengthConstraint extends AbstractStringPropertyConstraint { this.length = length; } + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%s length must be %s", String.valueOf(length)); + } + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessOrEqualConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessOrEqualConstraint.java index 7d61dd31df..3f085ec596 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessOrEqualConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessOrEqualConstraint.java @@ -21,6 +21,7 @@ package org.openecomp.sdc.be.model.tosca.constraints; import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; @@ -30,7 +31,6 @@ public class LessOrEqualConstraint extends AbstractComparablePropertyConstraint @NotNull private String lessOrEqual; - public LessOrEqualConstraint(String lessOrEqual) { this.lessOrEqual = lessOrEqual; } @@ -55,4 +55,8 @@ public class LessOrEqualConstraint extends AbstractComparablePropertyConstraint this.lessOrEqual = lessOrEqual; } + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%s property value must be <= %s", lessOrEqual); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessThanConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessThanConstraint.java index e2db77b45a..01eb6cdc32 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessThanConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/LessThanConstraint.java @@ -21,6 +21,7 @@ package org.openecomp.sdc.be.model.tosca.constraints; import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; @@ -47,4 +48,8 @@ public class LessThanConstraint extends AbstractComparablePropertyConstraint { } } + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%s value must be < %s", lessThan); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/MaxLengthConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/MaxLengthConstraint.java index 8b7ce49cbc..c8fef91ea6 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/MaxLengthConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/MaxLengthConstraint.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,11 +20,16 @@ package org.openecomp.sdc.be.model.tosca.constraints; +import java.util.List; +import java.util.Map; + +import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; import javax.validation.constraints.NotNull; -public class MaxLengthConstraint extends AbstractStringPropertyConstraint { +public class MaxLengthConstraint extends AbstractPropertyConstraint { @NotNull private Integer maxLength; @@ -37,10 +42,13 @@ public class MaxLengthConstraint extends AbstractStringPropertyConstraint { super(); } - @Override - protected void doValidate(String propertyValue) throws ConstraintViolationException { - if (propertyValue.length() > maxLength) { + protected void doValidate(Object propertyValue) throws ConstraintViolationException { + if (propertyValue instanceof String && String.valueOf(propertyValue).length() > maxLength) { throw new ConstraintViolationException("The length of the value is greater than [" + maxLength + "]"); + } else if (propertyValue instanceof List && ((List) propertyValue).size() > maxLength) { + throw new ConstraintViolationException("The size of the list is greater than [" + maxLength + "]"); + } else if (propertyValue instanceof Map && ((Map) propertyValue).size() > maxLength) { + throw new ConstraintViolationException("The size of the map is greater than [" + maxLength + "]"); } } @@ -51,4 +59,22 @@ public class MaxLengthConstraint extends AbstractStringPropertyConstraint { public void setMaxLength(Integer maxLength) { this.maxLength = maxLength; } + + @Override + public void validate(Object propertyValue) throws ConstraintViolationException { + if (propertyValue == null) { + throw new ConstraintViolationException("Value to validate is null"); + } + + if(!(propertyValue instanceof String || propertyValue instanceof List || propertyValue instanceof Map)) { + throw new ConstraintViolationException("This constraint can only be applied on String/List/Map value"); + } + + doValidate(propertyValue); + } + + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%s maximum length must be [%s]", String.valueOf(maxLength)); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/MinLengthConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/MinLengthConstraint.java index bc51f4fa5a..4f55970d79 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/MinLengthConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/MinLengthConstraint.java @@ -20,11 +20,16 @@ package org.openecomp.sdc.be.model.tosca.constraints; +import java.util.List; +import java.util.Map; + +import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; import javax.validation.constraints.NotNull; -public class MinLengthConstraint extends AbstractStringPropertyConstraint { +public class MinLengthConstraint extends AbstractPropertyConstraint { @NotNull private Integer minLength; @@ -37,10 +42,13 @@ public class MinLengthConstraint extends AbstractStringPropertyConstraint { super(); } - @Override - protected void doValidate(String propertyValue) throws ConstraintViolationException { - if (propertyValue.length() < minLength) { + protected void doValidate(Object propertyValue) throws ConstraintViolationException { + if (propertyValue instanceof String && String.valueOf(propertyValue).length() < minLength) { throw new ConstraintViolationException("The length of the value is less than [" + minLength + "]"); + } else if (propertyValue instanceof List && ((List) propertyValue).size() < minLength) { + throw new ConstraintViolationException("The size of the list is less than [" + minLength + "]"); + } else if (propertyValue instanceof Map && ((Map) propertyValue).size() < minLength) { + throw new ConstraintViolationException("The size of the map is less than [" + minLength + "]"); } } @@ -52,4 +60,19 @@ public class MinLengthConstraint extends AbstractStringPropertyConstraint { this.minLength = minLength; } + @Override + public void validate(Object propertyValue) throws ConstraintViolationException { + if (propertyValue == null) { + throw new ConstraintViolationException("Value to validate is null"); + } + if(!(propertyValue instanceof String || propertyValue instanceof List || propertyValue instanceof Map)) { + throw new ConstraintViolationException("This constraint can only be applied on String/List/Map value"); + } + doValidate(propertyValue); + } + + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%s minimum length must be [%s]", String.valueOf(minLength)); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/PatternConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/PatternConstraint.java index db26c33440..d3644c578d 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/PatternConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/PatternConstraint.java @@ -20,10 +20,13 @@ package org.openecomp.sdc.be.model.tosca.constraints; +import java.util.regex.Pattern; + +import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; import javax.validation.constraints.NotNull; -import java.util.regex.Pattern; public class PatternConstraint extends AbstractStringPropertyConstraint { @@ -43,4 +46,10 @@ public class PatternConstraint extends AbstractStringPropertyConstraint { throw new ConstraintViolationException("The value do not match pattern " + pattern); } } + + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%s property value must match the regular expression %s", + pattern); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ValidValuesConstraint.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ValidValuesConstraint.java index 0b35a9be8e..1ddf9c9e0e 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ValidValuesConstraint.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/tosca/constraints/ValidValuesConstraint.java @@ -21,13 +21,16 @@ package org.openecomp.sdc.be.model.tosca.constraints; import com.google.common.collect.Sets; + +import java.util.List; +import java.util.Set; + import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintFunctionalException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintViolationException; import javax.validation.constraints.NotNull; -import java.util.List; -import java.util.Set; public class ValidValuesConstraint extends AbstractPropertyConstraint { @@ -77,4 +80,9 @@ public class ValidValuesConstraint extends AbstractPropertyConstraint { this.validValues = validValues; } + @Override + public String getErrorMessage(ToscaType toscaType, ConstraintFunctionalException e, String propertyName) { + return getErrorMessage(toscaType, e, propertyName, "%s valid value must be one of the following: [%s]", + String.join(",", validValues)); + } } diff --git a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts index aa68551950..a1a85aa73d 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts @@ -28,12 +28,12 @@ export enum DerivedPropertyType { } export class PropertyBEModel { - + constraints: Array; defaultValue: string; definition: boolean; description: string; fromDerived: boolean; - getInputValues: Array + getInputValues: Array; name: string; parentUniqueId: string; password: boolean; @@ -43,9 +43,12 @@ export class PropertyBEModel { type: string; uniqueId: string; value: string; + parentPropertyType: string; + subPropertyInputPath: string; constructor(property?: PropertyBEModel) { if (property) { + this.constraints = property.constraints; this.defaultValue = property.defaultValue; this.description = property.description; this.fromDerived = property.fromDerived; @@ -60,6 +63,8 @@ export class PropertyBEModel { this.value = property.value; this.definition = property.definition; this.getInputValues = property.getInputValues; + this.parentPropertyType = property.parentPropertyType; + this.subPropertyInputPath = property.subPropertyInputPath; } if (!this.schema || !this.schema.property) { diff --git a/catalog-ui/src/app/models/properties.ts b/catalog-ui/src/app/models/properties.ts index a629140cb8..016c5b9f20 100644 --- a/catalog-ui/src/app/models/properties.ts +++ b/catalog-ui/src/app/models/properties.ts @@ -40,7 +40,6 @@ export class PropertiesGroup { export interface IPropertyModel extends InputPropertyBase { //server data - constraints:Array; source:string; //instance properties @@ -60,7 +59,6 @@ export class PropertyModel extends PropertyBEModel implements IPropertyModel { //server data uniqueId:string; name:string; - constraints:Array; defaultValue:string; description:string; password:boolean; @@ -93,7 +91,6 @@ export class PropertyModel extends PropertyBEModel implements IPropertyModel { constructor(property?:PropertyModel) { super(property); if (property) { - this.constraints = property.constraints; this.source = property.source; this.valueUniqueUid = property.valueUniqueUid; this.path = property.path; diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html index 65873a35a5..3ef1f57bf2 100644 --- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html @@ -57,6 +57,7 @@ pattern="validationUtils.getValidationPattern(input.type)" [value]="input.defaultValueObj" [type]="input.type" + [constraints]="input.constraints" [name]="input.name" (elementChanged)="onInputChanged(input, $event)" [readonly]="readonly" diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html index 3f87b070e8..c4639aeda0 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html @@ -51,6 +51,7 @@ [childType]="property.schema.property.type" [name]="property.name" [path]="property.propertiesName" + [constraints]="property.constraints" (elementChanged)="onElementChanged($event)" [readonly]="readonly || property.isDeclared || property.isDisabled" [testId]="'prop-' + propertyTestsId" diff --git a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts index b0f6dfb649..ef8d63df97 100644 --- a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts @@ -39,6 +39,7 @@ export class ConsumptionInput extends PropertyFEModel{ type: string; source: string; value: any; + constraints: Array; constructor(input?: any) { super(input); @@ -47,6 +48,7 @@ export class ConsumptionInput extends PropertyFEModel{ this.type = input.type; this.source = input.source; this.value = input.value || ""; + this.constraints = input.constraints; } } } diff --git a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts index 4f283fb3f1..049d40831a 100644 --- a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts @@ -22,7 +22,7 @@ import * as _ from "lodash"; import { Component, Compiler, EventEmitter, ViewContainerRef, ViewChild, Input, Output, ElementRef, ComponentRef, ComponentFactoryResolver } from '@angular/core' -import {ValidationConfiguration} from "app/models"; +import {ValidationConfiguration, PropertyFEModel} from "app/models"; import {IUiElementChangeEvent} from "../form-components/ui-element-base.component"; import {UiElementInputComponent} from "../form-components/input/ui-element-input.component"; import {UiElementPopoverInputComponent} from "../form-components/popover-input/ui-element-popover-input.component"; @@ -36,6 +36,7 @@ enum DynamicElementComponentCreatorIdentifier { FLOAT, BOOLEAN, SUBNETPOOLID, + ENUM, DEFAULT } @@ -58,6 +59,7 @@ export class DynamicElementComponent { @Input() name: string; @Input() testId: string; @Input() readonly:boolean; + @Input() constraints: Array; @Input() path:string;//optional param. used only for for subnetpoolid type @Input() value: any; @@ -86,6 +88,9 @@ export class DynamicElementComponent { case this.path && this.path.toUpperCase().indexOf("SUBNETPOOLID") !== -1: this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.SUBNETPOOLID; break; + case this.getValidValues() !== undefined && this.getValidValues() !== null: + this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.ENUM; + break; case this.type === 'integer': this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.INTEGER; break; @@ -153,6 +158,19 @@ export class DynamicElementComponent { this.createComponent(UiElementPopoverInputComponent); break; + case DynamicElementComponentCreatorIdentifier.ENUM: + this.createComponent(UiElementDropDownComponent); + let validVals:Array = [...this.getValidValues()].map(val => new DropdownValue(val, val)); + if (this.type === 'float' || this.type === 'integer') { + this.value = this.value && Number(this.value); + validVals = _.map( + validVals, + val => new DropdownValue(Number(val.value), val.value) + ); + } + this.cmpRef.instance.values = validVals; + break; + case DynamicElementComponentCreatorIdentifier.INTEGER: this.createComponent(UiElementIntegerInputComponent); this.cmpRef.instance.pattern = this.validation.validationPatterns.integer; @@ -195,6 +213,14 @@ export class DynamicElementComponent { this.cmpRef.instance.valueChange.subscribe((event) => { this.valueChange.emit(event); }); } + getValidValues(): Array { + let validVals; + _.forEach(this.constraints, constraint => { + validVals = validVals || constraint.validValues; + }); + return validVals; + } + createComponent(ComponentToCreate:any):void { let factory = this.componentFactoryResolver.resolveComponentFactory(ComponentToCreate); this.cmpRef = this.target.createComponent(factory); diff --git a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts index 9035b3ff50..97c7b4d959 100644 --- a/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/interface-operation/interface-operation.page.component.ts @@ -136,7 +136,7 @@ export class InterfaceOperationComponent { ngOnInit(): void { this.isLoading = true; - this.workflowIsOnline = !_.isUndefined(this.PluginsService.getPluginByStateUrl('workflowDesigner')); + this.workflowIsOnline = false;//!_.isUndefined(this.PluginsService.getPluginByStateUrl('workflowDesigner')); const workflowSubscription = this.enableWorkflowAssociation && this.workflowIsOnline ? this.WorkflowServiceNg2.getWorkflows() : Promise.resolve(); Observable.forkJoin( this.ComponentServiceNg2.getInterfaces(this.component), diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts index 953c973d1a..615325559e 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts @@ -126,7 +126,7 @@ export class PropertiesAssignmentComponent { this.loadingInstances = true; this.loadingProperties = true; this.componentServiceNg2 - .getComponentInputs(this.component) + .getComponentInputsWithProperties(this.component) .subscribe(response => { _.forEach(response.inputs, (input: InputBEModel) => { const newInput: InputFEModel = new InputFEModel(input); @@ -468,7 +468,10 @@ export class PropertiesAssignmentComponent { }; } else { if (this.isSelf()) { - request = this.componentServiceNg2.updateServiceProperties(this.component, changedProperties); + request = this.componentServiceNg2.updateServiceProperties(this.component, _.map(changedProperties, cp => { + delete cp.constraints; + return cp; + })); } else { request = this.componentInstanceServiceNg2 .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedProperties); diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts index d5946d2e4a..7d76904539 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts @@ -46,7 +46,8 @@ export class PropertyCreatorComponent { let nonPrimitiveTypesValues = _.map(nonPrimitiveTypes, (type: string) => new DropdownValue(type, type.replace("org.openecomp.datatypes.heat.","")) - ); + ) + .sort((a, b) => a.label.localeCompare(b.label)); this.typesProperties = _.concat(this.typesProperties,nonPrimitiveTypesValues); this.typesSchemaProperties = _.concat(typesSimpleProperties,nonPrimitiveTypesValues); this.typesProperties.unshift(new DropdownValue('','Select Type...')); diff --git a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html index 5d42fa7694..e77d880176 100644 --- a/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html +++ b/catalog-ui/src/app/ng2/pages/service-consumption-editor/service-consumption-editor.component.html @@ -52,6 +52,7 @@ *ngIf="consumptionInput.isSimpleType && (consumptionInput.source === SOURCE_TYPES.STATIC || consumptionInput.source === '')" data-tests-id="inputValue" [(value)]="consumptionInput.value" + [constraints]="consumptionInput.constraints" (elementChanged)="onChange($event.value, $event.isValid, consumptionInput)" [type]="consumptionInput.type"> diff --git a/catalog-ui/src/app/ng2/services/component-services/component.service.ts b/catalog-ui/src/app/ng2/services/component-services/component.service.ts index a25fb75a41..3243291483 100644 --- a/catalog-ui/src/app/ng2/services/component-services/component.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/component.service.ts @@ -108,6 +108,10 @@ export class ComponentServiceNg2 { return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INPUTS]); } + getComponentInputsWithProperties(component:Component):Observable { + return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INPUTS, COMPONENT_FIELDS.COMPONENT_INSTANCES, COMPONENT_FIELDS.COMPONENT_INSTANCES_PROPERTIES, COMPONENT_FIELDS.COMPONENT_PROPERTIES]); + } + getComponentDeploymentArtifacts(component:Component):Observable { return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_DEPLOYMENT_ARTIFACTS]); } diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInputDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInputDefinition.java index 1e8ef50564..ab3f536d63 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInputDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInputDefinition.java @@ -38,6 +38,13 @@ public class OperationInputDefinition extends InputDataDefinition { setSourceProperty(sourceProperty); } + public OperationInputDefinition(OperationInputDefinition oid) { + super(oid); + setName(oid.getName()); + setSource(oid.getSource()); + setSourceProperty(oid.getSourceProperty()); + } + public OperationInputDefinition(String name, String property, Boolean mandatory, String type) { super(); setName(name); diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/PropertyDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/PropertyDataDefinition.java index c4a78433f5..88863b2cf5 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/PropertyDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/PropertyDataDefinition.java @@ -59,6 +59,8 @@ public class PropertyDataDefinition extends ToscaDataDefinition { private String inputId; private String instanceUniqueId; private String propertyId; + private String parentPropertyType; + private String subPropertyInputPath; private List annotations; /** @@ -100,11 +102,29 @@ public class PropertyDataDefinition extends ToscaDataDefinition { this.setInputId(p.getInputId()); this.setInstanceUniqueId(p.getInstanceUniqueId()); this.setPropertyId(p.getPropertyId()); + this.setParentPropertyType(p.getParentPropertyType()); + this.setSubPropertyInputPath(p.getSubPropertyInputPath()); if(isNotEmpty(p.annotations)){ this.setAnnotations(p.annotations); } } + public String getParentPropertyType() { + return parentPropertyType; + } + + public void setParentPropertyType(String parentPropertyType) { + this.parentPropertyType = parentPropertyType; + } + + public String getSubPropertyInputPath() { + return subPropertyInputPath; + } + + public void setSubPropertyInputPath(String subPropertyInputPath) { + this.subPropertyInputPath = subPropertyInputPath; + } + public String getInputPath() { return inputPath; } @@ -285,7 +305,9 @@ public class PropertyDataDefinition extends ToscaDataDefinition { public String toString() { return "PropertyDataDefinition [uniqueId=" + uniqueId + ", type=" + type + ", required=" + required + ", definition=" + definition + ", defaultValue=" + defaultValue + ", description=" + description + ", schema=" + schema + ", password=" + password + ", name=" + name + ", value=" + value + ", label=" + label + ", hidden=" + hidden + ", immutable=" + immutable + ", inputPath=" + inputPath + ", status=" + status + ", inputId=" + inputId + ", instanceUniqueId=" - + instanceUniqueId + ", propertyId=" + propertyId + ", parentUniqueId=" + parentUniqueId + ", getInputValues=" + getInputValues + "]"; + + instanceUniqueId + ", propertyId=" + propertyId + ", parentUniqueId=" + parentUniqueId + ", getInputValues=" + getInputValues + + "parentPropertyType" + parentPropertyType + + "subPropertyInputPath" + subPropertyInputPath +"]"; } @Override diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java index ad699d07ae..f85f326f03 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java @@ -361,6 +361,7 @@ public interface Urls { final String GET_MODULE_BY_ID = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/resources/%s/groups/%s"; // inputs + final String UPDATE_INPUTS = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/update/inputs"; final String ADD_INPUTS = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/create/inputs"; //{componentType}/{componentId}/create/inputs final String DELETE_INPUT_BY_ID = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/delete/%s/input"; //{componentType}/{componentId}/delete/{inputId}/input final String GET_COMPONENT_INPUTS = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/services/%s/inputs"; //services/{componentId}/inputs diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/PropertyReqDetails.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/PropertyReqDetails.java index 0898206002..64086884fa 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/PropertyReqDetails.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/PropertyReqDetails.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,6 +23,7 @@ package org.openecomp.sdc.ci.tests.datatypes; import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition; public class PropertyReqDetails { + String name; String type; Boolean required = false; @@ -32,14 +33,18 @@ public class PropertyReqDetails { String propertyRangeMax; Boolean isPassword = false; SchemaDefinition schema; + String uniqueId; + String parentUniqueId; + String value; public PropertyReqDetails() { super(); } public PropertyReqDetails(String propertyName, String propertyType, Boolean propertyRequired, - String propertyDefaultValue, String propertyDescription, String propertyRangeMin, String propertyRangeMax, - Boolean propertyPassword) { + String propertyDefaultValue, String propertyDescription, String propertyRangeMin, + String propertyRangeMax, + Boolean propertyPassword) { super(); this.name = propertyName; this.type = propertyType; @@ -52,7 +57,7 @@ public class PropertyReqDetails { } public PropertyReqDetails(String propertyName, String propertyType, String propertyDefaultValue, - String propertyDescription, SchemaDefinition schema) { + String propertyDescription, SchemaDefinition schema) { super(); this.name = propertyName; this.type = propertyType; @@ -133,14 +138,42 @@ public class PropertyReqDetails { this.isPassword = propertyPassword; } + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } + + public String getParentUniqueId() { + return parentUniqueId; + } + + public void setParentUniqueId(String parentUniqueId) { + this.parentUniqueId = parentUniqueId; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + public String propertyToJsonString() { String jsonString; jsonString = - "{\"" + this.getName() + "\":{" + "\"name\":\"" + this.getName() + "\"," + "\"type\":\"" + this.getPropertyType() + "\"," + "\"required\":" - + this.getPropertyRequired() + "," + "\"defaultValue\":\"" + this.getPropertyDefaultValue() + "\"," - + "\"description\":\"" + this.getPropertyDescription() + "\"," + "\"constraints\":[{\"inRange\":[\"" - + this.getPropertyRangeMin() + "\",\"" + this.getPropertyRangeMax() + "\"]}]," + "\"isPassword\":" - + this.getPropertyPassword() + "}}"; + "{\"" + this.getName() + "\":{" + "\"name\":\"" + this.getName() + "\"," + "\"type\":\"" + this + .getPropertyType() + "\"," + "\"required\":" + + this.getPropertyRequired() + "," + "\"defaultValue\":\"" + this.getPropertyDefaultValue() + + "\"," + + "\"description\":\"" + this.getPropertyDescription() + "\"," + + "\"constraints\":[{\"inRange\":[\"" + + this.getPropertyRangeMin() + "\",\"" + this.getPropertyRangeMax() + "\"]}]," + + "\"isPassword\":" + + this.getPropertyPassword() + "}}"; return jsonString; } } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/inputs/InputsApiTests.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/inputs/InputsApiTests.java index 91cf3b0c44..714a029fd8 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/inputs/InputsApiTests.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/inputs/InputsApiTests.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,37 +20,61 @@ package org.openecomp.sdc.ci.tests.execute.inputs; +import static org.testng.AssertJUnit.assertTrue; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + import fj.data.Either; import org.apache.commons.lang3.tuple.Pair; import org.junit.Rule; import org.junit.rules.TestName; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; -import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstInputsMap; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstancePropInput; +import org.openecomp.sdc.be.model.InputDefinition; +import org.openecomp.sdc.be.model.PropertyConstraint; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; import org.openecomp.sdc.ci.tests.api.ComponentBaseTest; +import org.openecomp.sdc.ci.tests.datatypes.PropertyReqDetails; import org.openecomp.sdc.ci.tests.datatypes.ServiceReqDetails; import org.openecomp.sdc.ci.tests.datatypes.enums.LifeCycleStatesEnum; import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum; import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse; import org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils; import org.openecomp.sdc.ci.tests.utils.general.ElementFactory; -import org.openecomp.sdc.ci.tests.utils.rest.*; +import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.ComponentInstanceRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.InputsRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.PropertyRestUtils; +import org.openecomp.sdc.ci.tests.utils.rest.ResponseParser; +import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils; import org.openecomp.sdc.ci.tests.utils.validation.BaseValidationUtils; +import org.testng.AssertJUnit; import org.testng.annotations.Test; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.testng.AssertJUnit.assertTrue; - /** - * CI-Tests for inputs + * CI-Tests for inputs * @author il0695 * */ @@ -59,10 +83,10 @@ public class InputsApiTests extends ComponentBaseTest { private static String inputCsar1 = "FCGI_with_inputs.csar"; private static String inputCsar2 = "LDSA1_with_inputs.csar"; private static User sdncDesignerDetails = null; - + @Rule public static TestName name = new TestName(); - + /** * Constructor */ @@ -70,28 +94,28 @@ public class InputsApiTests extends ComponentBaseTest { super(name, InputsApiTests.class.getName()); sdncDesignerDetails = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER); } - + /** * Create VF with inputs from CSAR file - * - * @throws Exception + * + * @throws Exception */ @Test public void testCreateResourceInstanceWithInputsFromCsar() throws Exception { Resource vf = AtomicOperationUtils.importResourceFromCsar(ResourceTypeEnum.VF, UserRoleEnum.DESIGNER, inputCsar1); assertTrue("Success creating VF from CSAR", !vf.getInputs().isEmpty()); } - + /** * Create service and add to it VF instance with inputs - * - * @throws Exception + * + * @throws Exception */ @Test public void testAddVfInstanceWithInputsToService() throws Exception { createServiceWithVFInstanceWithInputs(); } - + /** * General test to check most functionality of inputs *
    @@ -101,33 +125,33 @@ public class InputsApiTests extends ComponentBaseTest { *
  • Get service inputs
  • *
  • Delete service inputs
  • *
- * - * @throws Exception + * + * @throws Exception */ @Test public void testInputsMainFunctionality() throws Exception { Service service = createServiceWithVFInstanceWithInputs(); int totalInputsBeforeAdd = service.getInputs().size(); - + // Get component instances RestResponse getInstancesResponse = ComponentInstanceRestUtils.getComponentInstances(ComponentTypeEnum.SERVICE, service.getUniqueId(), sdncDesignerDetails); BaseValidationUtils.checkSuccess(getInstancesResponse); List serviceInstances = new Gson().fromJson(getInstancesResponse.getResponse(), new TypeToken>(){}.getType()); - + // Get all inputs of first instance ComponentInstance vfInstance = serviceInstances.get(0); RestResponse getComponentInstanceInputsResponse = InputsRestUtils.getComponentInstanceInputs(service, vfInstance); BaseValidationUtils.checkSuccess(getComponentInstanceInputsResponse); List instanceInputs = new Gson().fromJson(getComponentInstanceInputsResponse.getResponse(), new TypeToken>(){}.getType()); - + // Take only the 2 first inputs List inputsToAdd = instanceInputs.stream().limit(2).collect(Collectors.toList()); - + // Build component instances input map to add to server ComponentInstInputsMap buildComponentInstInputsMap = buildComponentInstInputsMap(vfInstance.getUniqueId(), inputsToAdd); RestResponse addInputResponse = InputsRestUtils.addInput(service, buildComponentInstInputsMap, UserRoleEnum.DESIGNER); BaseValidationUtils.checkSuccess(addInputResponse); - + // Get service inputs count RestResponse getComponentInputsResponse = InputsRestUtils.getComponentInputs(service); BaseValidationUtils.checkSuccess(getComponentInputsResponse); @@ -135,11 +159,11 @@ public class InputsApiTests extends ComponentBaseTest { if (serviceInputsAfterAdd.size()-totalInputsBeforeAdd!=2) { assertTrue("Error adding inputs to service (service should have 2 inputs)", false); } - + // Delete 1 input from service RestResponse deleteInputFromComponentResponse = InputsRestUtils.deleteInputFromComponent(service, serviceInputsAfterAdd.get(0).getUniqueId()); BaseValidationUtils.checkSuccess(deleteInputFromComponentResponse); - + // Get service inputs count after delete RestResponse getComponentInputsResponseAfterDelete = InputsRestUtils.getComponentInputs(service); BaseValidationUtils.checkSuccess(getComponentInputsResponseAfterDelete); @@ -147,14 +171,14 @@ public class InputsApiTests extends ComponentBaseTest { if (serviceInputsAfterDelete.size()-totalInputsBeforeAdd!=1) { assertTrue("Error deleting inputs from service (service should have 1 input)", false); } - + assertTrue("Success testing inputs main functionality", true); } /** * Private method to create service with VF instance that has inputs * This is private method to be used by multiple tests - * + * * @return {@link org.openecomp.sdc.be.model} * @throws Exception * @throws IOException @@ -166,25 +190,25 @@ public class InputsApiTests extends ComponentBaseTest { assertTrue("Error creating default service", false); } Service service = createDefaultServiceEither.left().value(); - + // Create VF from CSAR file Resource vfWithInputs = AtomicOperationUtils.importResourceFromCsar(ResourceTypeEnum.VF, UserRoleEnum.DESIGNER, inputCsar2); // Certify VF Pair changeComponentState = AtomicOperationUtils.changeComponentState(vfWithInputs, UserRoleEnum.DESIGNER, LifeCycleStatesEnum.CERTIFY, true); assertTrue("response code is BaseRestUtils.STATUS_CODE_SUCCESS, returned :" + changeComponentState.getRight().getErrorCode(), changeComponentState.getRight().getErrorCode() == BaseRestUtils.STATUS_CODE_SUCCESS); - + // Add VF instance to service Either addComponentInstanceToComponentContainerEither = AtomicOperationUtils.addComponentInstanceToComponentContainer(vfWithInputs, service, UserRoleEnum.DESIGNER, true); if (addComponentInstanceToComponentContainerEither.isRight()){ assertTrue("Error adding VF to service", false); } - + // Get service response ServiceReqDetails serviceDetails = new ServiceReqDetails(service); RestResponse getServiceResponse = ServiceRestUtils.getService(serviceDetails, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER)); service = ResponseParser.parseToObjectUsingMapper(getServiceResponse.getResponse(), Service.class); - + // Get VF instance from service ComponentInstance vfInstance = service.getComponentInstances().get(0); if (vfInstance!=null){ @@ -194,10 +218,10 @@ public class InputsApiTests extends ComponentBaseTest { } return service; } - + /** * Return default ComponentInstInputsMap - * + * * @param addToInput * @param inputs * @return {@link org.openecomp.sdc.be.model.ComponentInstInputsMap} @@ -206,8 +230,132 @@ public class InputsApiTests extends ComponentBaseTest { Map> map = new HashMap<>(); map.put(addToInput, inputs); ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap(); - componentInstInputsMap.setComponentInstanceInputsMap(map); + componentInstInputsMap.setComponentInstanceInputsMap(map); return componentInstInputsMap; } + + @Test + public void validateValidValueConstraintOnInputFailTest() throws Exception { + Either createDefaultServiceEither = AtomicOperationUtils.createDefaultService(UserRoleEnum.DESIGNER, true); + if (createDefaultServiceEither.isRight()){ + assertTrue("Error creating default service", false); + } + Service service = createDefaultServiceEither.left().value(); + + String body = "{\"SubnetProp\": {\"schema\": {\"property\": {\"type\": \"\"}},\"type\": \"org.openecomp" + + ".datatypes.heat.network.neutron.Subnet\",\"name\": \"SubnetProp\"}}"; + RestResponse createPropertyResponse = PropertyRestUtils.createProperty(service.getUniqueId(), body, + sdncDesignerDetails); + AssertJUnit.assertEquals("Expected result code - 200, received - " + createPropertyResponse.getErrorCode(), 200, + (int) createPropertyResponse.getErrorCode()); + + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + PropertyReqDetails propertyResponseObject = mapper.readValue(createPropertyResponse.getResponse(), + PropertyReqDetails.class); + + PropertyDefinition input = new PropertyDefinition(); + input.setName("ipv6_address_mode"); + input.setType("string"); + input.setUniqueId("org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.ipv6_address_mode"); + + ComponentInstancePropInput componentInstancePropInput = new ComponentInstancePropInput(); + componentInstancePropInput.setPropertiesName("SubnetProp#ipv6_address_mode"); + componentInstancePropInput.setName("SubnetProp"); + componentInstancePropInput.setParentUniqueId(service.getUniqueId()); + componentInstancePropInput.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + componentInstancePropInput.setUniqueId(propertyResponseObject.getUniqueId()); + componentInstancePropInput.setInput(input); + + ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap(); + componentInstInputsMap.setServiceProperties(Collections.singletonMap(service.getUniqueId(), + Collections.singletonList(componentInstancePropInput))); + RestResponse addInputResponse = InputsRestUtils.addInput(service, componentInstInputsMap, + UserRoleEnum.DESIGNER); + + AssertJUnit.assertEquals("Expected result code - 200, received - " + addInputResponse.getErrorCode(), + 200, (int) addInputResponse.getErrorCode()); + + Type constraintType = new TypeToken() {}.getType(); + Type inDefType = new TypeToken>() { }.getType(); + Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyOperation.PropertyConstraintDeserialiser()).create(); + try { + List inputDefinitions = gson.fromJson(addInputResponse.getResponse(), + inDefType); + + inputDefinitions.get(0).setDefaultValue("Fail"); + + RestResponse updateInputResponse = InputsRestUtils.updateInput(service, mapper.writeValueAsString(inputDefinitions), + UserRoleEnum.DESIGNER); + + AssertJUnit.assertEquals("Expected result code - 400, received - " + addInputResponse.getErrorCode(), + 400, (int) updateInputResponse.getErrorCode()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void validateValidValueConstraintOnInputSuccessTest() throws Exception { + Either createDefaultServiceEither = AtomicOperationUtils.createDefaultService(UserRoleEnum.DESIGNER, true); + if (createDefaultServiceEither.isRight()){ + assertTrue("Error creating default service", false); + } + Service service = createDefaultServiceEither.left().value(); + + String body = "{\"SubnetProp\": {\"schema\": {\"property\": {\"type\": \"\"}},\"type\": \"org.openecomp" + + ".datatypes.heat.network.neutron.Subnet\",\"name\": \"SubnetProp\"}}"; + RestResponse createPropertyResponse = PropertyRestUtils.createProperty(service.getUniqueId(), body, + sdncDesignerDetails); + AssertJUnit.assertEquals("Expected result code - 200, received - " + createPropertyResponse.getErrorCode(), 200, + (int) createPropertyResponse.getErrorCode()); + + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + PropertyReqDetails propertyResponseObject = mapper.readValue(createPropertyResponse.getResponse(), + PropertyReqDetails.class); + + PropertyDefinition input = new PropertyDefinition(); + input.setName("ipv6_address_mode"); + input.setType("string"); + input.setUniqueId("org.openecomp.datatypes.heat.network.neutron.Subnet.datatype.ipv6_address_mode"); + + ComponentInstancePropInput componentInstancePropInput = new ComponentInstancePropInput(); + componentInstancePropInput.setPropertiesName("SubnetProp#ipv6_address_mode"); + componentInstancePropInput.setName("SubnetProp"); + componentInstancePropInput.setParentUniqueId(service.getUniqueId()); + componentInstancePropInput.setType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + componentInstancePropInput.setUniqueId(propertyResponseObject.getUniqueId()); + componentInstancePropInput.setInput(input); + + ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap(); + componentInstInputsMap.setServiceProperties(Collections.singletonMap(service.getUniqueId(), + Collections.singletonList(componentInstancePropInput))); + RestResponse addInputResponse = InputsRestUtils.addInput(service, componentInstInputsMap, + UserRoleEnum.DESIGNER); + + AssertJUnit.assertEquals("Expected result code - 200, received - " + addInputResponse.getErrorCode(), + 200, (int) addInputResponse.getErrorCode()); + + Type constraintType = new TypeToken() {}.getType(); + Type inDefType = new TypeToken>() { }.getType(); + Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyOperation.PropertyConstraintDeserialiser()).create(); + try { + List inputDefinitions = gson.fromJson(addInputResponse.getResponse(), + inDefType); + + inputDefinitions.get(0).setDefaultValue("slaac"); + + RestResponse updateInputResponse = InputsRestUtils.updateInput(service, mapper.writeValueAsString(inputDefinitions), + UserRoleEnum.DESIGNER); + + AssertJUnit.assertEquals("Expected result code - 200, received - " + addInputResponse.getErrorCode(), + 200, (int) updateInputResponse.getErrorCode()); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/property/PropertyApisTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/property/PropertyApisTest.java index 21e188649d..789b118419 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/property/PropertyApisTest.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/execute/property/PropertyApisTest.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,6 +20,19 @@ package org.openecomp.sdc.ci.tests.execute.property; +import static org.testng.AssertJUnit.assertTrue; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.json.simple.JSONObject; import org.json.simple.JSONValue; import org.junit.Rule; @@ -47,19 +60,12 @@ import org.testng.AssertJUnit; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.util.*; - -import static org.testng.AssertJUnit.assertTrue; - public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { protected static final String RESOURCE_CATEGORY = "Generic/Databases"; protected Config config = Config.instance(); protected String contentTypeHeaderData = "application/json"; protected String acceptHeaderDate = "application/json";; - - // protected User sdncDesignerDetails; - // protected ResourceReqDetails resourceDetails; protected PropertyReqDetails property; protected String body; @@ -75,30 +81,8 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { @BeforeMethod public void init() throws Exception { - // - // //Delete resource - // - // resourceDetails = new ResourceReqDetails(); - // resourceDetails.setResourceName("testresourceDetails"); - // - // resourceUtils.deleteResource_allVersions(resourceDetails, - // sdncDesignerDetails); - // - // //Create resource - // resourceDetails = createResource(sdncDesignerDetails, - // "testresourceDetails"); - - // Create property - // property.setPropertyName("test"); - // property.setPropertyType("integer"); - // property.setPropertySource("A&AI"); - // property.setPropertyDescription("test property"); - - // body = gson.toJson(property); property = ElementFactory.getDefaultProperty(); body = property.propertyToJsonString(); - // System.out.println(body); - // HTTP (for negative tests) headersMap.put(HttpHeaderEnum.CONTENT_TYPE.getValue(), contentTypeHeaderData); headersMap.put(HttpHeaderEnum.ACCEPT.getValue(), acceptHeaderDate); headersMap.put(HttpHeaderEnum.USER_ID.getValue(), sdncDesignerDetails.getUserId()); @@ -106,10 +90,75 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { } @Test - public void testPropertyApis() throws Exception { - // Create property - // System.out.println ("---- Create Property (POST) ----"); + public void validateValidValueConstraintFailTest() throws Exception { + body = "{\"SubnetProp\": {\"schema\": {\"property\": {\"type\": \"\"}},\"type\": \"org.openecomp.datatypes.heat.network.neutron.Subnet\",\"name\": \"SubnetProp\"}}"; + RestResponse createPropertyResponse = PropertyRestUtils.createProperty(getResourceId(resourceDetails), body, + sdncDesignerDetails); + AssertJUnit.assertEquals("Expected result code - 200, received - " + createPropertyResponse.getErrorCode(), 200, + (int) createPropertyResponse.getErrorCode()); + + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + try { + PropertyReqDetails propertyResponseObject = mapper.readValue(createPropertyResponse.getResponse(), + PropertyReqDetails.class); + + PropertyReqDetails propertyReqDetails = new PropertyReqDetails(); + propertyReqDetails.setPropertyType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + propertyReqDetails.setName(propertyResponseObject.getName()); + propertyReqDetails.setValue(mapper.writeValueAsString(Collections.singletonMap("ipv6_address_mode", "Fail"))); + propertyReqDetails.setParentUniqueId(propertyResponseObject.getParentUniqueId()); + propertyReqDetails.setUniqueId(propertyResponseObject.getUniqueId()); + + body = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(Collections.singletonList(propertyReqDetails)); + body = body.replace("propertyType", "type"); + RestResponse addValueToPropertyResponse = + PropertyRestUtils.addValueToProperty(getResourceId(resourceDetails), body, sdncDesignerDetails); + + AssertJUnit.assertEquals("Expected result code - 400, received - " + addValueToPropertyResponse.getErrorCode(), + 400, (int) addValueToPropertyResponse.getErrorCode()); + } catch (Exception e) { + e.printStackTrace(); + } + } + @Test + public void validateValidValueConstraintSuccessTest() throws Exception { + body = "{\"SubnetProp\": {\"schema\": {\"property\": {\"type\": \"\"}},\"type\": \"org.openecomp.datatypes.heat.network.neutron.Subnet\",\"name\": \"SubnetProp\"}}"; + RestResponse createPropertyResponse = PropertyRestUtils.createProperty(getResourceId(resourceDetails), body, + sdncDesignerDetails); + AssertJUnit.assertEquals("Expected result code - 201, received - " + createPropertyResponse.getErrorCode(), 200, + (int) createPropertyResponse.getErrorCode()); + + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + try { + PropertyReqDetails propertyResponseObject = mapper.readValue(createPropertyResponse.getResponse(), + PropertyReqDetails.class); + + PropertyReqDetails propertyReqDetails = new PropertyReqDetails(); + propertyReqDetails.setPropertyType("org.openecomp.datatypes.heat.network.neutron.Subnet"); + propertyReqDetails.setName(propertyResponseObject.getName()); + propertyReqDetails.setValue(mapper.writeValueAsString(Collections.singletonMap("ipv6_address_mode", "slaac"))); + propertyReqDetails.setParentUniqueId(propertyResponseObject.getParentUniqueId()); + propertyReqDetails.setUniqueId(propertyResponseObject.getUniqueId()); + + body = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(Collections.singletonList(propertyReqDetails)); + body = body.replace("propertyType", "type"); + RestResponse addValueToPropertyResponse = + PropertyRestUtils.addValueToProperty(getResourceId(resourceDetails), body, sdncDesignerDetails); + + AssertJUnit.assertEquals("Expected result code - 200, received - " + addValueToPropertyResponse.getErrorCode(), + 200, (int) addValueToPropertyResponse.getErrorCode()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void testPropertyApis() throws Exception { String propertyId = UniqueIdBuilder.buildComponentPropertyUniqueId(getResourceId(resourceDetails), property.getName()); PropertyRestUtils.deleteProperty(getResourceId(resourceDetails), propertyId, sdncDesignerDetails); @@ -119,7 +168,6 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { createPropertyResponse.getErrorCode() == 201); // Get property - // System.out.println ("---- Get Property (GET) ----"); RestResponse getPropertyResponse = PropertyRestUtils.getProperty(getResourceId(resourceDetails), propertyId, sdncDesignerDetails); AssertJUnit.assertTrue("Expected result code - 200, received - " + getPropertyResponse.getErrorCode(), @@ -127,19 +175,8 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { JSONObject jsonResp = (JSONObject) JSONValue.parse(getPropertyResponse.getResponse()); - // assertTrue("Wrong 'type' in the - // response",jsonResp.get("type").equals(property.getPropertyType())); - // assertTrue("Wrong 'source' in the - // response",jsonResp.get("name").equals(property.getPropertyName())); - // assertTrue("Wrong 'name' in the - // response",jsonResp.get("source").equals(property.getPropertySource())); - // assertTrue("Wrong 'description' in the - // response",jsonResp.get("description").equals(property.getPropertyDescription())); - // Update property - // System.out.println ("---- Update Property (UPDATE) ----"); property.setPropertyDescription("Updated description"); - // body = gson.toJson(property); body = property.propertyToJsonString(); RestResponse updatePropertyResponse = PropertyRestUtils.updateProperty(getResourceId(resourceDetails), @@ -148,7 +185,6 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { updatePropertyResponse.getErrorCode() == 200); // Get property - // System.out.println ("---- Get Property (GET) ----"); getPropertyResponse = PropertyRestUtils.getProperty(getResourceId(resourceDetails), propertyId, sdncDesignerDetails); AssertJUnit.assertTrue("Expected result code - 200, received - " + getPropertyResponse.getErrorCode(), @@ -156,24 +192,13 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { jsonResp = (JSONObject) JSONValue.parse(getPropertyResponse.getResponse()); - // assertTrue("Wrong 'type' in the - // response",jsonResp.get("type").equals(property.getPropertyType())); - // assertTrue("Wrong 'source' in the - // response",jsonResp.get("name").equals(property.getPropertyName())); - // assertTrue("Wrong 'name' in the - // response",jsonResp.get("source").equals(property.getPropertySource())); - // assertTrue("Wrong 'description' in the - // response",jsonResp.get("description").equals(property.getPropertyDescription())); - // Delete property - // System.out.println ("---- Delete Property (DELETE) ----"); RestResponse deletePropertyResponse = PropertyRestUtils.deleteProperty(getResourceId(resourceDetails), propertyId, sdncDesignerDetails); AssertJUnit.assertTrue("Expected result code - 204, received - " + deletePropertyResponse.getErrorCode(), deletePropertyResponse.getErrorCode() == 204); // Get property - verify that the property doesn't exist. - // System.out.println("---- GET - Property Not Found ----"); getPropertyResponse = PropertyRestUtils.getProperty(getResourceId(resourceDetails), propertyId, sdncDesignerDetails); List variables = Arrays.asList(""); @@ -185,16 +210,10 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { // -------------------------------------------------------------------------------------- protected String getPropertyId(ResourceReqDetails resource, PropertyReqDetails property) { - // return - // resource.getResourceName().toLowerCase()+".0.1."+property.getPropertyName(); return UniqueIdBuilder.buildComponentPropertyUniqueId(resource.getUniqueId(), property.getName()); } protected String getResourceId(ResourceReqDetails resource) { - // String resourceUid = - // UniqueIdBuilder.buildResourceUniqueId(resource.getResourceName(), - // "0.1"); - return resource.getUniqueId(); } @@ -212,7 +231,6 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { String description = "description"; ArrayList resourceTags = new ArrayList(); resourceTags.add(resourceName); - // String category = ResourceCategoryEnum.DATABASE.getValue(); ArrayList derivedFrom = new ArrayList(); derivedFrom.add("tosca.nodes.Root"); String vendorName = "Oracle"; @@ -224,7 +242,6 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { derivedFrom, vendorName, vendorRelease, contactId, icon); resourceDetails.addCategoryChain(ResourceCategoryEnum.GENERIC_DATABASE.getCategory(), ResourceCategoryEnum.GENERIC_DATABASE.getSubCategory()); - // deleteResource(resourceName.toLowerCase()+".0.1",sdncUserDetails.getUserId()); // TODO delete by name // deleteResource(UniqueIdBuilder.buildResourceUniqueId(resourceName, // "0.1"), sdncUserDetails.getUserId()); @@ -239,8 +256,6 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { @Test public void putReqToCreateUriNotAllowed() throws Exception { - // System.out.println("---- PUT request to Create uri - Not Allowed - // ----"); String url = String.format(Urls.CREATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), getResourceId(resourceDetails)); RestResponse propertyErrorResponse = httpRequest.httpSendByMethod(url, "PUT", body, headersMap); @@ -251,8 +266,6 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { @Test public void getReqToCreateUriNotAllowed() throws Exception { - // System.out.println("---- GET request to Create uri - Not Allowed - // ----"); String url = String.format(Urls.CREATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), getResourceId(resourceDetails)); RestResponse propertyErrorResponse = httpRequest.httpSendGet(url, headersMap); @@ -263,8 +276,6 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { @Test public void deleteReqToCreateUriNotAllowed() throws Exception { - // System.out.println("---- DELETE request to Create uri - Not Allowed - // ----"); String url = String.format(Urls.CREATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), getResourceId(resourceDetails)); RestResponse propertyErrorResponse = httpRequest.httpSendDelete(url, headersMap); @@ -275,8 +286,6 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { @Test public void postReqToUpdateUriNotAllowed() throws Exception { - // System.out.println("---- POST request to Update uri - Not Allowed - // ----"); String url = String.format(Urls.UPDATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), getResourceId(resourceDetails), getPropertyId(resourceDetails, property)); RestResponse propertyErrorResponse = httpRequest.httpSendPost(url, body, headersMap); @@ -287,7 +296,6 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { @Test public void deleteReqPropertyNotFound() throws Exception { - // System.out.println("---- DELETE - Property Not Found ----"); String unknownPropertyId = getPropertyId(resourceDetails, property) + "111"; String url = String.format(Urls.DELETE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), getResourceId(resourceDetails), unknownPropertyId); @@ -299,7 +307,6 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { @Test public void updateReqPropertyNotFound() throws Exception { - // System.out.println("---- PUT - Property Not Found ----"); String unknownPropertyId = getPropertyId(resourceDetails, property) + "111"; String url = String.format(Urls.UPDATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), getResourceId(resourceDetails), unknownPropertyId); @@ -311,12 +318,10 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { @Test public void modifierNotTheStateOwner() throws Exception { - // System.out.println("---- The modifier is not the state owner - // Operation Not Allowed ----"); User sdncUserDetails2 = createUser("tu5555", "Test", "User", "tu5555@intl.sdc.com", "DESIGNER"); headersMap.put(HttpHeaderEnum.USER_ID.getValue(), sdncUserDetails2.getUserId()); property.setPropertyDescription("new description"); - // body = gson.toJson(property); body = property.propertyToJsonString(); String url = String.format(Urls.UPDATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), getResourceId(resourceDetails), getPropertyId(resourceDetails, property)); @@ -329,15 +334,11 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { @Test public void postReqInvalidContent() throws Exception { - // System.out.println("---- POST - Invalid Content ----"); body = "invalid"; String url = String.format(Urls.CREATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), getResourceId(resourceDetails), getPropertyId(resourceDetails, property)); RestResponse propertyErrorResponse = httpRequest.httpSendPost(url, body, headersMap); - // System.out.println(propertyErrorResponse.getResponse()+" "+ - // propertyErrorResponse.getErrorCode()); - List variables = Arrays.asList(); ErrorValidationUtils.checkBodyResponseOnError(ActionStatus.INVALID_CONTENT.name(), variables, propertyErrorResponse.getResponse()); @@ -347,30 +348,20 @@ public class PropertyApisTest extends SimpleOneRsrcOneServiceTest { public void putReqInvalidContent() throws Exception { // Create property - // System.out.println ("---- Create Property (POST) ----"); RestResponse createPropertyResponse = PropertyRestUtils.createProperty(getResourceId(resourceDetails), body, sdncDesignerDetails); assertTrue("Expected result code - 201, received - " + createPropertyResponse.getErrorCode(), createPropertyResponse.getErrorCode() == 201); - // System.out.println("---- PUT - Invalid Content ----"); body = "invalid"; String url = String.format(Urls.UPDATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), getResourceId(resourceDetails), getPropertyId(resourceDetails, property)); - // System.out.println(url + "\n" + body); - RestResponse propertyErrorResponse = httpRequest.httpSendByMethod(url, "PUT", body, headersMap); - // System.out.println(propertyErrorResponse.getResponse()+" "+ - // propertyErrorResponse.getErrorCode()); - List variables = Arrays.asList(); ErrorValidationUtils.checkBodyResponseOnError(ActionStatus.INVALID_CONTENT.name(), variables, propertyErrorResponse.getResponse()); } - - // -------------------------------------------------------------------------------------- - } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/InputsRestUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/InputsRestUtils.java index 521da28522..36fe6e3ea7 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/InputsRestUtils.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/InputsRestUtils.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,6 +21,7 @@ package org.openecomp.sdc.ci.tests.utils.rest; import com.google.gson.Gson; + import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentInstInputsMap; @@ -36,34 +37,51 @@ import org.slf4j.LoggerFactory; /** * RestUtils for inputs - * - * @author il0695 * + * @author il0695 */ public class InputsRestUtils extends BaseRestUtils { @SuppressWarnings("unused") private static Logger logger = LoggerFactory.getLogger(InputsRestUtils.class.getName()); - + /** * Add inputs to service - * + * * @param component * @param inputs * @param userRole * @return {@link org.openecomp.sdc.ci.tests.datatypes.http.RestResponse} * @throws Exception */ - public static RestResponse addInput(Component component, ComponentInstInputsMap inputs, UserRoleEnum userRole) throws Exception { + public static RestResponse addInput(Component component, ComponentInstInputsMap inputs, UserRoleEnum userRole) + throws Exception { Config config = Utils.getConfig(); - String url = String.format(Urls.ADD_INPUTS, config.getCatalogBeHost(), config.getCatalogBePort(), ComponentTypeEnum.findParamByType(component.getComponentType()), component.getUniqueId()); + String url = String.format(Urls.ADD_INPUTS, config.getCatalogBeHost(), config.getCatalogBePort(), + ComponentTypeEnum.findParamByType(component.getComponentType()), component.getUniqueId()); String json = new Gson().toJson(inputs); return sendPost(url, json, userRole.getUserId(), acceptHeaderData); } + /** + * Update inputs to service + * + * @param component + * @param data + * @param userRole + * @return {@link org.openecomp.sdc.ci.tests.datatypes.http.RestResponse} + * @throws Exception + */ + public static RestResponse updateInput(Component component, String data, UserRoleEnum userRole) throws Exception { + Config config = Utils.getConfig(); + String url = String.format(Urls.UPDATE_INPUTS, config.getCatalogBeHost(), config.getCatalogBePort(), + ComponentTypeEnum.findParamByType(component.getComponentType()), component.getUniqueId()); + return sendPost(url, data, userRole.getUserId(), acceptHeaderData); + } + /** * Get all Component inputs - * + * * @param component * @return {@link org.openecomp.sdc.ci.tests.datatypes.http.RestResponse} * @throws Exception @@ -71,51 +89,60 @@ public class InputsRestUtils extends BaseRestUtils { public static RestResponse getComponentInputs(Component component) throws Exception { Config config = Utils.getConfig(); //services/{componentId}/inputs - String url = String.format(Urls.GET_COMPONENT_INPUTS, config.getCatalogBeHost(), config.getCatalogBePort(), component.getUniqueId()); + String url = String.format(Urls.GET_COMPONENT_INPUTS, config.getCatalogBeHost(), config.getCatalogBePort(), + component.getUniqueId()); return sendGet(url, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER).getUserId()); } - + /** * Get all inputs of component instance - * + * * @param parentComponent * @param componentInstance * @return {@link org.openecomp.sdc.ci.tests.datatypes.http.RestResponse} * @throws Exception */ - public static RestResponse getComponentInstanceInputs(Component parentComponent, ComponentInstance componentInstance) throws Exception { + public static RestResponse getComponentInstanceInputs(Component parentComponent, + ComponentInstance componentInstance) throws Exception { Config config = Utils.getConfig(); - //{componentType}/{componentId}/componentInstances/{instanceId}/{originComonentUid}/inputs - String url = String.format(Urls.GET_COMPONENT_INSTANCE_INPUTS, config.getCatalogBeHost(), config.getCatalogBePort(), ComponentTypeEnum.findParamByType(parentComponent.getComponentType()), parentComponent.getUniqueId(), componentInstance.getUniqueId(), componentInstance.getComponentUid()); + //{componentType}/{componentId}/componentInstances/{instanceId}/{originComonentUid}/inputs + String url = + String.format(Urls.GET_COMPONENT_INSTANCE_INPUTS, config.getCatalogBeHost(), config.getCatalogBePort(), + ComponentTypeEnum.findParamByType(parentComponent.getComponentType()), + parentComponent.getUniqueId(), componentInstance.getUniqueId(), + componentInstance.getComponentUid()); return sendGet(url, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER).getUserId()); } - + /** * Delete input from component - * + * * @param parentComponent * @param inputId * @return {@link org.openecomp.sdc.ci.tests.datatypes.http.RestResponse} * @throws Exception */ public static RestResponse deleteInputFromComponent(Component parentComponent, String inputId) throws Exception { - return deleteInputFromComponent(ComponentTypeEnum.findParamByType(parentComponent.getComponentType()), parentComponent.getUniqueId(), inputId); + return deleteInputFromComponent(ComponentTypeEnum.findParamByType(parentComponent.getComponentType()), + parentComponent.getUniqueId(), inputId); } /** * Delete input from component - * + * * @param componentType * @param componentId * @param inputUniqueId * @return {@link org.openecomp.sdc.ci.tests.datatypes.http.RestResponse} * @throws Exception */ - public static RestResponse deleteInputFromComponent(String componentType, String componentId, String inputUniqueId) throws Exception { + public static RestResponse deleteInputFromComponent(String componentType, String componentId, String inputUniqueId) + throws Exception { Config config = Utils.getConfig(); //{componentType}/{componentId}/delete/{inputId}/input - String url = String.format(Urls.DELETE_INPUT_BY_ID, config.getCatalogBeHost(), config.getCatalogBePort(), componentType, componentId, inputUniqueId); + String url = String.format(Urls.DELETE_INPUT_BY_ID, config.getCatalogBeHost(), config.getCatalogBePort(), + componentType, componentId, inputUniqueId); return sendDelete(url, ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER).getUserId()); } - + } diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/PropertyRestUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/PropertyRestUtils.java index 9d2cdb50e1..34a158fe74 100644 --- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/PropertyRestUtils.java +++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/PropertyRestUtils.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,9 +20,26 @@ package org.openecomp.sdc.ci.tests.utils.rest; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertTrue; + import com.google.gson.Gson; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; -import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.ComponentInstanceInput; +import org.openecomp.sdc.be.model.ComponentInstanceProperty; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.ci.tests.api.Urls; import org.openecomp.sdc.ci.tests.config.Config; import org.openecomp.sdc.ci.tests.datatypes.PropertyObject; @@ -33,334 +50,334 @@ import org.openecomp.sdc.common.util.GeneralUtility; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.testng.AssertJUnit.*; - public class PropertyRestUtils extends BaseRestUtils { - private static Logger logger = LoggerFactory.getLogger(PropertyRestUtils.class.getName()); - - public static RestResponse createProperty(String resourceId, String body, User user) throws Exception { - Config config = Config.instance(); - String url = String.format(Urls.CREATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), resourceId); - - return sendPost(url, body, user.getUserId(), acceptHeaderData); - } - - public static RestResponse createServiceProperty(String resourceId, String body, User user) throws Exception { - Config config = Config.instance(); - String url = String.format(Urls.CREATE_SERVICE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), - resourceId); - - return sendPost(url, body, user.getUserId(), acceptHeaderData); - } - - public static RestResponse updateProperty(String resourceId, String propertyId, String body, User user) - throws Exception { - Config config = Config.instance(); - - String url = String.format(Urls.UPDATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), - resourceId, propertyId); - return sendPut(url, body, user.getUserId(), acceptHeaderData); - } - - public static RestResponse updateGroupProperty(Component component, String groupId, String body, User user) - throws Exception { - Config config = Config.instance(); - - String url = String.format(Urls.RESOURCE_GROUP_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), component.getUniqueId(), groupId); - return sendPut(url, body, user.getUserId(), acceptHeaderData); - } - - public static RestResponse getProperty(String resourceId, String propertyId, User user) throws Exception { - Config config = Config.instance(); - String url = String.format(Urls.GET_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), resourceId, - propertyId); - return sendGet(url, user.getUserId()); - } - - public static RestResponse deleteProperty(String resourceId, String propertyId, User user) throws Exception { - Config config = Config.instance(); - String url = String.format(Urls.DELETE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), - resourceId, propertyId); - - return sendDelete(url, user.getUserId()); - } - - public static ComponentInstanceProperty getPropFromListByPropNameAndType(List propList, - String propNameToUpdate, String propTypeToUpdate) { - for (ComponentInstanceProperty componentInstanceProperty : propList) { - if (componentInstanceProperty.getName().equals(propNameToUpdate) - && componentInstanceProperty.getType().equals(propTypeToUpdate)) { - return componentInstanceProperty; - } - } - return null; - } - - public static ComponentInstanceProperty getPropFromListByPropNameTypeAndPath( - List propList, String propNameToUpdate, String propTypeToUpdate, - List path) { - for (ComponentInstanceProperty componentInstanceProperty : propList) { - if (componentInstanceProperty.getPath() == null) { - return getPropFromListByPropNameAndType(propList, propNameToUpdate, propTypeToUpdate); - } - if (componentInstanceProperty.getName().equals(propNameToUpdate) - && componentInstanceProperty.getType().equals(propTypeToUpdate) - && path.containsAll(componentInstanceProperty.getPath())) { - return componentInstanceProperty; - } - } - return null; - } - - public static ComponentInstanceProperty getPropFromListByPropIdAndPath(List propList, - String propId, List path) { - - for (ComponentInstanceProperty componentInstanceProperty : propList) { - if (path != null) { - if (componentInstanceProperty.getUniqueId().equals(propId) - && componentInstanceProperty.getPath().equals(path)) { - return componentInstanceProperty; - } - } else { - if (componentInstanceProperty.getUniqueId().equals(propId)) { - return componentInstanceProperty; - } - } - } - return null; - } - - public static void comparePropertyLists(List expectedList, - List actualList, Boolean isUpdate) { - - assertTrue( - "list size are not equals, expected size is: " + expectedList.size() + " ,actual: " + actualList.size(), - expectedList.size() == actualList.size()); - Boolean flag = false; - for (ComponentInstanceProperty expectedcompInstProp : expectedList) { - for (ComponentInstanceProperty actualcompInstProp : actualList) { - flag = comparePropertyObjects(expectedcompInstProp, actualcompInstProp, isUpdate); - if (flag) { - break; - } - } - } - // System.out.println("expected: " + expectedList + ", actual: " + - // actualList); - logger.debug("expected: {}, actual: {}", expectedList, actualList); - assertTrue("actual lists does not contain all uniqeIds", flag); - } - - public static Boolean comparePropertyObjects(ComponentInstanceProperty expectedCompInstProp, - ComponentInstanceProperty actualCompInstProp, Boolean isUpdate) { - String uniqueId = expectedCompInstProp.getUniqueId(); - String type = expectedCompInstProp.getType(); - String defaulValue = expectedCompInstProp.getDefaultValue(); - if (actualCompInstProp.getUniqueId().equals(uniqueId) - && actualCompInstProp.getPath().equals(expectedCompInstProp.getPath())) { - assertTrue("expected type is: " + type + " ,actual: " + actualCompInstProp.getType(), - actualCompInstProp.getType().equals(type)); - if (defaulValue == null) { - assertTrue( - "expected defaulValue is: " + defaulValue + " ,actual: " + actualCompInstProp.getDefaultValue(), - actualCompInstProp.getDefaultValue() == defaulValue); - } else { - assertTrue( - "expected defaulValue is: " + defaulValue + " ,actual: " + actualCompInstProp.getDefaultValue(), - actualCompInstProp.getDefaultValue().equals(defaulValue)); - } - if (isUpdate) { - assertTrue( - "actual [Value] parameter " + actualCompInstProp.getName() - + "should equal to expected [Value]: " + actualCompInstProp.getValue() + " ,Value: " - + actualCompInstProp.getValue(), - actualCompInstProp.getValue().equals(expectedCompInstProp.getValue())); - assertNotNull("valueId is null", actualCompInstProp.getValueUniqueUid()); - } else { - if (defaulValue == null) { - assertTrue( - "actual [Value] parameter " + actualCompInstProp.getName() - + "should equal to expected [defaultValue]: " + actualCompInstProp.getValue() - + " ,defaultValue: " + actualCompInstProp.getDefaultValue(), - actualCompInstProp.getValue() == expectedCompInstProp.getDefaultValue()); - } else { - assertTrue( - "actual [Value] parameter " + actualCompInstProp.getName() - + "should equal to expected [defaultValue]: " + actualCompInstProp.getValue() - + " ,defaultValue: " + actualCompInstProp.getDefaultValue(), - actualCompInstProp.getValue().equals(expectedCompInstProp.getDefaultValue())); - } - assertNull("valueId is not null", actualCompInstProp.getValueUniqueUid()); - } - return true; - } - return false; - } - - public static List addResourcePropertiesToList(Resource resource, - List listToFill) { - for (PropertyDefinition prop : resource.getProperties()) { - listToFill.add(new ComponentInstanceProperty(prop, null, null)); - } - return listToFill; - } - - public static List addComponentInstPropertiesToList(Component component, - List listToFill, String componentId) { - - if (componentId != null) { - List list = component.getComponentInstancesProperties().get(componentId); - for (ComponentInstanceProperty prop : list) { - ComponentInstanceProperty componentInstanceProperty = new ComponentInstanceProperty(prop, null, null); - componentInstanceProperty.setPath(prop.getPath()); - componentInstanceProperty.setValueUniqueUid(prop.getValueUniqueUid()); - componentInstanceProperty.setValue(prop.getValue()); - listToFill.add(componentInstanceProperty); - } - } else { - Map> componentInstancesProperties = component - .getComponentInstancesProperties(); - for (Map.Entry> componentInstanceProperties : componentInstancesProperties - .entrySet()) { - for (ComponentInstanceProperty prop : componentInstanceProperties.getValue()) { - ComponentInstanceProperty componentInstanceProperty = new ComponentInstanceProperty(prop, null, - null); - componentInstanceProperty.setPath(prop.getPath()); - componentInstanceProperty.setValueUniqueUid(prop.getValueUniqueUid()); - componentInstanceProperty.setValue(prop.getValue()); - listToFill.add(componentInstanceProperty); - } - } - } - - if (component.getComponentType().getValue().equals("Resource")) { - for (PropertyDefinition prop : ((Resource) component).getProperties()) { - listToFill.add(new ComponentInstanceProperty(prop, null, null)); - } - } - return listToFill; - } - - public static ComponentInstanceProperty getCompPropInstListByInstIdAndPropName(Component component, - ComponentInstance componentInstanceDetails, String name, String type) { - List propList = component.getComponentInstancesProperties() - .get(componentInstanceDetails.getUniqueId()); - if (propList != null) { - return getPropFromListByPropNameAndType(propList, name, type); - } - return null; - } - - private static void updatePropertyListWithPathParameter(Resource resource, List path, - List expectedPropertyList) { - List propertyList = resource.getProperties(); - for (PropertyDefinition propertyDefinition : propertyList) { - ComponentInstanceProperty propDetailsToRemove = PropertyRestUtils.getPropFromListByPropNameAndType( - expectedPropertyList, propertyDefinition.getName(), propertyDefinition.getType()); - ComponentInstanceProperty propDetailsToAdd = propDetailsToRemove; - propDetailsToAdd.setPath(path); - expectedPropertyList.remove(propDetailsToRemove); - expectedPropertyList.add(propDetailsToAdd); - } - } - - private static void updatePropertyListWithPathParameterOnCompInst(Service service, List path, - List expectedPropertyList) { - List servicePropertyList = new ArrayList<>(); - servicePropertyList = PropertyRestUtils.addComponentInstPropertiesToList(service, servicePropertyList, - path.get(0)); - - for (ComponentInstanceProperty serviceCompInstProperty : servicePropertyList) { - ComponentInstanceProperty propDetailsToRemove = PropertyRestUtils.getPropFromListByPropNameTypeAndPath( - expectedPropertyList, serviceCompInstProperty.getName(), serviceCompInstProperty.getType(), - serviceCompInstProperty.getPath()); - ComponentInstanceProperty propDetailsToAdd = propDetailsToRemove; - List tempPathList = new ArrayList(); - for (String tempPath : path) { - tempPathList.add(tempPath); - } - // path parameter can not contain the same service unique ID twice - if (propDetailsToAdd.getPath() != null - && !propDetailsToAdd.getPath().get(0).contains(service.getUniqueId())) { - if (!propDetailsToAdd.getPath().containsAll(tempPathList)) { - tempPathList.addAll(propDetailsToAdd.getPath()); - } - } - propDetailsToAdd.setPath(tempPathList); - expectedPropertyList.remove(propDetailsToRemove); - expectedPropertyList.add(propDetailsToAdd); - } - } - - public static void updatePropertyListWithPathOnResource(ComponentInstance componentInstDetails, Resource resource, - List list, Component container) { - List path = new ArrayList<>(); - if (container != null) { - List componentInstances = container.getComponentInstances(); - for (ComponentInstance componentInstance : componentInstances) { - if (componentInstance.getNormalizedName().equals(componentInstDetails.getNormalizedName())) { - path.add(componentInstance.getUniqueId()); - break; - } - } - - } else { - path.add(componentInstDetails.getUniqueId()); - } - updatePropertyListWithPathParameter(resource, path, list); - } - - public static void updatePropertyListWithPathOnComponentInstance(ComponentInstance componentInstDetails, - Service service, List list) { - List path = new ArrayList<>(); - path.add(componentInstDetails.getUniqueId()); - updatePropertyListWithPathParameterOnCompInst(service, path, list); - } - - public static RestResponse declareProporties(Component componentObject, Map> componentInstancesInputs, User sdncModifierDetails) - throws Exception { - Config config = Config.instance(); - String url = String.format(Urls.DECLARE_PROPERTIES, config.getCatalogBeHost(), config.getCatalogBePort(), ComponentTypeEnum.findParamByType(componentObject.getComponentType()), componentObject.getUniqueId()); - String userId = sdncModifierDetails.getUserId(); - Map headersMap = prepareHeadersMap(userId); - Map jsonBuilder = new HashMap<>(); - jsonBuilder.put("componentInstanceInputsMap", componentInstancesInputs); - Gson gson = new Gson(); - String userBodyJson = gson.toJson(jsonBuilder); - String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(userBodyJson); - headersMap.put(HttpHeaderEnum.Content_MD5.getValue(), calculateMD5); - HttpRequest http = new HttpRequest(); - // System.out.println(url); - // System.out.println(userBodyJson); - RestResponse declareProportiesResponse = http.httpSendPost(url, userBodyJson, headersMap); - if (declareProportiesResponse.getErrorCode() == STATUS_CODE_GET_SUCCESS) { - - } - return declareProportiesResponse; - } - - public static RestResponse updateInput(Component componentObject, PropertyObject componentInput, User sdncModifierDetails) - throws Exception { - Config config = Config.instance(); - String url = String.format(Urls.UPDATE_INPUT, config.getCatalogBeHost(), config.getCatalogBePort(), componentObject.getUniqueId()); - String userId = sdncModifierDetails.getUserId(); - Map headersMap = prepareHeadersMap(userId); - Gson gson = new Gson(); - String userBodyJson = gson.toJson(componentInput); - String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(userBodyJson); - headersMap.put(HttpHeaderEnum.Content_MD5.getValue(), calculateMD5); - HttpRequest http = new HttpRequest(); - // System.out.println(url); - // System.out.println(userBodyJson); - RestResponse declareProportiesResponse = http.httpSendPost(url, userBodyJson, headersMap); - if (declareProportiesResponse.getErrorCode() == STATUS_CODE_GET_SUCCESS) { - - } - return declareProportiesResponse; - } + private static Logger logger = LoggerFactory.getLogger(PropertyRestUtils.class.getName()); + + public static RestResponse createProperty(String resourceId, String body, User user) throws Exception { + Config config = Config.instance(); + String url = String.format(Urls.CREATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), resourceId); + + return sendPost(url, body, user.getUserId(), acceptHeaderData); + } + + public static RestResponse addValueToProperty(String resourceId, String body, User user) throws Exception { + Config config = Config.instance(); + String url = String.format(Urls.CREATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), resourceId); + + return sendPut(url, body, user.getUserId(), acceptHeaderData); + } + + public static RestResponse createServiceProperty(String resourceId, String body, User user) throws Exception { + Config config = Config.instance(); + String url = String.format(Urls.CREATE_SERVICE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), + resourceId); + + return sendPost(url, body, user.getUserId(), acceptHeaderData); + } + + public static RestResponse updateProperty(String resourceId, String propertyId, String body, User user) + throws Exception { + Config config = Config.instance(); + + String url = String.format(Urls.UPDATE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), + resourceId, propertyId); + return sendPut(url, body, user.getUserId(), acceptHeaderData); + } + + public static RestResponse updateGroupProperty(Component component, String groupId, String body, User user) + throws Exception { + Config config = Config.instance(); + + String url = String.format(Urls.RESOURCE_GROUP_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), component.getUniqueId(), groupId); + return sendPut(url, body, user.getUserId(), acceptHeaderData); + } + + public static RestResponse getProperty(String resourceId, String propertyId, User user) throws Exception { + Config config = Config.instance(); + String url = String.format(Urls.GET_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), resourceId, + propertyId); + return sendGet(url, user.getUserId()); + } + + public static RestResponse deleteProperty(String resourceId, String propertyId, User user) throws Exception { + Config config = Config.instance(); + String url = String.format(Urls.DELETE_PROPERTY, config.getCatalogBeHost(), config.getCatalogBePort(), + resourceId, propertyId); + + return sendDelete(url, user.getUserId()); + } + + public static ComponentInstanceProperty getPropFromListByPropNameAndType(List propList, + String propNameToUpdate, String propTypeToUpdate) { + for (ComponentInstanceProperty componentInstanceProperty : propList) { + if (componentInstanceProperty.getName().equals(propNameToUpdate) + && componentInstanceProperty.getType().equals(propTypeToUpdate)) { + return componentInstanceProperty; + } + } + return null; + } + + public static ComponentInstanceProperty getPropFromListByPropNameTypeAndPath( + List propList, String propNameToUpdate, String propTypeToUpdate, + List path) { + for (ComponentInstanceProperty componentInstanceProperty : propList) { + if (componentInstanceProperty.getPath() == null) { + return getPropFromListByPropNameAndType(propList, propNameToUpdate, propTypeToUpdate); + } + if (componentInstanceProperty.getName().equals(propNameToUpdate) + && componentInstanceProperty.getType().equals(propTypeToUpdate) + && path.containsAll(componentInstanceProperty.getPath())) { + return componentInstanceProperty; + } + } + return null; + } + + public static ComponentInstanceProperty getPropFromListByPropIdAndPath(List propList, + String propId, List path) { + + for (ComponentInstanceProperty componentInstanceProperty : propList) { + if (path != null) { + if (componentInstanceProperty.getUniqueId().equals(propId) + && componentInstanceProperty.getPath().equals(path)) { + return componentInstanceProperty; + } + } else { + if (componentInstanceProperty.getUniqueId().equals(propId)) { + return componentInstanceProperty; + } + } + } + return null; + } + + public static void comparePropertyLists(List expectedList, + List actualList, Boolean isUpdate) { + + assertTrue( + "list size are not equals, expected size is: " + expectedList.size() + " ,actual: " + actualList.size(), + expectedList.size() == actualList.size()); + Boolean flag = false; + for (ComponentInstanceProperty expectedcompInstProp : expectedList) { + for (ComponentInstanceProperty actualcompInstProp : actualList) { + flag = comparePropertyObjects(expectedcompInstProp, actualcompInstProp, isUpdate); + if (flag) { + break; + } + } + } + // System.out.println("expected: " + expectedList + ", actual: " + + // actualList); + logger.debug("expected: {}, actual: {}", expectedList, actualList); + assertTrue("actual lists does not contain all uniqeIds", flag); + } + + public static Boolean comparePropertyObjects(ComponentInstanceProperty expectedCompInstProp, + ComponentInstanceProperty actualCompInstProp, Boolean isUpdate) { + String uniqueId = expectedCompInstProp.getUniqueId(); + String type = expectedCompInstProp.getType(); + String defaulValue = (String) expectedCompInstProp.getDefaultValue(); + if (actualCompInstProp.getUniqueId().equals(uniqueId) + && actualCompInstProp.getPath().equals(expectedCompInstProp.getPath())) { + assertTrue("expected type is: " + type + " ,actual: " + actualCompInstProp.getType(), + actualCompInstProp.getType().equals(type)); + if (defaulValue == null) { + assertTrue( + "expected defaulValue is: " + defaulValue + " ,actual: " + actualCompInstProp.getDefaultValue(), + actualCompInstProp.getDefaultValue() == defaulValue); + } else { + assertTrue( + "expected defaulValue is: " + defaulValue + " ,actual: " + actualCompInstProp.getDefaultValue(), + actualCompInstProp.getDefaultValue().equals(defaulValue)); + } + if (isUpdate) { + assertTrue( + "actual [Value] parameter " + actualCompInstProp.getName() + + "should equal to expected [Value]: " + actualCompInstProp.getValue() + " ,Value: " + + actualCompInstProp.getValue(), + actualCompInstProp.getValue().equals(expectedCompInstProp.getValue())); + assertNotNull("valueId is null", actualCompInstProp.getValueUniqueUid()); + } else { + if (defaulValue == null) { + assertTrue( + "actual [Value] parameter " + actualCompInstProp.getName() + + "should equal to expected [defaultValue]: " + actualCompInstProp.getValue() + + " ,defaultValue: " + actualCompInstProp.getDefaultValue(), + actualCompInstProp.getValue() == expectedCompInstProp.getDefaultValue()); + } else { + assertTrue( + "actual [Value] parameter " + actualCompInstProp.getName() + + "should equal to expected [defaultValue]: " + actualCompInstProp.getValue() + + " ,defaultValue: " + actualCompInstProp.getDefaultValue(), + actualCompInstProp.getValue().equals(expectedCompInstProp.getDefaultValue())); + } + assertNull("valueId is not null", actualCompInstProp.getValueUniqueUid()); + } + return true; + } + return false; + } + + public static List addResourcePropertiesToList(Resource resource, + List listToFill) { + for (PropertyDefinition prop : resource.getProperties()) { + listToFill.add(new ComponentInstanceProperty(prop, null, null)); + } + return listToFill; + } + + public static List addComponentInstPropertiesToList(Component component, + List listToFill, String componentId) { + + if (componentId != null) { + List list = component.getComponentInstancesProperties().get(componentId); + for (ComponentInstanceProperty prop : list) { + ComponentInstanceProperty componentInstanceProperty = new ComponentInstanceProperty(prop, null, null); + componentInstanceProperty.setPath(prop.getPath()); + componentInstanceProperty.setValueUniqueUid(prop.getValueUniqueUid()); + componentInstanceProperty.setValue(prop.getValue()); + listToFill.add(componentInstanceProperty); + } + } else { + Map> componentInstancesProperties = component + .getComponentInstancesProperties(); + for (Map.Entry> componentInstanceProperties : componentInstancesProperties + .entrySet()) { + for (ComponentInstanceProperty prop : componentInstanceProperties.getValue()) { + ComponentInstanceProperty componentInstanceProperty = new ComponentInstanceProperty(prop, null, + null); + componentInstanceProperty.setPath(prop.getPath()); + componentInstanceProperty.setValueUniqueUid(prop.getValueUniqueUid()); + componentInstanceProperty.setValue(prop.getValue()); + listToFill.add(componentInstanceProperty); + } + } + } + + if (component.getComponentType().getValue().equals("Resource")) { + for (PropertyDefinition prop : ((Resource) component).getProperties()) { + listToFill.add(new ComponentInstanceProperty(prop, null, null)); + } + } + return listToFill; + } + + public static ComponentInstanceProperty getCompPropInstListByInstIdAndPropName(Component component, + ComponentInstance componentInstanceDetails, String name, String type) { + List propList = component.getComponentInstancesProperties() + .get(componentInstanceDetails.getUniqueId()); + if (propList != null) { + return getPropFromListByPropNameAndType(propList, name, type); + } + return null; + } + + private static void updatePropertyListWithPathParameter(Resource resource, List path, + List expectedPropertyList) { + List propertyList = resource.getProperties(); + for (PropertyDefinition propertyDefinition : propertyList) { + ComponentInstanceProperty propDetailsToRemove = PropertyRestUtils.getPropFromListByPropNameAndType( + expectedPropertyList, propertyDefinition.getName(), propertyDefinition.getType()); + ComponentInstanceProperty propDetailsToAdd = propDetailsToRemove; + propDetailsToAdd.setPath(path); + expectedPropertyList.remove(propDetailsToRemove); + expectedPropertyList.add(propDetailsToAdd); + } + } + + private static void updatePropertyListWithPathParameterOnCompInst(Service service, List path, + List expectedPropertyList) { + List servicePropertyList = new ArrayList<>(); + servicePropertyList = PropertyRestUtils.addComponentInstPropertiesToList(service, servicePropertyList, + path.get(0)); + + for (ComponentInstanceProperty serviceCompInstProperty : servicePropertyList) { + ComponentInstanceProperty propDetailsToRemove = PropertyRestUtils.getPropFromListByPropNameTypeAndPath( + expectedPropertyList, serviceCompInstProperty.getName(), serviceCompInstProperty.getType(), + serviceCompInstProperty.getPath()); + ComponentInstanceProperty propDetailsToAdd = propDetailsToRemove; + List tempPathList = new ArrayList(); + for (String tempPath : path) { + tempPathList.add(tempPath); + } + // path parameter can not contain the same service unique ID twice + if (propDetailsToAdd.getPath() != null + && !propDetailsToAdd.getPath().get(0).contains(service.getUniqueId())) { + if (!propDetailsToAdd.getPath().containsAll(tempPathList)) { + tempPathList.addAll(propDetailsToAdd.getPath()); + } + } + propDetailsToAdd.setPath(tempPathList); + expectedPropertyList.remove(propDetailsToRemove); + expectedPropertyList.add(propDetailsToAdd); + } + } + + public static void updatePropertyListWithPathOnResource(ComponentInstance componentInstDetails, Resource resource, + List list, Component container) { + List path = new ArrayList<>(); + if (container != null) { + List componentInstances = container.getComponentInstances(); + for (ComponentInstance componentInstance : componentInstances) { + if (componentInstance.getNormalizedName().equals(componentInstDetails.getNormalizedName())) { + path.add(componentInstance.getUniqueId()); + break; + } + } + + } else { + path.add(componentInstDetails.getUniqueId()); + } + updatePropertyListWithPathParameter(resource, path, list); + } + + public static void updatePropertyListWithPathOnComponentInstance(ComponentInstance componentInstDetails, + Service service, List list) { + List path = new ArrayList<>(); + path.add(componentInstDetails.getUniqueId()); + updatePropertyListWithPathParameterOnCompInst(service, path, list); + } + + public static RestResponse declareProporties(Component componentObject, Map> componentInstancesInputs, User sdncModifierDetails) + throws Exception { + Config config = Config.instance(); + String url = String.format(Urls.DECLARE_PROPERTIES, config.getCatalogBeHost(), config.getCatalogBePort(), ComponentTypeEnum.findParamByType(componentObject.getComponentType()), componentObject.getUniqueId()); + String userId = sdncModifierDetails.getUserId(); + Map headersMap = prepareHeadersMap(userId); + Map jsonBuilder = new HashMap<>(); + jsonBuilder.put("componentInstanceInputsMap", componentInstancesInputs); + Gson gson = new Gson(); + String userBodyJson = gson.toJson(jsonBuilder); + String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(userBodyJson); + headersMap.put(HttpHeaderEnum.Content_MD5.getValue(), calculateMD5); + HttpRequest http = new HttpRequest(); + // System.out.println(url); + // System.out.println(userBodyJson); + RestResponse declareProportiesResponse = http.httpSendPost(url, userBodyJson, headersMap); + if (declareProportiesResponse.getErrorCode() == STATUS_CODE_GET_SUCCESS) { + + } + return declareProportiesResponse; + } + + public static RestResponse updateInput(Component componentObject, PropertyObject componentInput, User sdncModifierDetails) + throws Exception { + Config config = Config.instance(); + String url = String.format(Urls.UPDATE_INPUT, config.getCatalogBeHost(), config.getCatalogBePort(), componentObject.getUniqueId()); + String userId = sdncModifierDetails.getUserId(); + Map headersMap = prepareHeadersMap(userId); + Gson gson = new Gson(); + String userBodyJson = gson.toJson(componentInput); + String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(userBodyJson); + headersMap.put(HttpHeaderEnum.Content_MD5.getValue(), calculateMD5); + HttpRequest http = new HttpRequest(); + // System.out.println(url); + // System.out.println(userBodyJson); + RestResponse declareProportiesResponse = http.httpSendPost(url, userBodyJson, headersMap); + if (declareProportiesResponse.getErrorCode() == STATUS_CODE_GET_SUCCESS) { + + } + return declareProportiesResponse; + } } -- cgit 1.2.3-korg