Change to enable SDC list type input 69/84769/9
authorToshimichi Fukuda <t_fukuda@jp.fujitsu.com>
Thu, 18 Apr 2019 12:38:46 +0000 (21:38 +0900)
committerOfir Sonsino <ofir.sonsino@intl.att.com>
Tue, 7 May 2019 16:09:28 +0000 (16:09 +0000)
Change-Id: Ic3a9c6e714a5afd22b58bf2cb066932b1ec2a5c0
Issue-ID: SDC-2046
Signed-off-by: Toshimichi Fukuda <t_fukuda@jp.fujitsu.com>
Signed-off-by: Satoshi Fujii <fujii-satoshi@jp.fujitsu.com>
Signed-off-by: Ayumu Ueha <ueha.ayumu@jp.fujitsu.com>
58 files changed:
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogic.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstanceInputPropertyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/GroupPropertyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PolicyPropertyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarationOrchestrator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/propertytopolicydeclarators/ComponentInstancePropertyToPolicyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/propertytopolicydeclarators/ComponentPropertyToPolicyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/InputsServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/PropertyConvertor.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaDataType.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaTemplate.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogicTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/InputsBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstanceInputPropertyDeclaratorTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentInstancePropertyDeclaratorTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclaratorTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/property/GroupPropertyDeclaratorTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PolicyPropertyDeclaratorTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PropertyDecelerationOrchestratorTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/property/PropertyDeclaratorTestBase.java
catalog-be/src/test/java/org/openecomp/sdc/be/datamodel/UiComponentDataConverterTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/servlets/InputsServletTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaDataTypeTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaTemplateTest.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/EdgeLabelEnum.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstListInput.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/DataTypeDefinition.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplate.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/ComponentParametersViewTest.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/datamodel/TopologyTemplateTest.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperationTest.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacadeTest.java
catalog-ui/src/app/ng2/app.module.ts
catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts
catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.html [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.less [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.ts [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.module.ts [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html
catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less
catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts
catalog-ui/src/app/ng2/services/component-services/component.service.ts
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/DataTypeDataDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/PropertyDataDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ComponentFieldsEnum.java

diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogic.java
new file mode 100644 (file)
index 0000000..e020876
--- /dev/null
@@ -0,0 +1,138 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019 Fujitsu Limited. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.components.impl;
+
+import fj.data.Either;
+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.operations.api.StorageOperationStatus;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+@org.springframework.stereotype.Component("dataTypeBusinessLogic")
+public class DataTypeBusinessLogic extends BaseBusinessLogic {
+
+    /**
+     * Get a list of data types that the Component has.
+     *
+     * @param componentId Unique ID of the Component
+     * @return list of data types
+     */
+    public Either<List<DataTypeDefinition>, StorageOperationStatus> getPrivateDataTypes(String componentId) {
+        ComponentParametersView filter = new ComponentParametersView();
+        filter.disableAll();
+        filter.setIgnoreDataType(false);
+
+        // Get Component object
+        Either<? extends Component, StorageOperationStatus> componentResult =
+                toscaOperationFacade.getToscaElement(componentId, filter);
+        if (componentResult.isRight()) {
+            return Either.right(componentResult.right().value());
+        }
+        Component component = componentResult.left().value();
+
+        List<DataTypeDefinition> dataTypesToReturn = component.getDataTypes();
+        if (dataTypesToReturn == null) {
+            // this means there is no DATA_TYPES graph vertex.
+            // in this case, returns empty list.
+            dataTypesToReturn = new ArrayList<>();
+        }
+
+        return Either.left(dataTypesToReturn);
+    }
+
+    /**
+     * Get a data type in a Component
+     *
+     * @param componentId  Unique ID of the Component
+     * @param dataTypeName Data type name
+     * @return found data type
+     */
+    public Either<DataTypeDefinition, StorageOperationStatus> getPrivateDataType(String componentId, String dataTypeName) {
+        Either<List<DataTypeDefinition>, StorageOperationStatus> dataTypesResult = this.getPrivateDataTypes(componentId);
+        if (dataTypesResult.isRight()) {
+            return Either.right(dataTypesResult.right().value());
+        }
+        List<DataTypeDefinition> dataTypes = dataTypesResult.left().value();
+        Optional<DataTypeDefinition> findResult = dataTypes.stream().filter(e -> e.getName().equals(dataTypeName)).findAny();
+        if (!findResult.isPresent()) {
+            return Either.right(StorageOperationStatus.NOT_FOUND);
+        }
+        return Either.left(findResult.get());
+    }
+
+    /**
+     * Delete a data type from the Component.
+     *
+     * @param componentId  Unique ID of the Component
+     * @param dataTypeName Data type name to be deleted
+     * @return deleted data type
+     */
+    public Either<DataTypeDefinition, StorageOperationStatus> deletePrivateDataType(String componentId, String dataTypeName) {
+        ComponentParametersView filter = new ComponentParametersView();
+        filter.disableAll();
+        filter.setIgnoreDataType(false);
+
+        // Get Component object
+        Either<? extends Component, StorageOperationStatus> componentResult =
+                toscaOperationFacade.getToscaElement(componentId, filter);
+        if (componentResult.isRight()) {
+            // not exists
+            return Either.right(componentResult.right().value());
+        }
+
+        return deletePrivateDataType(componentResult.left().value(), dataTypeName);
+    }
+
+    /**
+     * Delete a data type from the Component.
+     *
+     * @param component    Component object which has data types.
+     *                     needs to be fetched with componentParametersView.setIgnoreDataType(false)
+     * @param dataTypeName Data type name to be deleted
+     * @return deleted data type
+     */
+    public Either<DataTypeDefinition, StorageOperationStatus> deletePrivateDataType(Component component, String dataTypeName) {
+        // check the specified data type exists
+        List<DataTypeDefinition> dataTypes = component.getDataTypes();
+        if (CollectionUtils.isEmpty(dataTypes)) {
+            return Either.right(StorageOperationStatus.NOT_FOUND);
+        }
+        Optional<DataTypeDefinition> dataTypeResult =
+                dataTypes.stream().filter(e -> e.getName().equals(dataTypeName)).findFirst();
+        if (!dataTypeResult.isPresent()) {
+            return Either.right(StorageOperationStatus.NOT_FOUND);
+        }
+
+        // delete it
+        StorageOperationStatus deleteResult = toscaOperationFacade.deleteDataTypeOfComponent(component, dataTypeName);
+        if (deleteResult != StorageOperationStatus.OK) {
+            return Either.right(deleteResult);
+        }
+
+        // return deleted data type if ok
+        return Either.left(dataTypeResult.get());
+    }
+}
index 214b5df..a986946 100644 (file)
@@ -22,7 +22,9 @@ package org.openecomp.sdc.be.components.impl;
 
 import fj.data.Either;
 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 java.util.Objects;
@@ -31,6 +33,10 @@ import java.util.stream.Collectors;
 import javax.inject.Inject;
 import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
 import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator;
 import org.openecomp.sdc.be.components.validation.ComponentValidations;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
@@ -42,14 +48,18 @@ import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
 import org.openecomp.sdc.be.model.ComponentInstInputsMap;
+import org.openecomp.sdc.be.model.ComponentInstListInput;
 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.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.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
+import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
 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;
@@ -73,6 +83,9 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
     private PropertyDeclarationOrchestrator propertyDeclarationOrchestrator;
     @Inject
     private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
+    @Inject
+    private DataTypeBusinessLogic dataTypeBusinessLogic;
+
     /**
      * associate inputs to a given component with paging
      *
@@ -280,7 +293,7 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
             }
 
                        //Validate value and Constraint of input
-                       Either<Boolean, ResponseFormat> constraintValidatorResponse = validateInputValueConstraint(component, inputs);
+                       Either<Boolean, ResponseFormat> constraintValidatorResponse = validateInputValueConstraint(inputs);
                        if (constraintValidatorResponse.isRight()) {
                                log.error("Failed validation value and constraint of property: {}",
                                                constraintValidatorResponse.right().value());
@@ -339,8 +352,7 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
             }
     }
 
-       private Either<Boolean, ResponseFormat> validateInputValueConstraint(
-                       org.openecomp.sdc.be.model.Component component, List<InputDefinition> inputs) {
+    private Either<Boolean, ResponseFormat> validateInputValueConstraint(List<InputDefinition> inputs) {
                PropertyValueConstraintValidationUtil propertyValueConstraintValidationUtil =
                                PropertyValueConstraintValidationUtil.getInstance();
                List<InputDefinition> inputDefinitions = new ArrayList<>();
@@ -408,46 +420,107 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
         try {
             validateUserExists(userId, GET_PROPERTIES_BY_INPUT, false);
 
-            ComponentParametersView componentParametersView = new ComponentParametersView();
-            componentParametersView.disableAll();
-            componentParametersView.setIgnoreInputs(false);
-            componentParametersView.setIgnoreComponentInstancesInputs(false);
-            componentParametersView.setIgnoreComponentInstances(false);
-            componentParametersView.setIgnoreComponentInstancesProperties(false);
-            componentParametersView.setIgnorePolicies(false);
-            componentParametersView.setIgnoreGroups(false);
-            componentParametersView.setIgnoreUsers(false);
+            component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
 
-            Either<? extends org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponent = validateComponentExists(componentId, componentType, componentParametersView);
+            result =  propertyDeclarationOrchestrator.declarePropertiesToInputs(component, componentInstInputsMapUi)
+                    .left()
+                    .bind(inputsToCreate -> prepareInputsForCreation(userId, componentId, inputsToCreate))
+                    .right()
+                                       .map(componentsUtils::getResponseFormat);
 
-            if (validateComponent.isRight()) {
-                result = Either.right(validateComponent.right().value());
-                return result;
-            }
-            component = validateComponent.left().value();
+            return result;
 
-            if (shouldLockComp) {
-                Either<Boolean, ResponseFormat> lockComponent = lockComponent(component, CREATE_INPUT);
-                if (lockComponent.isRight()) {
-                    result = Either.right(lockComponent.right().value());
-                    return result;
+        } catch (ComponentException e) {
+            log.error("#createMultipleInputs: Exception thrown: ", e);
+            result = Either.right(e.getResponseFormat());
+            return result;
+        } finally {
+
+            if (!inTransaction) {
+                if (result == null || result.isRight()) {
+                    log.debug(GOING_TO_EXECUTE_ROLLBACK_ON_CREATE_GROUP);
+                    titanDao.rollback();
+                } else {
+                    log.debug(GOING_TO_EXECUTE_COMMIT_ON_CREATE_GROUP);
+                    titanDao.commit();
                 }
             }
+            // unlock resource
+            if (shouldLockComp && component != null) {
+                graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
+            }
 
-            Either<Boolean, ResponseFormat> canWork = validateCanWorkOnComponent(component, userId);
-            if (canWork.isRight()) {
-                result = Either.right(canWork.right().value());
-                return result;
+        }
+    }
+
+    /**
+     * Creates a list input with a data type which has properties specified.
+     *
+     * @param userId User ID
+     * @param componentId Component ID
+     * @param componentType Component type
+     * @param componentListInput Properties to be declared and input to be created
+     * @param shouldLockComp true if the component should be locked
+     * @param inTransaction true if already in transaction
+     */
+    public Either<List<InputDefinition>, ResponseFormat> createListInput(String userId, String componentId,
+        ComponentTypeEnum componentType, ComponentInstListInput componentListInput, boolean shouldLockComp,
+        boolean inTransaction) {
+
+        Either<List<InputDefinition>, ResponseFormat> result = null;
+        org.openecomp.sdc.be.model.Component component = null;
+
+        log.trace("#createListInput: enter");
+
+        try {
+            /* check if user exists */
+            validateUserExists(userId, GET_PROPERTIES_BY_INPUT, false);
+
+            component = getAndValidateComponentForCreate(userId, componentId, componentType, shouldLockComp);
+
+            InputDefinition listInput = componentListInput.getListInput();
+            DataTypeDefinition dataType =
+                prepareDataTypeForListInput(componentListInput.getComponentInstInputsMap(), listInput);
+            Map<String, DataTypeDefinition> dataTypesMap = new HashMap<>();
+            dataTypesMap.put(dataType.getName(), dataType);
+            if (log.isDebugEnabled()) {
+                log.debug("#createListInput: dataTypesMap={}", ReflectionToStringBuilder.toString(dataTypesMap));
             }
 
-            result =  propertyDeclarationOrchestrator.declarePropertiesToInputs(component, componentInstInputsMapUi)
-                    .left()
-                    .bind(inputsToCreate -> prepareInputsForCreation(userId, componentId, inputsToCreate))
-                    .right()
-                                       .map(componentsUtils::getResponseFormat);
+            Either<List<DataTypeDefinition>, StorageOperationStatus> dataTypeResult =
+                toscaOperationFacade.addDataTypesToComponent(dataTypesMap, componentId);
+            if (dataTypeResult.isRight()) {
+                log.debug("#createListInput: DataType creation failed.");
+                throw new ComponentException(componentsUtils.getResponseFormat(dataTypeResult.right().value()));
+            }
+
+            // create list input
+            listInput.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(componentId, listInput.getName()));
+            listInput.setInstanceUniqueId(
+                propertyDeclarationOrchestrator.getPropOwnerId(componentListInput.getComponentInstInputsMap()));
+            listInput.setIsDeclaredListInput(true);
+            Map<String, InputDefinition> listInputMap = new HashMap<>();
+            listInputMap.put(listInput.getName(), listInput);
+            result = createListInputsInGraph(listInputMap, dataTypesMap, component);
+            if (result.isRight()) {
+                log.debug("#createListInput: createListInputsInGraph failed.");
+                throw new ComponentException(result.right().value());
+            }
+
+            // update properties
+            result = propertyDeclarationOrchestrator
+                .declarePropertiesToListInput(component, componentListInput.getComponentInstInputsMap(), listInput)
+                .right().map(err -> componentsUtils.getResponseFormat(err))
+                .left().map(Arrays::asList);
+
+            log.trace("#createListInput: leave");
 
             return result;
 
+        } catch (ComponentException e) {
+            log.error("#createListInput: Exception thrown", e);
+            result = Either.right(e.getResponseFormat());
+            return result;
         } finally {
 
             if (!inTransaction) {
@@ -463,8 +536,65 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
             if (shouldLockComp && component != null) {
                 graphLockOperation.unlockComponent(componentId, componentType.getNodeType());
             }
+        }
+    }
 
+    private ComponentParametersView getBaseComponentParametersView() {
+        ComponentParametersView componentParametersView = new ComponentParametersView();
+        componentParametersView.disableAll();
+        componentParametersView.setIgnoreInputs(false);
+        componentParametersView.setIgnoreComponentInstances(false);
+        componentParametersView.setIgnoreComponentInstancesInputs(false);
+        componentParametersView.setIgnoreComponentInstancesProperties(false);
+        componentParametersView.setIgnorePolicies(false);
+        componentParametersView.setIgnoreGroups(false);
+        componentParametersView.setIgnoreUsers(false);
+        return componentParametersView;
+    }
+
+    private org.openecomp.sdc.be.model.Component getAndValidateComponentForCreate(
+        String userId, String componentId, ComponentTypeEnum componentType, boolean shouldLockComp
+    ) {
+
+        ComponentParametersView componentParametersView = getBaseComponentParametersView();
+
+        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither =
+            // get Component Object
+            validateComponentExists(componentId, componentType, componentParametersView)
+            .left().bind(component -> {
+                if (shouldLockComp) {
+                    // lock the component
+                    return lockComponent(component, CREATE_INPUT).left().map(result -> component);
+                }
+                return Either.left(component);
+            }).left().bind(component -> validateCanWorkOnComponent(component, userId).left().map(result -> component));
+        if (componentEither.isRight()) {
+            throw new ComponentException(componentEither.right().value());
+        }
+        return componentEither.left().value();
+    }
+
+    private DataTypeDefinition prepareDataTypeForListInput(ComponentInstInputsMap inputsMap, InputDefinition input) {
+        // Confirm if type is list
+        if (StringUtils.isEmpty(input.getType()) || !input.getType().equals(ToscaPropertyType.LIST.getType())) {
+            log.debug("#prepareDataTypeForListInput: Type of input is not list.");
+            throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_TYPE));
         }
+
+        // Confirm schema type is not empty
+        String desiredTypeName = input.getSchemaType();
+        if (StringUtils.isEmpty(desiredTypeName)) {
+            log.debug("#prepareDataTypeForListInput: Schema type of list input is empty.");
+            throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_PROPERTY_INNER_TYPE));
+        }
+
+        DataTypeDefinition dataType = new DataTypeDefinition();
+        List<ComponentInstancePropInput> propInputs = inputsMap.resolvePropertiesToDeclare().getRight();
+        dataType.setName(desiredTypeName);
+        dataType.setDerivedFromName(ToscaPropertyType.Root.getType());
+        // Copy properties from inputsMap
+        dataType.setProperties(propInputs.stream().map(PropertyDefinition::new).collect(Collectors.toList()));
+        return dataType;
     }
 
     private  Either<List<InputDefinition>, StorageOperationStatus> prepareInputsForCreation(String userId, String cmptId, List<InputDefinition> inputsToCreate) {
@@ -519,6 +649,42 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
         return Either.left(associateInputsEither.left().value());
     }
 
+    private Either<List<InputDefinition>, ResponseFormat> createListInputsInGraph(Map<String, InputDefinition> inputs,
+        Map<String, DataTypeDefinition> privateDataTypes, org.openecomp.sdc.be.model.Component component) {
+
+        log.trace("#createListInputsInGraph: enter");
+        Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(
+            applicationDataTypeCache);
+        if (allDataTypes.isRight()) {
+            return Either.right(allDataTypes.right().value());
+        }
+
+        Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value();
+        dataTypes.putAll(privateDataTypes);
+
+        for (Map.Entry<String, InputDefinition> inputDefinition : inputs.entrySet()) {
+            String inputName = inputDefinition.getKey();
+            inputDefinition.getValue().setName(inputName);
+
+            Either<InputDefinition, ResponseFormat> preparedInputEither =
+                prepareAndValidateInputBeforeCreate(inputDefinition.getValue(), dataTypes);
+            if (preparedInputEither.isRight()) {
+                return Either.right(preparedInputEither.right().value());
+            }
+        }
+
+        Either<List<InputDefinition>, StorageOperationStatus> addInputsEither = toscaOperationFacade
+            .addInputsToComponent(inputs, component.getUniqueId());
+        if (addInputsEither.isRight()) {
+            log.debug("#createListInputsInGraph: Failed to create inputs under component {}. Status is {}",
+                component.getUniqueId(), addInputsEither.right().value());
+            return Either.right(componentsUtils.getResponseFormat(
+                componentsUtils.convertFromStorageResponse(addInputsEither.right().value())));
+        }
+        log.trace("#createListInputsInGraph: leave");
+        return Either.left(addInputsEither.left().value());
+    }
+
     /**
      * Delete input from service
      *
@@ -536,21 +702,16 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
 
         validateUserExists(userId, "Delete input", true);
 
-        ComponentParametersView componentParametersView = new ComponentParametersView();
-        componentParametersView.disableAll();
-        componentParametersView.setIgnoreInputs(false);
-        componentParametersView.setIgnoreComponentInstances(false);
-        componentParametersView.setIgnoreComponentInstancesInputs(false);
-        componentParametersView.setIgnoreComponentInstancesProperties(false);
-        componentParametersView.setIgnorePolicies(false);
-        componentParametersView.setIgnoreGroups(false);
-        componentParametersView.setIgnoreUsers(false);
+        ComponentParametersView componentParametersView = getBaseComponentParametersView();
         componentParametersView.setIgnoreInterfaces(false);
+        componentParametersView.setIgnoreDataType(false);
         componentParametersView.setIgnoreProperties(false);
 
-        Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> componentEither = toscaOperationFacade.getToscaElement(componentId, componentParametersView);
+        Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> componentEither =
+            toscaOperationFacade.getToscaElement(componentId, componentParametersView);
         if (componentEither.isRight()) {
-            deleteEither = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(componentEither.right().value())));
+            deleteEither = Either.right(componentsUtils.getResponseFormat(
+                componentsUtils.convertFromStorageResponse(componentEither.right().value())));
             return deleteEither;
         }
         org.openecomp.sdc.be.model.Component component = componentEither.left().value();
@@ -562,13 +723,15 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
                 // Get the input
                         findAny();
         if (!optionalInput.isPresent()) {
-            return Either.right(componentsUtils.getResponseFormat(ActionStatus.INPUT_IS_NOT_CHILD_OF_COMPONENT, inputId, componentId));
+            return Either.right(
+                componentsUtils.getResponseFormat(ActionStatus.INPUT_IS_NOT_CHILD_OF_COMPONENT, inputId, componentId));
         }
 
         InputDefinition inputForDelete = optionalInput.get();
 
         // Lock component
-        Either<Boolean, ResponseFormat> lockResultEither = lockComponent(componentId, component, "deleteInput");
+        Either<Boolean, ResponseFormat> lockResultEither =
+            lockComponent(componentId, component, "deleteInput");
         if (lockResultEither.isRight()) {
             ResponseFormat responseFormat = lockResultEither.right().value();
             deleteEither = Either.right(responseFormat);
@@ -577,18 +740,29 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
 
         // Delete input operations
         try {
-            StorageOperationStatus status = toscaOperationFacade.deleteInputOfResource(component, inputForDelete.getName());
+            StorageOperationStatus status =
+                toscaOperationFacade.deleteInputOfResource(component, inputForDelete.getName());
             if (status != StorageOperationStatus.OK) {
                 log.debug("Component id: {} delete input id: {} failed", componentId, inputId);
-                deleteEither = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), component.getName()));
+                deleteEither = Either.right(componentsUtils.getResponseFormat(
+                    componentsUtils.convertFromStorageResponse(status), component.getName()));
+                return deleteEither;
+            }
+
+            if (BooleanUtils.isTrue(inputForDelete.getIsDeclaredListInput())){
+                deleteEither = deleteListInput(componentId, inputId, component, inputForDelete, status);
                 return deleteEither;
             }
-            StorageOperationStatus storageOperationStatus = propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(component, inputForDelete);
+
+            StorageOperationStatus storageOperationStatus =
+                propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(component, inputForDelete);
             if (storageOperationStatus != StorageOperationStatus.OK) {
                 log.debug("Component id: {} update properties declared as input for input id: {} failed", componentId, inputId);
-                deleteEither = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), component.getName()));
+                deleteEither = Either.right(componentsUtils.getResponseFormat(
+                    componentsUtils.convertFromStorageResponse(status), component.getName()));
                 return deleteEither;
             }
+
             deleteEither = Either.left(inputForDelete);
             return deleteEither;
         } finally {
@@ -603,8 +777,31 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
         }
     }
 
-    private Either<InputDefinition, ResponseFormat> prepareAndValidateInputBeforeCreate(InputDefinition newInputDefinition, Map<String, DataTypeDefinition> dataTypes) {
+    private Either<InputDefinition, ResponseFormat> deleteListInput(String componentId, String inputId,
+        org.openecomp.sdc.be.model.Component component,
+        InputDefinition inputForDelete, StorageOperationStatus status) {
+        // the input is created by 'Declare List'.
+        // need to 1. undeclare properties, 2. delete input, 3. delete private data type
+
+        StorageOperationStatus storageOperationStatus =
+            propertyDeclarationOrchestrator.unDeclarePropertiesAsListInputs(component, inputForDelete);
+        if (storageOperationStatus != StorageOperationStatus.OK) {
+            log.debug("Component id: {} update properties declared as input for input id: {} failed", componentId, inputId);
+            return Either.right(componentsUtils.getResponseFormat(
+                componentsUtils.convertFromStorageResponse(status), component.getName()));
+        }
+        Either<DataTypeDefinition, StorageOperationStatus> deleteResult =
+            dataTypeBusinessLogic.deletePrivateDataType(component, inputForDelete.getSchemaType());
+        if (deleteResult.isRight()) {
+            log.debug("Component id: {} delete datatype name: {} failed", componentId, inputForDelete.getSchemaType());
+            return Either.right(componentsUtils.getResponseFormat(
+                componentsUtils.convertFromStorageResponse(deleteResult.right().value()), component.getName()));
+        }
+        log.trace("deleteInput: deletePrivateDataType (OK)");
+        return Either.left(inputForDelete);
+    }
 
+    private Either<InputDefinition, ResponseFormat> prepareAndValidateInputBeforeCreate(InputDefinition newInputDefinition, Map<String, DataTypeDefinition> dataTypes) {
 
         // validate input default values
         Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newInputDefinition, dataTypes);
@@ -613,24 +810,22 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
         }
         // convert property
         ToscaPropertyType type = getType(newInputDefinition.getType());
-        if (type != null) {
+        if (type != null && newInputDefinition != null) {
             PropertyValueConverter converter = type.getConverter();
             // get inner type
+            SchemaDefinition schema = newInputDefinition.getSchema();
             String innerType = null;
-            if (newInputDefinition != null) {
-                SchemaDefinition schema = newInputDefinition.getSchema();
-                if (schema != null) {
-                    PropertyDataDefinition prop = schema.getProperty();
-                    if (prop != null) {
-                        innerType = prop.getType();
-                    }
-                }
-                String convertedValue;
-                if (newInputDefinition.getDefaultValue() != null) {
-                    convertedValue = converter.convert(newInputDefinition.getDefaultValue(), innerType, dataTypes);
-                    newInputDefinition.setDefaultValue(convertedValue);
+            if (schema != null) {
+                PropertyDataDefinition prop = schema.getProperty();
+                if (prop != null) {
+                    innerType = prop.getType();
                 }
             }
+            String convertedValue;
+            if (newInputDefinition.getDefaultValue() != null) {
+                convertedValue = converter.convert(newInputDefinition.getDefaultValue(), innerType, dataTypes);
+                newInputDefinition.setDefaultValue(convertedValue);
+            }
         }
         return Either.left(newInputDefinition);
     }
@@ -696,5 +891,4 @@ public class InputsBusinessLogic extends BaseBusinessLogic {
 
     }
 
-
 }
index faeca88..d7b366e 100644 (file)
@@ -78,6 +78,16 @@ public class ComponentInstanceInputPropertyDeclarator extends DefaultPropertyDec
         return toscaOperationFacade.updateComponentInstanceInputs(component, componentInstanceInputsByInputId.get(0).getComponentInstanceId(), componentInstanceInputsByInputId);
     }
 
+    @Override
+    public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition input) {
+        List<ComponentInstanceInput> componentInstanceInputsByInputId = componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(component, input.getUniqueId());
+        if (isEmpty(componentInstanceInputsByInputId)) {
+            return StorageOperationStatus.OK;
+        }
+        componentInstanceInputsByInputId.forEach(cmptInstanceInput -> prepareValueBeforeDelete(input, cmptInstanceInput, cmptInstanceInput.getPath()));
+        return toscaOperationFacade.updateComponentInstanceInputs(component, componentInstanceInputsByInputId.get(0).getComponentInstanceId(), componentInstanceInputsByInputId);
+    }
+
     @Override
     InputDefinition createInputFromProperty(String componentId, ComponentInstance propertiesOwner, String inputName, ComponentInstancePropInput propInput, PropertyDataDefinition prop) {
         InputDefinition inputFromProperty = super.createInputFromProperty(componentId, propertiesOwner, inputName, propInput, prop);
index c716e24..973e598 100644 (file)
@@ -70,4 +70,13 @@ public class ComponentInstancePropertyDeclarator extends DefaultPropertyDeclarat
         return toscaOperationFacade.updateComponentInstanceProperties(component, componentInstancePropertiesDeclaredAsInput.get(0).getComponentInstanceId(), componentInstancePropertiesDeclaredAsInput);
     }
 
+    @Override
+    public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition input) {
+        List<ComponentInstanceProperty> componentInstancePropertiesDeclaredAsInput = componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(component, input.getUniqueId());
+        if (CollectionUtils.isEmpty(componentInstancePropertiesDeclaredAsInput)) {
+            return StorageOperationStatus.OK;
+        }
+        componentInstancePropertiesDeclaredAsInput.forEach(cmptInstanceProperty -> prepareValueBeforeDelete(input, cmptInstanceProperty, cmptInstanceProperty.getPath()));
+        return toscaOperationFacade.updateComponentInstanceProperties(component, componentInstancePropertiesDeclaredAsInput.get(0).getComponentInstanceId(), componentInstancePropertiesDeclaredAsInput);
+    }
 }
index d382499..ae76dad 100644 (file)
@@ -110,6 +110,40 @@ public class ComponentPropertyDeclarator extends DefaultPropertyDeclarator<Compo
     return StorageOperationStatus.OK;
   }
 
+  @Override
+  public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component,
+                                                            InputDefinition input) {
+    PropertyDefinition propertyDefinition = new PropertyDefinition(input);
+
+    if(propertyBL.isPropertyUsedByOperation(component, propertyDefinition)) {
+      return StorageOperationStatus.DECLARED_INPUT_USED_BY_OPERATION;
+    }
+
+    Optional<List <PropertyDefinition>> propertyToUpdateCandidate =
+            getDeclaredPropertiesByInputId(component, input.getUniqueId());
+
+    if(propertyToUpdateCandidate.isPresent()) {
+      List<PropertyDefinition> propertiesToUpdate = propertyToUpdateCandidate.get();
+      if (!propertiesToUpdate.isEmpty()) {
+        return unDeclareInputs(component, input, propertiesToUpdate);
+      }
+    }
+
+    return StorageOperationStatus.OK;
+  }
+
+  private StorageOperationStatus unDeclareInputs(Component component,
+                                                 InputDefinition input,
+                                                 List <PropertyDefinition> propertiesToUpdate) {
+    for (PropertyDefinition propertyToUpdate : propertiesToUpdate) {
+      StorageOperationStatus storageOperationStatus = unDeclareInput(component, input, propertyToUpdate);
+      if (StorageOperationStatus.OK != storageOperationStatus) {
+        return storageOperationStatus;
+      }
+    }
+    return StorageOperationStatus.OK;
+  }
+
   private StorageOperationStatus unDeclareInput(Component component,
                                                 InputDefinition input,
                                                 PropertyDefinition propertyToUpdate) {
@@ -124,9 +158,34 @@ public class ComponentPropertyDeclarator extends DefaultPropertyDeclarator<Compo
     return StorageOperationStatus.OK;
   }
 
-  private Optional<PropertyDefinition> getDeclaredPropertyByInputId(Component component,
+  private Optional<PropertyDefinition> getDeclaredPropertyByInputId(Component component, String inputId) {
+    List<PropertyDefinition> properties = component.getProperties();
+
+    if (CollectionUtils.isEmpty(properties)) {
+      return Optional.empty();
+    }
+
+    for (PropertyDefinition propertyDefinition : properties) {
+      List<GetInputValueDataDefinition> getInputValues = propertyDefinition.getGetInputValues();
+      if (CollectionUtils.isEmpty(getInputValues)) {
+        continue;
+      }
+
+      Optional<GetInputValueDataDefinition> getInputCandidate =
+              getInputValues.stream().filter(getInput -> getInput.getInputId().equals(inputId)).findAny();
+
+      if (getInputCandidate.isPresent()) {
+        return Optional.of(propertyDefinition);
+      }
+    }
+
+    return Optional.empty();
+  }
+
+  private Optional<List <PropertyDefinition>> getDeclaredPropertiesByInputId(Component component,
                                                                     String inputId) {
     List<PropertyDefinition> properties = component.getProperties();
+    List<PropertyDefinition> propertiesToUpdate = new ArrayList<>();
 
     if(CollectionUtils.isEmpty(properties)) {
       return Optional.empty();
@@ -139,14 +198,14 @@ public class ComponentPropertyDeclarator extends DefaultPropertyDeclarator<Compo
       }
 
       Optional<GetInputValueDataDefinition> getInputCandidate =
-          getInputValues.stream().filter(getInput -> getInput.getInputId().equals(inputId))
-              .findAny();
+              getInputValues.stream().filter(getInput -> getInput.getInputId().equals(inputId))
+                      .findAny();
 
       if(getInputCandidate.isPresent()) {
-        return Optional.of(propertyDefinition);
+        propertiesToUpdate.add(propertyDefinition);
       }
     }
 
-    return Optional.empty();
+    return Optional.of(propertiesToUpdate);
   }
 }
index 02b261b..46c1c00 100644 (file)
@@ -11,12 +11,14 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Arrays;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
 import org.json.simple.JSONObject;
 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
 import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
@@ -45,6 +47,7 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
     private final Gson gson = new Gson();
     private ComponentsUtils componentsUtils;
     private PropertyOperation propertyOperation;
+    private static final String GET_INPUT_INDEX = "INDEX";
 
     public DefaultPropertyDeclarator(ComponentsUtils componentsUtils, PropertyOperation propertyOperation) {
         this.componentsUtils = componentsUtils;
@@ -75,7 +78,17 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
         return resolvePropertiesOwner(component, propertiesOwnerId)
                        .map(propertyOwner -> declarePropertiesAsPolicies(component, propertyOwner, propsToDeclare))
                        .orElse(Either.right(onPropertiesOwnerNotFound(component.getUniqueId(), propertiesOwnerId)));
+    }
 
+    @Override
+    public Either<InputDefinition, StorageOperationStatus> declarePropertiesAsListInput(Component component, String propertiesOwnerId, List<ComponentInstancePropInput> propsToDeclare, InputDefinition input) {
+        log.debug("#declarePropertiesAsListInput - declaring properties as inputs for component {} from properties owner {}", component.getUniqueId(), propertiesOwnerId);
+        Optional<PROPERTYOWNER> propertyOwner = resolvePropertiesOwner(component, propertiesOwnerId);
+        if (propertyOwner.isPresent()) {
+            return declarePropertiesAsListInput(component, propertyOwner.get(), propsToDeclare, input);
+        } else {
+            return Either.right(onPropertiesOwnerNotFound(component.getUniqueId(), propertiesOwnerId));
+        }
     }
 
     public StorageOperationStatus unDeclarePropertiesAsPolicies(Component component, PolicyDefinition policy) {
@@ -130,12 +143,12 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
     }
 
     private void changePropertyValueToGetPolicy(PropertyDataDefinition prop, PolicyDefinition policyDefinition) {
-        JSONObject jobject = new JSONObject();
+        JSONObject jsonObject = new JSONObject();
 
         String origValue = Objects.isNull(prop.getValue()) ? prop.getDefaultValue() : prop.getValue();
-        jobject.put(GET_POLICY, null);
-        prop.setValue(jobject.toJSONString());
-        policyDefinition.setValue(jobject.toJSONString());
+        jsonObject.put(GET_POLICY, null);
+        prop.setValue(jsonObject.toJSONString());
+        policyDefinition.setValue(jsonObject.toJSONString());
 
         if(CollectionUtils.isEmpty(prop.getGetPolicyValues())){
             prop.setGetPolicyValues(new ArrayList<>());
@@ -155,6 +168,39 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
     }
 
 
+    private Either<InputDefinition, StorageOperationStatus> declarePropertiesAsListInput(Component component, PROPERTYOWNER propertiesOwner, List<ComponentInstancePropInput> propsToDeclare, InputDefinition input) {
+        List<PROPERTYTYPE> declaredProperties = new ArrayList<>();
+        for (ComponentInstancePropInput propInput : propsToDeclare) {
+            if (StringUtils.isNotEmpty(propInput.getPropertiesName()) && propInput.getInput() != null) {
+                // sub-property in complex type is checked on UI. currently not supported.
+                log.debug("skip propInput (propertiesName={}) currently not supported.", propInput.getPropertiesName());
+                continue;
+            }
+            PROPERTYTYPE declaredProperty = createDeclaredProperty(propInput);
+
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put(GET_INPUT, Arrays.asList(input.getName(), GET_INPUT_INDEX, propInput.getName()));
+            declaredProperty.setValue(jsonObject.toJSONString());
+
+            GetInputValueDataDefinition getInputValueDataDefinition = new GetInputValueDataDefinition();
+            getInputValueDataDefinition.setInputId(input.getUniqueId());
+            getInputValueDataDefinition.setInputName(input.getName());
+            List<GetInputValueDataDefinition> getInputValues = declaredProperty.getGetInputValues();
+            if (getInputValues == null) {
+                getInputValues = new ArrayList<>();
+                declaredProperty.setGetInputValues(getInputValues);
+            }
+            getInputValues.add(getInputValueDataDefinition);
+
+            if (!declaredProperties.contains(declaredProperty)) {
+                // Add property to the list if not contain in declareProperties.
+                declaredProperties.add(declaredProperty);
+            }
+        }
+        return updatePropertiesValues(component, propertiesOwner.getUniqueId(), declaredProperties)
+                .left().map(x -> input);
+    }
+
     private PropertiesDeclarationData createInputsAndOverridePropertiesValues(String componentId, PROPERTYOWNER propertiesOwner, List<ComponentInstancePropInput> propsToDeclare) {
         List<PROPERTYTYPE> declaredProperties = new ArrayList<>();
         List<InputDefinition> createdInputs = propsToDeclare.stream()
@@ -182,6 +228,7 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
             generatedInputPrefix = null;
         }
         String generatedInputName = generateInputName(generatedInputPrefix, propInput);
+        log.debug("createInput: propOwner.uniqueId={}, propInput.parentUniqueId={}", propertiesOwner.getUniqueId(), propInput.getParentUniqueId());
         return createInputFromProperty(componentId, propertiesOwner, generatedInputName, propInput, prop);
     }
 
@@ -266,18 +313,18 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
     }
 
     private void changePropertyValueToGetInputValue(String inputName, String[] parsedPropNames, InputDefinition input, PropertyDataDefinition prop, boolean complexProperty) {
-        JSONObject jobject = new JSONObject();
+        JSONObject jsonObject = new JSONObject();
         String value = prop.getValue();
         if(value == null || value.isEmpty()){
             if(complexProperty){
 
-                jobject = createJSONValueForProperty(parsedPropNames.length -1, parsedPropNames, jobject, inputName);
-                prop.setValue(jobject.toJSONString());
+                jsonObject = createJSONValueForProperty(parsedPropNames.length -1, parsedPropNames, jsonObject, inputName);
+                prop.setValue(jsonObject.toJSONString());
 
             }else{
 
-                jobject.put(GET_INPUT, input.getName());
-                prop.setValue(jobject.toJSONString());
+                jsonObject.put(GET_INPUT, input.getName());
+                prop.setValue(jsonObject.toJSONString());
 
             }
 
@@ -286,8 +333,8 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
             Object objValue =  new Yaml().load(value);
             if( objValue instanceof Map || objValue  instanceof List){
                 if(!complexProperty){
-                    jobject.put(GET_INPUT, input.getName());
-                    prop.setValue(jobject.toJSONString());
+                    jsonObject.put(GET_INPUT, input.getName());
+                    prop.setValue(jsonObject.toJSONString());
 
 
                 }else{
@@ -300,14 +347,13 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
                 }
 
             }else{
-                jobject.put(GET_INPUT, input.getName());
-                prop.setValue(jobject.toJSONString());
+                jsonObject.put(GET_INPUT, input.getName());
+                prop.setValue(jsonObject.toJSONString());
 
             }
 
         }
 
-
         if(CollectionUtils.isEmpty(prop.getGetInputValues())){
             prop.setGetInputValues(new ArrayList<>());
         }
@@ -453,6 +499,9 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
             } else if (value instanceof Map) {
                 Map<String, Object> subMap = (Map<String, Object>)value;
                 resetInputName(subMap, inputName);
+            } else if (value instanceof List && ((List) value).contains(inputName) && key.equals(GET_INPUT)) {
+                value = "";
+                lhm1.remove(key);
             } else {
                 continue;
             }
index 46ca85c..f9ef479 100644 (file)
@@ -89,6 +89,13 @@ public class GroupPropertyDeclarator extends DefaultPropertyDeclarator<GroupDefi
                 .orElse(StorageOperationStatus.OK);
     }
 
+    @Override
+    public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition inputForDelete) {
+        return getGroupPropertiesDeclaredAsInput(component, inputForDelete.getUniqueId())
+                .map(groupProperties -> unDeclareGroupProperties(component, inputForDelete, groupProperties))
+                .orElse(StorageOperationStatus.OK);
+    }
+
     private StorageOperationStatus unDeclareGroupProperties(Component container, InputDefinition input, GroupProperties groupProperties) {
         String groupId = groupProperties.getGroupId();
         List<PropertyDataDefinition> propsDeclaredAsInput = groupProperties.getProperties();
index f7f4a75..1705910 100644 (file)
@@ -87,6 +87,13 @@ public class PolicyPropertyDeclarator extends DefaultPropertyDeclarator<PolicyDe
                 .orElse(StorageOperationStatus.OK);
     }
 
+    @Override
+    public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition inputForDelete) {
+        return getPolicyPropertiesDeclaredAsInput(component, inputForDelete.getUniqueId())
+                .map(policyProperties -> unDeclarePolicyProperties(component, inputForDelete, policyProperties))
+                .orElse(StorageOperationStatus.OK);
+    }
+
     private StorageOperationStatus unDeclarePolicyProperties(Component container, InputDefinition input, PolicyProperties policyProperties) {
         String policyId = policyProperties.getPolicyId();
         List<PropertyDataDefinition> propsDeclaredAsInput = policyProperties.getProperties();
index 3a32559..a6c752d 100644 (file)
@@ -58,6 +58,20 @@ public class PropertyDeclarationOrchestrator {
         return propertyDeclarator.declarePropertiesAsPolicies(component, propsToDeclare.getLeft(), propsToDeclare.getRight());
     }
 
+    /**
+     *
+     * @param component
+     * @param componentInstInputsMap
+     * @param input
+     * @return
+     */
+    public Either<InputDefinition, StorageOperationStatus> declarePropertiesToListInput(Component component, ComponentInstInputsMap componentInstInputsMap, InputDefinition input) {
+        PropertyDeclarator propertyDeclarator = getPropertyDeclarator(componentInstInputsMap);
+        Pair<String, List<ComponentInstancePropInput>> propsToDeclare = componentInstInputsMap.resolvePropertiesToDeclare();
+        log.debug("#declarePropertiesToInputs: componentId={}, propOwnerId={}", component.getUniqueId(), propsToDeclare.getLeft());
+        return propertyDeclarator.declarePropertiesAsListInput(component, propsToDeclare.getLeft(), propsToDeclare.getRight(), input);
+    }
+
     public StorageOperationStatus unDeclarePropertiesAsInputs(Component component, InputDefinition inputToDelete) {
         log.debug("#unDeclarePropertiesAsInputs - removing input declaration for input {} on component {}", inputToDelete.getName(), component.getUniqueId());
         for (PropertyDeclarator propertyDeclarator : propertyDeclaratorsToInput) {
@@ -70,6 +84,36 @@ public class PropertyDeclarationOrchestrator {
         return StorageOperationStatus.OK;
 
     }
+    /**
+     * Un declare properties declared as list type input
+     *
+     * @param component
+     * @param inputToDelete
+     * @return
+     */
+    public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition inputToDelete) {
+        log.debug("#unDeclarePropertiesAsListInputs - removing input declaration for input {} on component {}", inputToDelete.getName(), component.getUniqueId());
+        for (PropertyDeclarator propertyDeclarator : propertyDeclaratorsToInput) {
+            StorageOperationStatus storageOperationStatus = propertyDeclarator.unDeclarePropertiesAsListInputs(component, inputToDelete);
+            if (StorageOperationStatus.OK != storageOperationStatus) {
+                log.debug("#unDeclarePropertiesAsListInputs - failed to remove input declaration for input {} on component {}. reason {}", inputToDelete.getName(), component.getUniqueId(), storageOperationStatus);
+                return storageOperationStatus;
+            }
+        }
+        return StorageOperationStatus.OK;
+
+    }
+
+    /**
+     * Get properties owner id
+     *
+     * @param componentInstInputsMap
+     * @return
+     */
+    public String getPropOwnerId(ComponentInstInputsMap componentInstInputsMap) {
+        Pair<String, List<ComponentInstancePropInput>> propsToDeclare = componentInstInputsMap.resolvePropertiesToDeclare();
+        return propsToDeclare.getLeft();
+    }
 
     public StorageOperationStatus unDeclarePropertiesAsPolicies(Component component, PolicyDefinition policyToDelete) {
         log.debug("#unDeclarePropertiesAsInputs - removing policy declaration for input {} on component {}", policyToDelete
index c0f7628..b8b6c6e 100644 (file)
@@ -44,4 +44,21 @@ public interface PropertyDeclarator {
      */
     StorageOperationStatus unDeclarePropertiesAsPolicies(Component component, PolicyDefinition policy);
 
+    /**
+     * Updates given list of properties to get values from the specified "list input" with get_input function.
+     * This function does NOT create "list input", it needs to be created separately.
+     * @param component the container
+     * @param propertiesOwnerId the id of the owner of the properties to declare (e.g ComponentInstance, Policy, Group etc)
+     * @param propsToDeclare the list of properties that are being declared as inputs
+     * @param input the input from which properties get values
+     * @return the input same as passed one at 4th argument
+     */
+    Either<InputDefinition, StorageOperationStatus> declarePropertiesAsListInput(Component component, String propertiesOwnerId, List<ComponentInstancePropInput> propsToDeclare, InputDefinition input);
+
+    /**
+     * Un declare properties declared as list type input
+     * @param component the container of the input to be deleted
+     * @param input the input to be deleted
+     */
+    StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition input);
 }
index bbbdf6f..2726f67 100644 (file)
@@ -64,6 +64,11 @@ public class ComponentInstancePropertyToPolicyDeclarator extends
         return StorageOperationStatus.OK;
     }
 
+    @Override
+    public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition input) {
+        return StorageOperationStatus.OK;
+    }
+
     @Override
     public StorageOperationStatus unDeclarePropertiesAsPolicies(Component component, PolicyDefinition policy) {
 
index 1d73786..6bd09c1 100644 (file)
@@ -64,10 +64,15 @@ public class ComponentPropertyToPolicyDeclarator extends DefaultPropertyDeclarat
         return StorageOperationStatus.OK;
     }
 
+    @Override
+    public StorageOperationStatus unDeclarePropertiesAsListInputs(Component component, InputDefinition input) {
+        // no need for implementation since we are in a policy scenario
+        return StorageOperationStatus.OK;
+    }
+
     @Override
     public void addPropertiesListToInput(PropertyDataDefinition declaredProp, InputDefinition input) {
         // no need for implementation since we are in a policy scenario
-        return;
     }
 
     @Override
index 7da6533..9f77c51 100644 (file)
@@ -44,10 +44,15 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.openecomp.sdc.be.components.impl.DataTypeBusinessLogic;
 import org.openecomp.sdc.be.components.impl.InputsBusinessLogic;
 import org.openecomp.sdc.be.config.BeEcompErrorManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.impl.WebAppContextWrapper;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.datatypes.enums.DeclarationTypeEnum;
 import org.openecomp.sdc.be.model.ComponentInstInputsMap;
 import org.openecomp.sdc.be.model.ComponentInstanceInput;
@@ -55,10 +60,13 @@ import org.openecomp.sdc.be.model.ComponentInstanceProperty;
 import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.Resource;
 import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.ComponentInstListInput;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
 import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.exception.ResponseFormat;
+import org.springframework.web.context.WebApplicationContext;
 
 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
 @Api(value = "Input Catalog", description = "Input Servlet")
@@ -256,6 +264,14 @@ public class InputsServlet extends AbstractValidationsServlet {
         }
     }
 
+    private Either<ComponentInstInputsMap, ResponseFormat> parseToComponentInstanceMap(String serviceJson, User user) {
+        return getComponentsUtils().convertJsonToObjectUsingObjectMapper(serviceJson, user, ComponentInstInputsMap.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE);
+    }
+
+    private Either<ComponentInstListInput, ResponseFormat> parseToComponentInstListInput(String json, User user) {
+        return getComponentsUtils().convertJsonToObjectUsingObjectMapper(json, user, ComponentInstListInput.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE);
+    }
+
     @POST
     @Path("/{componentType}/{componentId}/create/inputs")
     @ApiOperation(value = "Create inputs on service", httpMethod = "POST", notes = "Return inputs list", response = Resource.class)
@@ -268,6 +284,71 @@ public class InputsServlet extends AbstractValidationsServlet {
     }
 
 
+    /**
+     * Creates a "list input" and updates given list of properties to get value from the input.
+     * also a data type which has same properties is created.
+     * the data type will be the entry_schema of the list input.
+     * @param componentType the container type (service, resource, ...)
+     * @param componentId the container ID
+     * @param request HttpServletRequest object
+     * @param userId the User ID
+     * @param componentInstInputsMapObj the list of properties to be declared and the "list input" to be created.
+     *                                  the type of the input must be "list".
+     *                                  schema.type of the input will be the name of new data type.
+     * @return the created input
+     */
+    @POST
+    @Path("/{componentType}/{componentId}/create/listInput")
+    @ApiOperation(value = "Create a list input on service", httpMethod = "POST", notes = "Return input", response = Resource.class)
+    @ApiResponses(value = { @ApiResponse(code = 200, message = "Component found"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 404, message = "Component not found") })
+    public Response createListInput(@PathParam("componentType") final String componentType, @PathParam("componentId") final String componentId, @Context final HttpServletRequest request,
+                                         @HeaderParam(value = Constants.USER_ID_HEADER) String userId, @ApiParam(value = "ComponentIns Inputs Object to be created", required = true) String componentInstInputsMapObj) {
+
+        ServletContext context = request.getSession().getServletContext();
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("#createListInput: Start handle request of {}", url);
+        Response response = null;
+
+        try {
+            InputsBusinessLogic businessLogic = getInputBL(context);
+
+            // get modifier id
+            User modifier = new User();
+            modifier.setUserId(userId);
+            log.debug("modifier id is {}", userId);
+
+            Either<ComponentInstListInput, ResponseFormat> componentInstInputsMapRes =
+                parseToComponentInstListInput(componentInstInputsMapObj, modifier);
+            if (componentInstInputsMapRes.isRight()) {
+                log.debug("failed to parse componentInstInputsMap");
+                response = buildErrorResponse(componentInstInputsMapRes.right().value());
+                return response;
+            }
+
+            ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
+            ComponentInstListInput componentInstInputsMap = componentInstInputsMapRes.left().value();
+            if (log.isDebugEnabled()) {
+                // for inspection on debug
+                log.debug("parsed componentInstInputsMap={}", ReflectionToStringBuilder.toString(componentInstInputsMap));
+            }
+
+            Either<List<InputDefinition>, ResponseFormat> inputPropertiesRes = businessLogic.createListInput(
+                userId, componentId, componentTypeEnum, componentInstInputsMap, true, false);
+            if (inputPropertiesRes.isRight()) {
+                log.debug("failed to create list input for service: {}", componentId);
+                return buildErrorResponse(inputPropertiesRes.right().value());
+            }
+            Object properties = RepresentationUtils.toRepresentation(inputPropertiesRes.left().value());
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), properties);
+
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create list input for service with id: " + componentId);
+            log.debug("createListInput failed with exception", e);
+            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+            return response;
+        }
+    }
+
 
     @DELETE
     @Path("/{componentType}/{componentId}/delete/{inputId}/input")
@@ -304,4 +385,142 @@ public class InputsServlet extends AbstractValidationsServlet {
         }
     }
 
+    /**
+     * Gets a specific data type associated with a component.
+     * @param componentType the container type (service, resource, ...)
+     * @param componentId the container ID
+     * @param dataTypeName the data type name
+     * @param request HttpServletRequest object
+     * @return the data type info
+     */
+    @GET
+    @Path("/{componentType}/{componentId}/dataType/{dataTypeName}")
+    @ApiOperation(value = "Get data type in service", httpMethod = "GET", notes = "Get data type in service",
+            response = DataTypeDefinition.class)
+    @ApiResponses(value = {
+            @ApiResponse(code = 200, message = "Data type found"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 404, message = "Data type not found")})
+    public Response getDataType(
+            @PathParam("componentType") final String componentType,
+            @PathParam("componentId") final String componentId,
+            @PathParam("dataTypeName") final String dataTypeName,
+            @Context final HttpServletRequest request
+    ) {
+        ServletContext context = request.getSession().getServletContext();
+        ComponentsUtils componentsUtils = getComponentsUtils();
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("(getDataType) Start handle request of {}", url);
+        Response response;
+
+        try {
+            DataTypeBusinessLogic businessLogic = getDataTypeBL(context);
+            Either<DataTypeDefinition, StorageOperationStatus> getResult = businessLogic.getPrivateDataType(componentId, dataTypeName);
+            if (getResult.isRight()) {
+                ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getResult.right().value());
+                return buildErrorResponse(componentsUtils.getResponseFormat(actionStatus));
+            }
+            Object json = RepresentationUtils.toRepresentation(getResult.left().value());
+            return buildOkResponse(componentsUtils.getResponseFormat(ActionStatus.OK), json);
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get data type from service + " + componentId + " + with name: " + dataTypeName);
+            log.debug("Get data type failed with exception", e);
+            response = buildErrorResponse(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+            return response;
+        }
+    }
+
+    /**
+     * Gets a list of data types which a component has.
+     * @param componentType the container type (service, resource, ...)
+     * @param componentId the container ID
+     * @param request HttpServletRequest object
+     * @return the list of data types in the component
+     */
+    @GET
+    @Path("/{componentType}/{componentId}/dataTypes")
+    @ApiOperation(value = "Get data types that service has", httpMethod = "GET", notes = "Get data types in service",
+            response = Resource.class)
+    @ApiResponses(value = {
+            @ApiResponse(code = 200, message = "Data type found"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 404, message = "Component not found")})
+    public Response getDataTypes(
+            @PathParam("componentType") final String componentType,
+            @PathParam("componentId") final String componentId,
+            @Context final HttpServletRequest request
+    ) {
+        ServletContext context = request.getSession().getServletContext();
+        ComponentsUtils componentsUtils = getComponentsUtils();
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("(getDataType) Start handle request of {}", url);
+        Response response;
+
+        try {
+            DataTypeBusinessLogic businessLogic = getDataTypeBL(context);
+            Either<List<DataTypeDefinition>, StorageOperationStatus> getResult = businessLogic.getPrivateDataTypes(componentId);
+            if (getResult.isRight()) {
+                ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getResult.right().value());
+                return buildErrorResponse(componentsUtils.getResponseFormat(actionStatus));
+            }
+            Object json = RepresentationUtils.toRepresentation(getResult.left().value());
+            return buildOkResponse(componentsUtils.getResponseFormat(ActionStatus.OK), json);
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get data type from service + " + componentId);
+            log.debug("Get data type failed with exception", e);
+            response = buildErrorResponse(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+            return response;
+        }
+    }
+
+    /**
+     * Deletes a data type from a component.
+     * @param componentType the container type (service, resource, ...)
+     * @param componentId the container ID
+     * @param dataTypeName the data type name to be deleted
+     * @param request HttpServletRequest object
+     * @return operation result
+     */
+    @DELETE
+    @Path("/{componentType}/{componentId}/dataType/{dataTypeName}")
+    @ApiOperation(value = "Delete data type from service", httpMethod = "DELETE", notes = "Delete service input",
+            response = Resource.class)
+    @ApiResponses(value = {
+            @ApiResponse(code = 200, message = "Data type deleted"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 404, message = "Data type not found")})
+    public Response deleteDataType(
+            @PathParam("componentType") final String componentType,
+            @PathParam("componentId") final String componentId,
+            @PathParam("dataTypeName") final String dataTypeName,
+            @Context final HttpServletRequest request
+    ) {
+        ServletContext context = request.getSession().getServletContext();
+        ComponentsUtils componentsUtils = getComponentsUtils();
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("(get) Start handle request of {}", url);
+        Response response;
+
+        try {
+            DataTypeBusinessLogic businessLogic = getDataTypeBL(context);
+            Either<DataTypeDefinition, StorageOperationStatus> deleteResult = businessLogic.deletePrivateDataType(componentId, dataTypeName);
+            if (deleteResult.isRight()) {
+                ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(deleteResult.right().value());
+                return buildErrorResponse(componentsUtils.getResponseFormat(actionStatus));
+            }
+            Object json = RepresentationUtils.toRepresentation(deleteResult.left().value());
+            return buildOkResponse(componentsUtils.getResponseFormat(ActionStatus.OK), json);
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete data type for service + " + componentId + " + with name: " + dataTypeName);
+            log.debug("Delete data type failed with exception", e);
+            response = buildErrorResponse(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+            return response;
+        }
+    }
+
+    private DataTypeBusinessLogic getDataTypeBL(ServletContext context) {
+        WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
+        WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
+        return webApplicationContext.getBean(DataTypeBusinessLogic.class);
+    }
 }
index 405db5a..baf5b30 100644 (file)
@@ -22,6 +22,7 @@ package org.openecomp.sdc.be.tosca;
 
 import com.google.gson.Gson;
 import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.google.gson.stream.JsonReader;
 import fj.data.Either;
@@ -32,6 +33,7 @@ import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.be.model.tosca.ToscaFunctions;
 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
 import org.openecomp.sdc.be.model.tosca.converters.DataTypePropertyConverter;
 import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
@@ -185,25 +187,31 @@ public class PropertyConvertor {
                 log.trace("It's well defined type. convert it");
                 ToscaValueConverter converter = type.getValueConverter();
                 return converter.convertToToscaValue(value, innerType, dataTypes);
-            } else {
-                log.trace("It's data type or inputs in primitive type. convert as map");
-                Object convertedValue;
-                if (innerConverter != null && (ToscaPropertyType.MAP.equals(type) || ToscaPropertyType.LIST.equals(type))) {
-                    convertedValue = innerConverter.convertToToscaValue(value, innerType, dataTypes);
-                } else {
-                    if (isScalar) {
-                        // complex json for scalar type
-                        convertedValue = mapConverterInst.handleComplexJsonValue(jsonElement);
-                    } else {
-                        if (innerConverter != null) {
-                            convertedValue = innerConverter.convertToToscaValue(value, innerType, dataTypes);
-                        } else {
-                            convertedValue = mapConverterInst.convertDataTypeToToscaObject(innerType, dataTypes, innerConverter, isScalar, jsonElement, preserveEmptyValue);
-                        }
-                    }
+            }
+            log.trace("It's data type or inputs in primitive type. convert as map");
+            if (jsonElement.isJsonObject()) {
+                JsonObject jsonObj = jsonElement.getAsJsonObject();
+                // check if value is a get_input function
+                if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_INPUT.getFunctionName())) {
+                    Object obj = mapConverterInst.handleComplexJsonValue(jsonElement);
+                    log.debug("It's get_input function. obj={}", obj);
+                    return obj;
                 }
-                return convertedValue;
             }
+            Object convertedValue;
+            if (innerConverter != null && (ToscaPropertyType.MAP.equals(type) || ToscaPropertyType.LIST.equals(type))) {
+                convertedValue = innerConverter.convertToToscaValue(value, innerType, dataTypes);
+            } else if (isScalar) {
+                // complex json for scalar type
+                convertedValue = mapConverterInst.handleComplexJsonValue(jsonElement);
+            } else if (innerConverter != null) {
+                convertedValue = innerConverter.convertToToscaValue(value, innerType, dataTypes);
+            } else {
+                convertedValue = mapConverterInst.convertDataTypeToToscaObject(
+                    innerType, dataTypes, innerConverter, isScalar, jsonElement, preserveEmptyValue);
+            }
+
+            return convertedValue;
 
         } catch (Exception e) {
             log.debug("convertToToscaValue failed to parse json value :", e);
index 54cf4cf..65451e9 100644 (file)
@@ -76,7 +76,6 @@ import java.util.stream.Collectors;
 import static org.apache.commons.collections.CollectionUtils.isEmpty;
 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
 import static org.apache.commons.collections.MapUtils.isNotEmpty;
-import static org.apache.commons.lang.StringUtils.isNotEmpty;
 import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceDefinitionElement;
 import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceTypeElement;
 
@@ -313,6 +312,7 @@ public class ToscaExportHandler {
         topologyTemplate.setSubstitution_mappings(substitutionMapping);
 
         toscaNode.setTopology_template(topologyTemplate);
+
         return Either.left(toscaNode);
     }
 
@@ -560,6 +560,30 @@ public class ToscaExportHandler {
             resolveDefaultPropertyValue(inputDef, mergedProperties, dataTypes);
             toscaNodeType.setProperties(mergedProperties);
         }
+
+        /* convert private data_types */
+        List<DataTypeDefinition> privateDataTypes = component.getDataTypes();
+        if (CollectionUtils.isNotEmpty(privateDataTypes) ) {
+            Map<String, ToscaDataType> toscaDataTypeMap = new HashMap<>();
+            for (DataTypeDefinition dataType: privateDataTypes) {
+                log.debug("Emitting private data type: component.name={} dataType.name={}",
+                        component.getNormalizedName(), dataType.getName());
+                ToscaDataType toscaDataType = new ToscaDataType();
+                toscaDataType.setDerived_from(dataType.getDerivedFromName());
+                toscaDataType.setDescription(dataType.getDescription());
+                toscaDataType.setVersion(dataType.getVersion());
+                if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
+                    toscaDataType.setProperties(dataType.getProperties().stream()
+                            .collect(Collectors.toMap(
+                                    s -> s.getName(),
+                                    s -> propertyConvertor.convertProperty(dataTypes, s, PropertyConvertor.PropertyType.PROPERTY)
+                            )));
+                }
+                toscaDataTypeMap.put(dataType.getName(), toscaDataType);
+            }
+            toscaNode.setData_types(toscaDataTypeMap);
+        }
+
         // Extracted to method for code reuse
         return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
     }
@@ -570,17 +594,30 @@ public class ToscaExportHandler {
         for (Map.Entry<String, ToscaProperty> mergedPropertyEntry : mergedProperties.entrySet()) {
             ToscaProperty value = mergedPropertyEntry.getValue();
             if (Objects.nonNull(value) && value.getDefaultp() instanceof Map) {
-                Map<String, String> valueAsMap = (Map<String, String>) value.getDefaultp();
-                String inputName = valueAsMap.get(ToscaFunctions.GET_INPUT.getFunctionName());
-                Optional<InputDefinition> matchedInputDefinition = inputDef.stream()
-                        .filter(componentInput -> componentInput.getName().equals(inputName))
-                        .findFirst();
-                if (matchedInputDefinition.isPresent()) {
-                    InputDefinition matchedInput = matchedInputDefinition.get();
-                    Object resolvedDefaultValue = new PropertyConvertor().convertToToscaObject(matchedInput.getType(),
-                            matchedInput.getDefaultValue(), matchedInput.getSchemaType(), dataTypes, false);
-                    value.setDefaultp(resolvedDefaultValue);
-                    mergedProperties.put(mergedPropertyEntry.getKey(), value);
+                Map<String, Object> valueAsMap = (Map<String, Object>) value.getDefaultp();
+                Object getInputValue = valueAsMap.get(ToscaFunctions.GET_INPUT.getFunctionName());
+                if (getInputValue instanceof String) {
+                    String inputName = (String)getInputValue;
+                    Optional<InputDefinition> matchedInputDefinition = inputDef.stream()
+                            .filter(componentInput -> componentInput.getName().equals(inputName))
+                            .findFirst();
+                    if (matchedInputDefinition.isPresent()) {
+                        InputDefinition matchedInput = matchedInputDefinition.get();
+                        Object resolvedDefaultValue = new PropertyConvertor().convertToToscaObject(matchedInput.getType(),
+                                matchedInput.getDefaultValue(), matchedInput.getSchemaType(), dataTypes, false);
+                        value.setDefaultp(resolvedDefaultValue);
+                        mergedProperties.put(mergedPropertyEntry.getKey(), value);
+                    }
+                } else if (getInputValue instanceof List) {
+                    // new get_input syntax to refer to sub-element (introduced from TOSCA v1.3)
+                    // e.g. get_input: [input_name, INDEX, inner_property]
+                    // currently resolving default value for the syntax is not supported
+                    log.debug("#resolveDefaultPropertyValue: ignore get_input list syntax. propname={}, val={}",
+                        mergedPropertyEntry.getKey(), getInputValue);
+                } else {
+                    // Ignore unknown get_input syntax
+                    log.debug("#resolveDefaultPropertyValue: ignore unknown get_input syntax. propname={}, val={}",
+                        mergedPropertyEntry.getKey(), getInputValue);
                 }
             }
         }
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaDataType.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaDataType.java
new file mode 100644 (file)
index 0000000..8a4ec7c
--- /dev/null
@@ -0,0 +1,126 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019 Fujitsu Limited. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.tosca.model;
+
+import java.util.Map;
+
+/**
+ * Represents a data type (in data_types in TOSCA model).
+ */
+public class ToscaDataType {
+
+    private String derived_from;
+    private String version;
+    private Map<String, String> metadata;
+    private String description;
+    //private List<ToscaConstraint> constraints;
+    private Map<String, ToscaProperty> properties;
+
+    /**
+     * Gets derived_from.
+     *
+     * @return Current derived_from value.
+     */
+    public String getDerived_from() {
+        return derived_from;
+    }
+
+    /**
+     * Sets derived_from.
+     *
+     * @param derived_from New derived_from value.
+     */
+    public void setDerived_from(String derived_from) {
+        this.derived_from = derived_from;
+    }
+
+    /**
+     * Gets version.
+     *
+     * @return Current version value.
+     */
+    public String getVersion() {
+        return version;
+    }
+
+    /**
+     * Sets version.
+     *
+     * @param version New version value.
+     */
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    /**
+     * Gets metadata map.
+     *
+     * @return Current metadata map.
+     */
+    public Map<String, String> getMetadata() {
+        return metadata;
+    }
+
+    /**
+     * Sets metadata map.
+     *
+     * @param metadata New metadata map.
+     */
+    public void setMetadata(Map<String, String> metadata) {
+        this.metadata = metadata;
+    }
+
+    /**
+     * Gets description.
+     *
+     * @return Current description value.
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Sets description.
+     *
+     * @param description New description value.
+     */
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    /**
+     * Gets properties map.
+     *
+     * @return Current properties map.
+     */
+    public Map<String, ToscaProperty> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Sets properties map.
+     *
+     * @param properties New properties map.
+     */
+    public void setProperties(Map<String, ToscaProperty> properties) {
+        this.properties = properties;
+    }
+}
index 65a6dbf..742e8bb 100644 (file)
@@ -32,6 +32,7 @@ public class ToscaTemplate {
     private ToscaMetadata metadata;
     private List<Map<String, Map<String, String>>> imports;
     private Map<String, Object> interface_types;
+    private Map<String, ToscaDataType> data_types;
     private Map<String, ToscaNodeType> node_types;
     private ToscaTopolgyTemplate topology_template;
 
@@ -102,5 +103,21 @@ public class ToscaTemplate {
         this.interface_types = interface_types;
 
     }
+
+    /**
+     * Gets data_types map.
+     * @return Current data_types map.
+     */
+    public Map<String, ToscaDataType> getData_types() {
+        return data_types;
+    }
+
+    /**
+     * Sets data_types map.
+     * @param data_types New data_types map.
+     */
+    public void setData_types(Map<String, ToscaDataType> data_types) {
+        this.data_types = data_types;
+    }
 }
 
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypeBusinessLogicTest.java
new file mode 100644 (file)
index 0000000..9219de1
--- /dev/null
@@ -0,0 +1,156 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019 Fujitsu Limited. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.components.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import fj.data.Either;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+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.openecomp.sdc.be.components.validation.UserValidations;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.ComponentInstanceInput;
+import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
+import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
+import org.openecomp.sdc.be.user.IUserBusinessLogic;
+
+public class DataTypeBusinessLogicTest {
+
+    private static final String COMPONENT_INSTANCE_ID = "instanceId";
+    private static final String COMPONENT_ID = "componentId";
+    private static final String USER_ID = "userId";
+    private static final String INSTANCE_INPUT_ID = "inputId";
+    private static final String DATATYPE_NAME = "org.onap.datatypes.mytype";
+
+    @Mock
+    private ComponentsUtils componentsUtilsMock;
+
+    @Mock
+    private IUserBusinessLogic userAdminMock;
+
+    @Mock
+    private ToscaOperationFacade toscaOperationFacadeMock;
+
+    @Mock
+    private UserValidations userValidations;
+
+    @Mock
+    private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
+
+    @InjectMocks
+    private DataTypeBusinessLogic testInstance;
+
+    private Service service;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        service = new Service();
+        service.setUniqueId(COMPONENT_INSTANCE_ID);
+        ComponentInstance componentInstance = new ComponentInstance();
+        componentInstance.setUniqueId(COMPONENT_INSTANCE_ID);
+        service.setComponentInstances(Collections.singletonList(componentInstance));
+        DataTypeDefinition dataType = new DataTypeDefinition();
+        dataType.setName(DATATYPE_NAME);
+        dataType.setDerivedFromName(ToscaPropertyType.Root.getType());
+        List<DataTypeDefinition> dataTypes = Arrays.asList(dataType);
+        service.setDataTypes(dataTypes);
+
+        Map<String, List<ComponentInstanceInput>> instanceInputMap = new HashMap<>();
+        ComponentInstanceInput componentInstanceInput = new ComponentInstanceInput();
+        componentInstanceInput.setInputId(INSTANCE_INPUT_ID);
+        instanceInputMap.put(COMPONENT_INSTANCE_ID, Collections.singletonList(componentInstanceInput));
+        instanceInputMap.put("someInputId", Collections.singletonList(new ComponentInstanceInput()));
+        service.setComponentInstancesInputs(instanceInputMap);
+        when(userValidations.validateUserExists(eq(USER_ID), anyString(), eq(false))).thenReturn(new User());
+        when(userAdminMock.getUser(USER_ID, false)).thenReturn(Either.left(new User()));
+    }
+
+    @Test
+    public void test_getPrivateDataTypes() throws Exception {
+        setMockitoWhenGetToscaElementCalled();
+
+        Either<List<DataTypeDefinition>, StorageOperationStatus> result = testInstance.getPrivateDataTypes(COMPONENT_ID);
+        assertTrue(result.isLeft());
+        List<DataTypeDefinition> dataTypes = result.left().value();
+        assertEquals(service.getDataTypes(), dataTypes);
+    }
+
+    @Test
+    public void test_getPrivateDataType() throws Exception {
+        setMockitoWhenGetToscaElementCalled();
+
+        Either<DataTypeDefinition, StorageOperationStatus> result =
+            testInstance.getPrivateDataType(COMPONENT_ID, DATATYPE_NAME);
+        assertTrue(result.isLeft());
+        DataTypeDefinition dataType = result.left().value();
+        assertEquals(service.getDataTypes().get(0), dataType);
+    }
+
+    @Test
+    public void test_deletePrivateDataType1() throws Exception {
+        setMockitoWhenGetToscaElementCalled();
+        when(toscaOperationFacadeMock.deleteDataTypeOfComponent(service, DATATYPE_NAME))
+            .thenReturn(StorageOperationStatus.OK);
+
+        Either<DataTypeDefinition, StorageOperationStatus> result =
+            testInstance.deletePrivateDataType(COMPONENT_ID, DATATYPE_NAME);
+        assertTrue(result.isLeft());
+        DataTypeDefinition dataType = result.left().value();
+        assertEquals(service.getDataTypes().get(0), dataType);
+    }
+
+    @Test
+    public void test_deletePrivateDataType2() throws Exception {
+        when(toscaOperationFacadeMock.deleteDataTypeOfComponent(service, DATATYPE_NAME))
+            .thenReturn(StorageOperationStatus.OK);
+
+        Either<DataTypeDefinition, StorageOperationStatus> result =
+            testInstance.deletePrivateDataType(service, DATATYPE_NAME);
+        assertTrue(result.isLeft());
+        DataTypeDefinition dataType = result.left().value();
+        assertEquals(service.getDataTypes().get(0), dataType);
+    }
+
+    private void setMockitoWhenGetToscaElementCalled() {
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class)))
+                .thenReturn(Either.left(service));
+    }
+}
index 2ef3d46..b306b2a 100644 (file)
 package org.openecomp.sdc.be.components.impl;
 
 import fj.data.Either;
+import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.components.property.PropertyDeclarationOrchestrator;
+import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder;
 import org.openecomp.sdc.be.components.validation.UserValidations;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
+import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
+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.cache.ApplicationDataTypeCache;
 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
+import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
 import org.openecomp.sdc.be.user.IUserBusinessLogic;
 import org.openecomp.sdc.exception.ResponseFormat;
 
@@ -40,9 +53,9 @@ import java.util.*;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyObject;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class InputsBusinessLogicTest {
@@ -50,7 +63,13 @@ public class InputsBusinessLogicTest {
     private static final String COMPONENT_INSTANCE_ID = "instanceId";
     private static final String COMPONENT_ID = "componentId";
     private static final String USER_ID = "userId";
-    public static final String INSTANCE_INPUT_ID = "inputId";
+    private static final String INSTANCE_INPUT_ID = "inputId";
+    private static final String LISTINPUT_NAME = "listInput";
+    private static final String LISTINPUT_SCHEMA_TYPE = "org.onap.datatypes.listinput";
+    private static final String LISTINPUT_PROP1_NAME = "prop1";
+    private static final String LISTINPUT_PROP1_TYPE = "string";
+    private static final String LISTINPUT_PROP2_NAME = "prop2";
+    private static final String LISTINPUT_PROP2_TYPE = "integer";
 
     @Mock
     private ComponentsUtils componentsUtilsMock;
@@ -67,26 +86,54 @@ public class InputsBusinessLogicTest {
     @Mock
     private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
 
+    @Mock
+    private IGraphLockOperation graphLockOperation;
+
+    @Mock
+    private PropertyDeclarationOrchestrator propertyDeclarationOrchestrator;
+
+    @Mock
+    private ApplicationDataTypeCache applicationDataTypeCache;
+
+    @Mock
+    private PropertyOperation propertyOperation;
+
+    @Mock
+    private TitanDao titanDao;
+
+    @Mock
+    private DataTypeBusinessLogic dataTypeBusinessLogic;
+
     @InjectMocks
     private InputsBusinessLogic testInstance;
 
     private Service service;
 
+    @Captor
+    ArgumentCaptor<Map<String, DataTypeDefinition>> dataTypesMapCaptor;
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         service = new Service();
-        service.setUniqueId(COMPONENT_INSTANCE_ID);
+        service.setUniqueId(COMPONENT_ID);
+        service.setLastUpdaterUserId(USER_ID);
+        service.setIsDeleted(false);
+        service.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
+
+        // add a ComponentInstance
         ComponentInstance componentInstance = new ComponentInstance();
         componentInstance.setUniqueId(COMPONENT_INSTANCE_ID);
         service.setComponentInstances(Collections.singletonList(componentInstance));
 
+        // add inputs to the ComponentInstance
         Map<String, List<ComponentInstanceInput>> instanceInputMap = new HashMap<>();
         ComponentInstanceInput componentInstanceInput = new ComponentInstanceInput();
         componentInstanceInput.setInputId(INSTANCE_INPUT_ID);
         instanceInputMap.put(COMPONENT_INSTANCE_ID, Collections.singletonList(componentInstanceInput));
         instanceInputMap.put("someInputId", Collections.singletonList(new ComponentInstanceInput()));
         service.setComponentInstancesInputs(instanceInputMap);
+
         when(userValidations.validateUserExists(eq(USER_ID), anyString(), eq(false))).thenReturn(new User());
         when(userAdminMock.getUser(USER_ID, false)).thenReturn(Either.left(new User()));
     }
@@ -96,7 +143,7 @@ public class InputsBusinessLogicTest {
         when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service));
         Either<List<ComponentInstanceInput>, ResponseFormat> componentInstanceInputs = testInstance.getComponentInstanceInputs(USER_ID, COMPONENT_ID, "nonExisting");
         assertTrue(componentInstanceInputs.isRight());
-        Mockito.verify(componentsUtilsMock).getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND);
+        verify(componentsUtilsMock).getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND);
     }
 
     @Test
@@ -263,4 +310,321 @@ public class InputsBusinessLogicTest {
         Either<List<ComponentInstanceInput>, ResponseFormat> result = testInstance.getInputsForComponentInput("USR01", COMPONENT_ID,"INPO1");
         assertEquals(true,result.isLeft());
     }
+
+
+    private InputDefinition setUpListInput() {
+        InputDefinition listInput = new InputDefinition();
+        listInput.setName(LISTINPUT_NAME);
+        listInput.setType("list");
+        SchemaDefinition listInputSchema = new SchemaDefinition();
+        listInputSchema.setProperty(new PropertyDataDefinitionBuilder()
+                .setType(LISTINPUT_SCHEMA_TYPE)
+                .setIsRequired(false)
+                .build()
+        );
+        listInput.setSchema(listInputSchema);
+        return listInput;
+    }
+
+    private ComponentInstListInput setUpCreateListInputParams() {
+        ComponentInstListInput componentInstListInput = new ComponentInstListInput();
+
+        // Create a "list input"
+        InputDefinition listInput = setUpListInput();
+        componentInstListInput.setListInput(listInput);
+
+        // Create ComponentInstancePropInputs
+        // for inputs in the ComponentInstance
+        Map<String, List<ComponentInstancePropInput>> propInputsListMap = new HashMap<>();
+        // Add 2 PropInputs. property owner is COMPONENT_INSTANCE_ID
+        List<ComponentInstancePropInput> propInputsList = new ArrayList<>();
+        ComponentInstancePropInput propInput = new ComponentInstancePropInput();
+        propInput.setName(LISTINPUT_PROP1_NAME);
+        propInput.setType(LISTINPUT_PROP1_TYPE);
+        propInput.setUniqueId(COMPONENT_INSTANCE_ID+"."+LISTINPUT_PROP1_NAME);
+        propInputsList.add(propInput);
+        propInput = new ComponentInstancePropInput();
+        propInput.setName(LISTINPUT_PROP2_NAME);
+        propInput.setType(LISTINPUT_PROP2_TYPE);
+        propInput.setUniqueId(COMPONENT_INSTANCE_ID+"."+LISTINPUT_PROP2_NAME);
+        propInputsList.add(propInput);
+        propInputsListMap.put(COMPONENT_INSTANCE_ID, propInputsList);
+        ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap();
+        componentInstInputsMap.setComponentInstanceInputsMap(propInputsListMap);
+        componentInstListInput.setComponentInstInputsMap(componentInstInputsMap);
+
+        return componentInstListInput;
+    }
+
+    @Test
+    public void test_createListInput_success() throws Exception {
+        ComponentInstListInput createListInputParams = setUpCreateListInputParams();
+        ComponentInstInputsMap componentInstInputsMap = createListInputParams.getComponentInstInputsMap();
+        List<ComponentInstancePropInput> propInputsList = componentInstInputsMap.getComponentInstanceInputsMap().get(COMPONENT_INSTANCE_ID);
+        InputDefinition listInput = createListInputParams.getListInput();
+
+        // set up mock returns
+        // for get component object:
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service));
+        when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
+        // for data type creation (use captor):
+        when(toscaOperationFacadeMock.addDataTypesToComponent(dataTypesMapCaptor.capture(), eq(COMPONENT_ID))).thenReturn(Either.left(new ArrayList<>()));
+        when(propertyDeclarationOrchestrator.getPropOwnerId(componentInstInputsMap)).thenReturn(COMPONENT_INSTANCE_ID);
+        when(propertyDeclarationOrchestrator.declarePropertiesToListInput(service, componentInstInputsMap, listInput)).thenReturn(Either.left(listInput));
+        // for BaseOperation.getAllDataTypes:
+        when(applicationDataTypeCache.getAll()).thenReturn(Either.left(new HashMap<>())); // don't use Collections.emptyMap
+        // for BaseOperation.validatePropertyDefaultValue:
+        when(propertyOperation.isPropertyTypeValid(any())).thenReturn(true);
+        when(propertyOperation.isPropertyInnerTypeValid(any(),any())).thenReturn(new ImmutablePair<>(listInput.getSchemaType(), true));
+        when(propertyOperation.isPropertyDefaultValueValid(any(), any())).thenReturn(true);
+        // for createListInputsInGraph:
+        when(toscaOperationFacadeMock.addInputsToComponent(anyMap(), eq(COMPONENT_ID))).thenReturn(Either.left(Arrays.asList(listInput)));
+        // for rollback/commit:
+        when(titanDao.commit()).thenReturn(TitanOperationStatus.OK);
+        // for unlock resource
+        when(graphLockOperation.unlockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
+
+        Either<List<InputDefinition>, ResponseFormat> result =
+                testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false);
+        // validate result
+        assertEquals(true, result.isLeft());
+        List<InputDefinition> resultInputList = result.left().value();
+        assertEquals(1, resultInputList.size());
+        //InputDefinition resultInput = resultInputList.get(0);
+        Map<String, DataTypeDefinition> captoredDataTypeMap = dataTypesMapCaptor.getValue();
+        assertEquals(1, captoredDataTypeMap.size());
+        assertEquals(true, captoredDataTypeMap.containsKey(LISTINPUT_SCHEMA_TYPE));
+        DataTypeDefinition captoredDataType = captoredDataTypeMap.get(LISTINPUT_SCHEMA_TYPE);
+        assertEquals("tosca.datatypes.Root", captoredDataType.getDerivedFromName());
+        assertEquals( propInputsList.size(), captoredDataType.getProperties().size());
+        // confirm if corresponding property exists in data type
+        captoredDataType.getProperties().forEach(dataTypeProp -> {
+            Optional<ComponentInstancePropInput> find = propInputsList.stream()
+                    .filter(propInput -> propInput.getName().equals(dataTypeProp.getName())).findAny();
+            assertEquals(true, find.isPresent());
+        });
+    }
+
+    @Test
+    public void test_createListInput_fail_getComponent() throws Exception {
+        ComponentInstListInput createListInputParams = setUpCreateListInputParams();
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<List<InputDefinition>, ResponseFormat> result =
+                testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false);
+        assertEquals(true, result.isRight());
+    }
+
+
+    @Test
+    public void test_createListInput_fail_lockComponent() throws Exception {
+        ComponentInstListInput createListInputParams = setUpCreateListInputParams();
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service));
+        when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.FAILED_TO_LOCK_ELEMENT);
+        Either<List<InputDefinition>, ResponseFormat> result =
+                testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false);
+        assertEquals(true, result.isRight());
+    }
+
+    @Test
+    public void test_createListInput_fail_getAllDataTypes() throws Exception {
+        ComponentInstListInput createListInputParams = setUpCreateListInputParams();
+        ComponentInstInputsMap componentInstInputsMap = createListInputParams.getComponentInstInputsMap();
+
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service));
+        when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
+        when(toscaOperationFacadeMock.addDataTypesToComponent(dataTypesMapCaptor.capture(), eq(COMPONENT_ID))).thenReturn(Either.left(new ArrayList<>()));
+        when(propertyDeclarationOrchestrator.getPropOwnerId(componentInstInputsMap)).thenReturn(COMPONENT_INSTANCE_ID);
+        when(applicationDataTypeCache.getAll()).thenReturn(Either.right(TitanOperationStatus.NOT_FOUND));
+        when(componentsUtilsMock.getResponseFormat(ActionStatus.DATA_TYPE_CANNOT_BE_EMPTY)).thenReturn(new ResponseFormat());
+
+        Either<List<InputDefinition>, ResponseFormat> result =
+                testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false);
+        assertEquals(true, result.isRight());
+        verify(applicationDataTypeCache, times(1)).getAll();
+        verify(componentsUtilsMock, times(1)).getResponseFormat(ActionStatus.DATA_TYPE_CANNOT_BE_EMPTY);
+    }
+
+    @Test
+    public void test_createListInput_fail_prepareAndValidateInput() throws Exception {
+        ComponentInstListInput createListInputParams = setUpCreateListInputParams();
+        ComponentInstInputsMap componentInstInputsMap = createListInputParams.getComponentInstInputsMap();
+        InputDefinition listInput = createListInputParams.getListInput();
+
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service));
+        when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
+        when(toscaOperationFacadeMock.addDataTypesToComponent(dataTypesMapCaptor.capture(), eq(COMPONENT_ID))).thenReturn(Either.left(new ArrayList<>()));
+        when(propertyDeclarationOrchestrator.getPropOwnerId(componentInstInputsMap)).thenReturn(COMPONENT_INSTANCE_ID);
+        when(applicationDataTypeCache.getAll()).thenReturn(Either.left(new HashMap<>())); // don't use Collections.emptyMap
+        // for BaseOperation.validatePropertyDefaultValue:
+        when(propertyOperation.isPropertyTypeValid(any())).thenReturn(false);
+
+        Either<List<InputDefinition>, ResponseFormat> result =
+                testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false);
+        assertEquals(true, result.isRight());
+        verify(propertyOperation, times(1)).isPropertyTypeValid(any());
+    }
+
+    @Test
+    public void test_createListInput_fail_addInputsToComponent() throws Exception {
+        ComponentInstListInput createListInputParams = setUpCreateListInputParams();
+        ComponentInstInputsMap componentInstInputsMap = createListInputParams.getComponentInstInputsMap();
+        InputDefinition listInput = createListInputParams.getListInput();
+
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), Mockito.any(ComponentParametersView.class))).thenReturn(Either.left(service));
+        when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
+        when(toscaOperationFacadeMock.addDataTypesToComponent(dataTypesMapCaptor.capture(), eq(COMPONENT_ID))).thenReturn(Either.left(new ArrayList<>()));
+        when(propertyDeclarationOrchestrator.getPropOwnerId(componentInstInputsMap)).thenReturn(COMPONENT_INSTANCE_ID);
+        when(applicationDataTypeCache.getAll()).thenReturn(Either.left(new HashMap<>())); // don't use Collections.emptyMap
+        // for BaseOperation.validatePropertyDefaultValue:
+        when(propertyOperation.isPropertyTypeValid(any())).thenReturn(true);
+        when(propertyOperation.isPropertyInnerTypeValid(any(),any())).thenReturn(new ImmutablePair<>(listInput.getSchemaType(), true));
+        when(propertyOperation.isPropertyDefaultValueValid(any(), any())).thenReturn(true);
+        when(toscaOperationFacadeMock.addInputsToComponent(anyMap(), eq(COMPONENT_ID))).thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+
+        Either<List<InputDefinition>, ResponseFormat> result =
+                testInstance.createListInput(USER_ID, COMPONENT_ID, ComponentTypeEnum.SERVICE, createListInputParams, true, false);
+        assertEquals(true, result.isRight());
+        verify(toscaOperationFacadeMock, times(1)).addInputsToComponent(anyMap(), eq(COMPONENT_ID));
+    }
+
+    @Test
+    public void test_deleteInput_listInput_fail_getComponent() throws Exception {
+        //ComponentInstListInput createListInputParams = setUpCreateListInputParams();
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat());
+
+        Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, LISTINPUT_NAME);
+        assertEquals(true, result.isRight());
+        verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class));
+    }
+
+
+    @Test
+    public void test_deleteInput_listInput_fail_validateInput() throws Exception {
+        InputDefinition listInput = setUpListInput();
+        String inputId = COMPONENT_ID + "." + listInput.getName();
+        listInput.setUniqueId(inputId);
+        service.setInputs(Collections.singletonList(listInput));
+        //ComponentInstListInput createListInputParams = setUpCreateListInputParams();
+        final String NONEXIST_INPUT_NAME = "myInput";
+
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(service));
+        when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat());
+
+        Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, NONEXIST_INPUT_NAME);
+        assertEquals(true, result.isRight());
+        verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class));
+    }
+
+
+    @Test
+    public void test_deleteInput_listInput_fail_lockComponent() throws Exception {
+        InputDefinition listInput = setUpListInput();
+        String inputId = COMPONENT_ID + "." + listInput.getName();
+        listInput.setUniqueId(inputId);
+        service.setInputs(Collections.singletonList(listInput));
+
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(service));
+        //when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat());
+        when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.NOT_FOUND);
+
+        Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, inputId);
+        assertEquals(true, result.isRight());
+        verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class));
+        verify(graphLockOperation, times(1)).lockComponent(COMPONENT_ID, NodeTypeEnum.Service);
+    }
+
+
+    @Test
+    public void test_deleteInput_listInput_fail_deleteInput() throws Exception {
+        InputDefinition listInput = setUpListInput();
+        String inputId = COMPONENT_ID + "." + listInput.getName();
+        listInput.setUniqueId(inputId);
+        service.setInputs(Collections.singletonList(listInput));
+
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(service));
+        when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
+        when(toscaOperationFacadeMock.deleteInputOfResource(service, listInput.getName())).thenReturn(StorageOperationStatus.BAD_REQUEST);
+        when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat());
+
+        Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, inputId);
+        assertEquals(true, result.isRight());
+        verify(toscaOperationFacadeMock, times(1)).getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class));
+        verify(graphLockOperation, times(1)).lockComponent(COMPONENT_ID, NodeTypeEnum.Service);
+        verify(toscaOperationFacadeMock, times(1)).deleteInputOfResource(service, listInput.getName());
+    }
+
+
+    @Test
+    public void test_deleteInput_listInput_success() throws Exception {
+        InputDefinition listInput = setUpListInput();
+        String inputId = COMPONENT_ID + "." + listInput.getName();
+        listInput.setUniqueId(inputId);
+        listInput.setIsDeclaredListInput(true);
+        service.setInputs(Collections.singletonList(listInput));
+        ArgumentCaptor<String> schemaTypeCaptor = ArgumentCaptor.forClass(String.class);
+
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(service));
+        when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
+        when(toscaOperationFacadeMock.deleteInputOfResource(service, listInput.getName())).thenReturn(StorageOperationStatus.OK);
+        //when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat());
+        when(propertyDeclarationOrchestrator.unDeclarePropertiesAsListInputs(service, listInput)).thenReturn(StorageOperationStatus.OK);
+        when(dataTypeBusinessLogic.deletePrivateDataType(eq(service), schemaTypeCaptor.capture()))
+                .thenReturn(Either.left(new DataTypeDefinition())); // TODO: replace to return proper datatype
+        //when(propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(service, listInput)).thenReturn(StorageOperationStatus.OK);
+
+        Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, inputId);
+        assertEquals(true, result.isLeft());
+        verify(propertyDeclarationOrchestrator, times(1)).unDeclarePropertiesAsListInputs(service, listInput);
+        verify(dataTypeBusinessLogic, times(1)).deletePrivateDataType(service, listInput.getSchemaType());
+        assertEquals(listInput.getSchemaType(), schemaTypeCaptor.getValue());
+    }
+
+
+    @Test
+    public void test_deleteInput_input_fail_unDeclare() throws Exception {
+        InputDefinition listInput = setUpListInput();
+        String inputId = COMPONENT_ID + "." + listInput.getName();
+        listInput.setUniqueId(inputId);
+        listInput.setIsDeclaredListInput(false);
+        service.setInputs(Collections.singletonList(listInput));
+
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(service));
+        when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
+        when(toscaOperationFacadeMock.deleteInputOfResource(service, listInput.getName())).thenReturn(StorageOperationStatus.OK);
+        //when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat());
+        when(propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(service, listInput)).thenReturn(StorageOperationStatus.BAD_REQUEST);
+
+        Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, inputId);
+        assertEquals(true, result.isRight());
+        verify(propertyDeclarationOrchestrator, times(1)).unDeclarePropertiesAsInputs(service, listInput);
+    }
+
+
+    @Test
+    public void test_deleteInput_input_success() throws Exception {
+        InputDefinition listInput = setUpListInput();
+        String inputId = COMPONENT_ID + "." + listInput.getName();
+        listInput.setUniqueId(inputId);
+        listInput.setIsDeclaredListInput(false);
+        service.setInputs(Collections.singletonList(listInput));
+
+        when(toscaOperationFacadeMock.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(service));
+        when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)).thenReturn(StorageOperationStatus.OK);
+        when(toscaOperationFacadeMock.deleteInputOfResource(service, listInput.getName())).thenReturn(StorageOperationStatus.OK);
+        //when(componentsUtilsMock.getResponseFormat(any())).thenReturn(new ResponseFormat());
+        when(propertyDeclarationOrchestrator.unDeclarePropertiesAsInputs(service, listInput)).thenReturn(StorageOperationStatus.OK);
+
+        Either<InputDefinition, ResponseFormat> result = testInstance.deleteInput(COMPONENT_ID, USER_ID, inputId);
+        assertEquals(true, result.isLeft());
+        verify(propertyDeclarationOrchestrator, times(1)).unDeclarePropertiesAsInputs(service, listInput);
+    }
+
 }
index acfa721..f5d4aab 100644 (file)
@@ -1,6 +1,7 @@
 package org.openecomp.sdc.be.components.property;
 
 import fj.data.Either;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -8,19 +9,25 @@ import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
+import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
 import org.openecomp.sdc.be.components.utils.AnnotationBuilder;
 import org.openecomp.sdc.be.components.utils.InputsBuilder;
+import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder;
 import org.openecomp.sdc.be.components.utils.ResourceBuilder;
 import org.openecomp.sdc.be.datatypes.elements.Annotation;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstanceInput;
 import org.openecomp.sdc.be.model.ComponentInstancePropInput;
 import org.openecomp.sdc.be.model.ComponentParametersView;
 import org.openecomp.sdc.be.model.InputDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
 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.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -41,6 +48,12 @@ public class ComponentInstanceInputPropertyDeclaratorTest extends PropertyDeclar
     @Mock
     private ToscaOperationFacade toscaOperationFacade;
 
+    @Mock
+    private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
+
+    @Mock
+    private PropertyOperation propertyOperation;
+
     @Captor
     private ArgumentCaptor<ComponentParametersView> inputsFilterCaptor;
 
@@ -50,8 +63,8 @@ public class ComponentInstanceInputPropertyDeclaratorTest extends PropertyDeclar
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        testInstance = new ComponentInstanceInputPropertyDeclarator(mockComponentUtils(), null,
-                toscaOperationFacade, null, mockExceptionUtils());
+        testInstance = new ComponentInstanceInputPropertyDeclarator(mockComponentUtils(), propertyOperation,
+                toscaOperationFacade, componentInstanceBusinessLogic, mockExceptionUtils());
         annotation1 =  AnnotationBuilder.create()
                 .setType("annotationType1")
                 .setName("annotation1")
@@ -88,6 +101,55 @@ public class ComponentInstanceInputPropertyDeclaratorTest extends PropertyDeclar
         assertThatExceptionOfType(StorageException.class).isThrownBy(() -> testInstance.declarePropertiesAsInputs(resource, "inst1", propsToDeclare));
     }
 
+    @Test
+    public void unDeclarePropertiesAsListInputsTest() {
+        InputDefinition inputToDelete = new InputDefinition();
+        inputToDelete.setUniqueId(INPUT_ID);
+        inputToDelete.setName(INPUT_ID);
+        inputToDelete.setIsDeclaredListInput(true);
+
+        Component component = createComponentWithListInput(INPUT_ID, "innerPropName");
+        PropertyDefinition prop = new PropertyDataDefinitionBuilder()
+                .setName("propName")
+                .setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName"))
+                .setType("list")
+                .setUniqueId("propName")
+                .addGetInputValue(INPUT_ID)
+                .build();
+        component.setProperties(Collections.singletonList(prop));
+
+        List<ComponentInstanceInput> ciPropList = new ArrayList<>();
+        ComponentInstanceInput ciProp = new ComponentInstanceInput();
+        List<String> pathOfComponentInstances = new ArrayList<>();
+        pathOfComponentInstances.add("pathOfComponentInstances");
+        ciProp.setPath(pathOfComponentInstances);
+        ciProp.setUniqueId("componentInstanceId");
+        ciProp.setDefaultValue("default value");
+        ciProp.setComponentInstanceId("componentInstanceId");
+        ciProp.setComponentInstanceName("componentInstanceName");
+        ciProp.setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName"));
+        ciPropList.add(ciProp);
+
+        when(componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(eq(component), eq(INPUT_ID))).thenReturn(ciPropList);
+        when(propertyOperation.findDefaultValueFromSecondPosition(eq(pathOfComponentInstances), eq(ciProp.getUniqueId()), eq(ciProp.getDefaultValue()))).thenReturn(Either.left(ciProp.getDefaultValue()));
+        when(toscaOperationFacade.updateComponentInstanceInputs(eq(component), eq(ciProp.getComponentInstanceId()), eq(ciPropList))).thenReturn(StorageOperationStatus.OK);
+        StorageOperationStatus storageOperationStatus = testInstance.unDeclarePropertiesAsListInputs(component, inputToDelete);
+
+        assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK);
+    }
+
+    @Test
+    public void unDeclarePropertiesAsListInputsTest_whenNoListInput_returnOk() {
+        InputDefinition input = new InputDefinition();
+        input.setUniqueId(INPUT_ID);
+        input.setName(INPUT_ID);
+        input.setValue("value");
+        List<ComponentInstanceInput> resList = new ArrayList<>();
+        when(componentInstanceBusinessLogic.getComponentInstanceInputsByInputId(eq(resource), eq(INPUT_ID))).thenReturn(resList);
+        StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input);
+        Assert.assertEquals(status, StorageOperationStatus.OK);
+    }
+
     private void verifyInputAnnotations(InputDefinition inputDefinition) {
         List<Annotation> annotations = inputDefinition.getAnnotations();
         assertThat(annotations)
@@ -105,4 +167,19 @@ public class ComponentInstanceInputPropertyDeclaratorTest extends PropertyDeclar
                 .build();
     }
 
-}
\ No newline at end of file
+    private Component createComponentWithListInput(String inputName, String propName) {
+        InputDefinition input = InputsBuilder.create()
+                .setName(inputName)
+                .build();
+
+        input.setUniqueId(INPUT_ID);
+        input.setName(INPUT_ID);
+        input.setDefaultValue("defaultValue");
+        input.setValue(generateGetInputValueAsListInput(inputName, propName));
+
+        return new ResourceBuilder()
+                .setUniqueId(RESOURCE_ID)
+                .addInput(input)
+                .build();
+    }
+}
index 5752ae2..f59adad 100644 (file)
@@ -1,26 +1,25 @@
 package org.openecomp.sdc.be.components.property;
 
 import fj.data.Either;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
+import org.mockito.*;
 import org.mockito.junit.MockitoJUnitRunner;
+import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
+import org.openecomp.sdc.be.components.utils.InputsBuilder;
 import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder;
+import org.openecomp.sdc.be.components.utils.ResourceBuilder;
 import org.openecomp.sdc.be.dao.utils.MapUtil;
 import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.model.*;
 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -37,6 +36,11 @@ public class ComponentInstancePropertyDeclaratorTest extends PropertyDeclaratorT
     private ComponentInstancePropertyDeclarator testInstance;
     @Mock
     private ToscaOperationFacade toscaOperationFacade;
+    @Mock
+    private ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
+    @Mock
+    private PropertyOperation propertyOperation;
+
     @Captor
     private ArgumentCaptor<Map<String, List<ComponentInstanceProperty>>> instancePropertiesCaptor;
 
@@ -98,6 +102,100 @@ public class ComponentInstancePropertyDeclaratorTest extends PropertyDeclaratorT
         verifyUpdatedComplexProperty(capturedInstanceProperties, inputs);
     }
 
+    @Test
+    public void declarePropertiesAsListInput() {
+        // construct arguments
+        List<PropertyDataDefinition> properties = Arrays.asList(prop1, prop2);
+        List<ComponentInstancePropInput> propsToDeclare = createInstancePropInputList(properties);
+        InputDefinition input = new InputDefinition(new PropertyDataDefinitionBuilder()
+                .setName("listinput")
+                .setType("list")
+                .setDescription("description")
+                .setSchemaType("org.onap.datatype.listinput")
+                .build());
+        // mock returns
+        when(toscaOperationFacade.addComponentInstancePropertiesToComponent(eq(resource), instancePropertiesCaptor.capture())).thenReturn(Either.left(Collections.emptyMap()));
+        Either<InputDefinition, StorageOperationStatus> result = testInstance.declarePropertiesAsListInput(resource, "inst1", propsToDeclare, input);
+        // validate result
+        assertThat(result.isLeft()).isTrue();
+        List<ComponentInstanceProperty> capturedInstanceProperties = instancePropertiesCaptor.getValue().get(INSTANCE_ID);
+        assertThat(capturedInstanceProperties.size()).isEqualTo(2);
+        Map<String, PropertyDataDefinition> propertiesMap =
+                properties.stream().collect(Collectors.toMap(PropertyDataDefinition::getName, e->e));
+        for(ComponentInstanceProperty instanceProperty: capturedInstanceProperties) {
+            assertThat(propertiesMap.containsKey(instanceProperty.getName())).isTrue();
+            PropertyDataDefinition property = propertiesMap.get(instanceProperty.getName());
+            assertThat(instanceProperty.getType()).isEqualTo(property.getType());
+            assertThat(instanceProperty.isGetInputProperty()).isTrue();
+        }
+    }
+
+    @Test
+    public void declarePropertiesAsListInput_propertyOwnerNotFound() {
+        // construct arguments
+        List<PropertyDataDefinition> properties = Arrays.asList(prop1, prop2);
+        List<ComponentInstancePropInput> propsToDeclare = createInstancePropInputList(properties);
+        InputDefinition input = new InputDefinition(new PropertyDataDefinitionBuilder()
+                .setName("listinput")
+                .setType("list")
+                .setDescription("description")
+                .setSchemaType("org.onap.datatype.listinput")
+                .build());
+        Either<InputDefinition, StorageOperationStatus> result = testInstance.declarePropertiesAsListInput(resource, "inst2", propsToDeclare, input);
+        // validate result
+        assertThat(result.isRight()).isTrue();
+        assertThat(result.right().value()).isEqualTo(StorageOperationStatus.NOT_FOUND);
+    }
+
+    @Test
+    public void unDeclarePropertiesAsListInputsTest() {
+        InputDefinition inputToDelete = new InputDefinition();
+        inputToDelete.setUniqueId(INPUT_ID);
+        inputToDelete.setName(INPUT_ID);
+        inputToDelete.setIsDeclaredListInput(true);
+
+        Component component = createComponentWithListInput(INPUT_ID, "innerPropName");
+        PropertyDefinition prop = new PropertyDataDefinitionBuilder()
+                .setName("propName")
+                .setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName"))
+                .setType("list")
+                .setUniqueId("propName")
+                .addGetInputValue(INPUT_ID)
+                .build();
+        component.setProperties(Collections.singletonList(prop));
+
+        List<ComponentInstanceProperty> ciPropList = new ArrayList<>();
+        ComponentInstanceProperty ciProp = new ComponentInstanceProperty();
+        List<String> pathOfComponentInstances = new ArrayList<>();
+        pathOfComponentInstances.add("pathOfComponentInstances");
+        ciProp.setPath(pathOfComponentInstances);
+        ciProp.setUniqueId("componentInstanceId");
+        ciProp.setDefaultValue("default value");
+        ciProp.setComponentInstanceId("componentInstanceId");
+        ciProp.setComponentInstanceName("componentInstanceName");
+        ciProp.setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName"));
+        ciPropList.add(ciProp);
+
+        when(componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(eq(component), eq(INPUT_ID))).thenReturn(ciPropList);
+        when(propertyOperation.findDefaultValueFromSecondPosition(eq(pathOfComponentInstances), eq(ciProp.getUniqueId()), eq(ciProp.getDefaultValue()))).thenReturn(Either.left(ciProp.getDefaultValue()));
+        when(toscaOperationFacade.updateComponentInstanceProperties(eq(component), eq(ciProp.getComponentInstanceId()), eq(ciPropList))).thenReturn(StorageOperationStatus.OK);
+        StorageOperationStatus storageOperationStatus = testInstance.unDeclarePropertiesAsListInputs(component, inputToDelete);
+
+        assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK);
+    }
+
+    @Test
+    public void unDeclarePropertiesAsListInputsTest_whenNoListInput_returnOk() {
+        InputDefinition input = new InputDefinition();
+        input.setUniqueId(INPUT_ID);
+        input.setName(INPUT_ID);
+        input.setValue("value");
+        List<ComponentInstanceProperty> resList = new ArrayList<>();
+        when(componentInstanceBusinessLogic.getComponentInstancePropertiesByInputId(eq(resource), eq(INPUT_ID))).thenReturn(resList);
+        StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input);
+        Assert.assertEquals(status, StorageOperationStatus.OK);
+    }
+    
     private void verifyUpdatedProperties(List<PropertyDataDefinition> properties, List<ComponentInstanceProperty> capturedInstanceProperties, List<InputDefinition> inputs) {
         assertThat(capturedInstanceProperties).hasSize(properties.size());
         Map<String, ComponentInstanceProperty> updatedPropertiesByName = MapUtil.toMap(capturedInstanceProperties, ComponentInstanceProperty::getName);
@@ -204,4 +302,19 @@ public class ComponentInstancePropertyDeclaratorTest extends PropertyDeclaratorT
         assertThat(input.getInstanceUniqueId()).isEqualTo(INSTANCE_ID);
     }
 
-}
\ No newline at end of file
+    private Component createComponentWithListInput(String inputName, String propName) {
+        InputDefinition input = InputsBuilder.create()
+                .setName(inputName)
+                .build();
+
+        input.setUniqueId(INPUT_ID);
+        input.setName(INPUT_ID);
+        input.setDefaultValue("defaultValue");
+        input.setValue(generateGetInputValueAsListInput(inputName, propName));
+
+        return new ResourceBuilder()
+                .setUniqueId(RESOURCE_ID)
+                .addInput(input)
+                .build();
+    }
+}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclaratorTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclaratorTest.java
new file mode 100644 (file)
index 0000000..7069fe8
--- /dev/null
@@ -0,0 +1,175 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019 Fujitsu Limited. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.components.property;
+
+import fj.data.Either;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
+import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
+import org.openecomp.sdc.be.model.InputDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class ComponentPropertyDeclaratorTest extends PropertyDeclaratorTestBase {
+
+    @InjectMocks
+    private ComponentPropertyDeclarator testInstance;
+    @Mock
+    private PropertyBusinessLogic propertyBusinessLogic;
+    @Mock
+    private PropertyOperation propertyOperation;
+    @Mock
+    private ToscaOperationFacade toscaOperationFacade;
+
+    @Test
+    public void unDeclarePropertiesAsListInputsTest_whenPropertyUsedByOperation() {
+        InputDefinition input = new InputDefinition();
+        input.setUniqueId(INPUT_ID);
+        input.setName(INPUT_ID);
+        input.setValue("value");
+
+        PropertyDefinition propertyDefinition = new PropertyDefinition(input);
+
+        when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), eq(propertyDefinition))).thenReturn(true);
+        StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input);
+        Assert.assertEquals(status, StorageOperationStatus.DECLARED_INPUT_USED_BY_OPERATION);
+    }
+
+    @Test
+    public void unDeclarePropertiesAsListInputsTest_whenNotPresentPropertyToUpdateCandidate() {
+        InputDefinition input = new InputDefinition();
+        input.setUniqueId(INPUT_ID);
+        input.setName(INPUT_ID);
+        input.setValue("value");
+
+        PropertyDefinition propertyDefinition = new PropertyDefinition();
+        resource.setProperties(Collections.singletonList(propertyDefinition));
+
+        when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), any(PropertyDefinition.class))).thenReturn(false);
+        StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input);
+        Assert.assertEquals(status, StorageOperationStatus.OK);
+    }
+
+    @Test
+    public void unDeclarePropertiesAsListInputsTest_whenPropertiesEmpty() {
+        InputDefinition input = new InputDefinition();
+        input.setUniqueId(INPUT_ID);
+        input.setName(INPUT_ID);
+        input.setValue("value");
+
+        resource.setProperties(new ArrayList<>());
+
+        when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), any(PropertyDefinition.class))).thenReturn(false);
+        StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input);
+        Assert.assertEquals(status, StorageOperationStatus.OK);
+    }
+
+    @Test
+    public void unDeclarePropertiesAsListInputsTest_whenPropertiesToUpdateIsEmpty() {
+        InputDefinition input = new InputDefinition();
+        input.setUniqueId(INPUT_ID);
+        input.setName(INPUT_ID);
+        input.setValue("value");
+
+        PropertyDefinition propertyDefinition = new PropertyDefinition(input);
+        resource.setProperties(Collections.singletonList(propertyDefinition));
+
+        when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), eq(propertyDefinition))).thenReturn(false);
+        StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input);
+        Assert.assertEquals(status, StorageOperationStatus.OK);
+    }
+
+    @Test
+    public void unDeclarePropertiesAsListInputsTest_singleProperty() {
+        InputDefinition input = new InputDefinition();
+        input.setUniqueId(INPUT_ID);
+        input.setName(INPUT_ID);
+        input.setValue("value");
+        input.setDefaultValue("default value");
+
+        PropertyDefinition propertyDefinition = new PropertyDefinition(input);
+        List<GetInputValueDataDefinition> getInputValueList = new ArrayList<>();
+        getInputValueList.add(buildGetInputValue(INPUT_ID));
+        getInputValueList.add(buildGetInputValue("otherInputId"));
+        propertyDefinition.setGetInputValues(getInputValueList);
+        propertyDefinition.setUniqueId("propertyId");
+        propertyDefinition.setDefaultValue("default value");
+        propertyDefinition.setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName"));
+        resource.setProperties(Collections.singletonList(propertyDefinition));
+
+        when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), any())).thenReturn(false);
+        when(propertyOperation.findDefaultValueFromSecondPosition(eq(Collections.emptyList()), eq(propertyDefinition.getUniqueId()), eq(propertyDefinition.getDefaultValue()))).thenReturn(Either.left(propertyDefinition.getDefaultValue()));
+        when(toscaOperationFacade.updatePropertyOfComponent(eq(resource), any())).thenReturn(Either.left(propertyDefinition));
+        StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input);
+        Assert.assertEquals(status, StorageOperationStatus.OK);
+    }
+
+    @Test
+    public void unDeclarePropertiesAsListInputsTest_UnDeclareInputFail() {
+        InputDefinition input = new InputDefinition();
+        input.setUniqueId(INPUT_ID);
+        input.setName(INPUT_ID);
+        input.setValue("value");
+        input.setDefaultValue("default value");
+
+        PropertyDefinition propertyDefinition = new PropertyDefinition(input);
+        List<GetInputValueDataDefinition> getInputValueList = new ArrayList<>();
+        getInputValueList.add(buildGetInputValue(INPUT_ID));
+        getInputValueList.add(buildGetInputValue("otherInputId"));
+        propertyDefinition.setGetInputValues(getInputValueList);
+        propertyDefinition.setUniqueId("propertyId");
+        propertyDefinition.setDefaultValue("default value");
+        propertyDefinition.setValue(generateGetInputValueAsListInput(INPUT_ID, "innerPropName"));
+        resource.setProperties(Collections.singletonList(propertyDefinition));
+
+        when(propertyBusinessLogic.isPropertyUsedByOperation(eq(resource), any())).thenReturn(false);
+        when(propertyOperation.findDefaultValueFromSecondPosition(eq(Collections.emptyList()), eq(propertyDefinition.getUniqueId()), eq(propertyDefinition.getDefaultValue()))).thenReturn(Either.left(propertyDefinition.getDefaultValue()));
+        when(toscaOperationFacade.updatePropertyOfComponent(eq(resource), any())).thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        StorageOperationStatus status = testInstance.unDeclarePropertiesAsListInputs(resource, input);
+        Assert.assertEquals(status, StorageOperationStatus.NOT_FOUND);
+    }
+
+    private GetInputValueDataDefinition buildGetInputValue(String InputId) {
+        GetInputValueDataDefinition getInputValue = new GetInputValueDataDefinition();
+        getInputValue.setInputId(InputId);
+        getInputValue.setInputName(InputId);
+
+        return getInputValue;
+    }
+
+}
index 63e39b5..72706db 100644 (file)
@@ -136,6 +136,56 @@ public class GroupPropertyDeclaratorTest extends PropertyDeclaratorTestBase {
         assertThat(updatedProperty.getUniqueId()).isEqualTo(getInputPropForInput.getUniqueId());
     }
 
+    @Test
+    public void testUnDeclarePropertiesAsListInputs_whenComponentHasNoGroups_returnOk() {
+        Resource resource = new Resource();
+        StorageOperationStatus storageOperationStatus = groupPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input);
+        assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK);
+        verifyZeroInteractions(groupOperation);
+    }
+
+    @Test
+    public void testUnDeclarePropertiesAsListInputs_whenNoPropertiesFromGroupMatchInputId_returnOk() {
+        StorageOperationStatus storageOperationStatus = groupPropertyDeclarator.unDeclarePropertiesAsListInputs(createResourceWithGroup(), input);
+        assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK);
+        verifyZeroInteractions(groupOperation);
+    }
+
+    @Test
+    public void whenFailingToUpdateDeclaredPropertiesAsListInputs_returnErrorStatus() {
+        Resource resource = createResourceWithGroups(GROUP_ID);
+        Optional<GroupDefinition> groupDefinition = resource.getGroupById(GROUP_ID);
+        assertThat(groupDefinition.isPresent()).isTrue();
+        PropertyDataDefinition getInputPropForInput = buildGetInputProperty(INPUT_ID);
+        groupDefinition.get().setProperties(Collections.singletonList(getInputPropForInput));
+        when(propertyOperation.findDefaultValueFromSecondPosition(Collections.emptyList(), getInputPropForInput.getUniqueId(), getInputPropForInput.getDefaultValue())).thenReturn(Either.left(getInputPropForInput.getDefaultValue()));
+        when(groupOperation.updateGroupProperties(eq(resource), eq(GROUP_ID), updatedPropsCapture.capture())).thenReturn(StorageOperationStatus.GENERAL_ERROR);
+        StorageOperationStatus storageOperationStatus = groupPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input);
+        assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.GENERAL_ERROR);
+    }
+
+    @Test
+    public void testUnDeclarePropertiesAsListInputs_propertiesUpdatedCorrectly() {
+        Resource resource = createResourceWithGroups(GROUP_ID, "groupId3");
+        Optional<GroupDefinition> groupDefinition = resource.getGroupById(GROUP_ID);
+        PropertyDataDefinition getInputPropForInput = buildGetInputProperty(INPUT_ID);
+        PropertyDataDefinition someOtherProperty = new PropertyDataDefinitionBuilder().build();
+        groupDefinition.get().setProperties(Arrays.asList(getInputPropForInput, someOtherProperty));
+
+        when(propertyOperation.findDefaultValueFromSecondPosition(Collections.emptyList(), getInputPropForInput.getUniqueId(), getInputPropForInput.getDefaultValue())).thenReturn(Either.left(getInputPropForInput.getDefaultValue()));
+        when(groupOperation.updateGroupProperties(eq(resource), eq(GROUP_ID), updatedPropsCapture.capture())).thenReturn(StorageOperationStatus.OK);
+        StorageOperationStatus storageOperationStatus = groupPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input);
+
+        assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK);
+        List<PropertyDataDefinition> updatedProperties = updatedPropsCapture.getValue();
+        assertThat(updatedProperties).hasSize(1);
+        PropertyDataDefinition updatedProperty = updatedProperties.get(0);
+        assertThat(updatedProperty.isGetInputProperty()).isFalse();
+        assertThat(updatedProperty.getValue()).isEmpty();
+        assertThat(updatedProperty.getDefaultValue()).isEqualTo(getInputPropForInput.getDefaultValue());
+        assertThat(updatedProperty.getUniqueId()).isEqualTo(getInputPropForInput.getUniqueId());
+    }
+
     private Resource createResourceWithGroup() {
         return createResourceWithGroups(GROUP_ID);
     }
index 72c2654..f85388a 100644 (file)
@@ -134,6 +134,55 @@ public class PolicyPropertyDeclaratorTest extends PropertyDeclaratorTestBase {
         assertThat(updatedProperty.getUniqueId()).isEqualTo(getInputPropForInput.getUniqueId());
     }
 
+    @Test
+    public void testUnDeclarePropertiesAsListInputs_whenComponentHasNoPolicies_returnOk() {
+        Resource resource = new Resource();
+        StorageOperationStatus storageOperationStatus = policyPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input);
+        assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK);
+        verifyZeroInteractions(policyOperation);
+    }
+
+    @Test
+    public void testUnDeclarePropertiesAsListInputs_whenNoPropertiesFromPolicyMatchInputId_returnOk() {
+        StorageOperationStatus storageOperationStatus = policyPropertyDeclarator.unDeclarePropertiesAsListInputs(createResourceWithPolicy(), input);
+        assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK);
+        verifyZeroInteractions(policyOperation);
+    }
+
+    @Test
+    public void whenFailingToUpdateDeclaredPropertiesAsListInputs_returnErrorStatus() {
+        Resource resource = createResourceWithPolicies(POLICY_ID);
+        PolicyDefinition policyDefinition = resource.getPolicies().get(POLICY_ID);
+        PropertyDataDefinition getInputPropForInput = buildGetInputProperty(INPUT_ID);
+        policyDefinition.setProperties(Collections.singletonList(getInputPropForInput));
+        when(propertyOperation.findDefaultValueFromSecondPosition(Collections.emptyList(), getInputPropForInput.getUniqueId(), getInputPropForInput.getDefaultValue())).thenReturn(Either.left(getInputPropForInput.getDefaultValue()));
+        when(policyOperation.updatePolicyProperties(eq(resource), eq(POLICY_ID), updatedPropsCapture.capture())).thenReturn(StorageOperationStatus.GENERAL_ERROR);
+        StorageOperationStatus storageOperationStatus = policyPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input);
+        assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.GENERAL_ERROR);
+    }
+
+    @Test
+    public void testUnDeclarePropertiesAsListInputs_propertiesUpdatedCorrectly() {
+        Resource resource = createResourceWithPolicies(POLICY_ID, "policyId3");
+        PolicyDefinition policyDefinition = resource.getPolicies().get(POLICY_ID);
+        PropertyDataDefinition getInputPropForInput = buildGetInputProperty(INPUT_ID);
+        PropertyDataDefinition someOtherProperty = new PropertyDataDefinitionBuilder().build();
+        policyDefinition.setProperties(Arrays.asList(getInputPropForInput, someOtherProperty));
+
+        when(propertyOperation.findDefaultValueFromSecondPosition(Collections.emptyList(), getInputPropForInput.getUniqueId(), getInputPropForInput.getDefaultValue())).thenReturn(Either.left(getInputPropForInput.getDefaultValue()));
+        when(policyOperation.updatePolicyProperties(eq(resource), eq(POLICY_ID), updatedPropsCapture.capture())).thenReturn(StorageOperationStatus.OK);
+        StorageOperationStatus storageOperationStatus = policyPropertyDeclarator.unDeclarePropertiesAsListInputs(resource, input);
+
+        assertThat(storageOperationStatus).isEqualTo(StorageOperationStatus.OK);
+        List<PropertyDataDefinition> updatedProperties = updatedPropsCapture.getValue();
+        assertThat(updatedProperties).hasSize(1);
+        PropertyDataDefinition updatedProperty = updatedProperties.get(0);
+        assertThat(updatedProperty.isGetInputProperty()).isFalse();
+        assertThat(updatedProperty.getValue()).isEmpty();
+        assertThat(updatedProperty.getDefaultValue()).isEqualTo(getInputPropForInput.getDefaultValue());
+        assertThat(updatedProperty.getUniqueId()).isEqualTo(getInputPropForInput.getUniqueId());
+    }
+
     private Resource createResourceWithPolicy() {
         return createResourceWithPolicies(POLICY_ID);
     }
index 1a2a76e..ef1d45d 100644 (file)
@@ -4,23 +4,32 @@ import fj.data.Either;
 import mockit.Deencapsulation;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Answers;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-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.ComponentInstancePropInput;
+import org.openecomp.sdc.be.model.InputDefinition;
+import org.openecomp.sdc.be.model.Resource;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 
-import java.util.*;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 public class PropertyDecelerationOrchestratorTest {
 
        @InjectMocks
        PropertyDeclarationOrchestrator testSubject;
 
-       @Mock
+       @Mock(answer = Answers.CALLS_REAL_METHODS)
        List<PropertyDeclarator> propertyDeceleratorsMock;
-       
+
        @Mock
        private ComponentInstanceInputPropertyDeclarator componentInstanceInputPropertyDecelerator;
        @Mock
@@ -44,6 +53,21 @@ public class PropertyDecelerationOrchestratorTest {
                result = testSubject.declarePropertiesToInputs(component, componentInstInputsMap);
        }
 
+       @Test
+       public void testDeclarePropertiesToListInputs() throws Exception {
+               Component component = new Resource();
+               ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap();
+               Map<String, List<ComponentInstancePropInput>> componentInstanceInputsMap = new HashMap<>();
+               List<ComponentInstancePropInput> value = new LinkedList<>();
+               componentInstanceInputsMap.put("mock", value);
+               componentInstInputsMap.setComponentInstanceInputsMap(componentInstanceInputsMap);
+               InputDefinition input = new InputDefinition();
+               Either<InputDefinition, StorageOperationStatus> result;
+
+               // default test
+               result = testSubject.declarePropertiesToListInput(component, componentInstInputsMap, input);
+       }
+
        @Test
        public void testUnDeclarePropertiesAsInputs() throws Exception {
                Component component = new Resource();
@@ -58,6 +82,33 @@ public class PropertyDecelerationOrchestratorTest {
                result = testSubject.unDeclarePropertiesAsInputs(component, inputToDelete);
        }
 
+       @Test
+       public void testUnDeclarePropertiesAsListInputs() throws Exception {
+               Component component = new Resource();
+               InputDefinition inputToDelete = new InputDefinition();
+               StorageOperationStatus result;
+
+               Iterator<PropertyDeclarator> mockIter = Mockito.mock(Iterator.class);
+               Mockito.when(propertyDeceleratorsMock.iterator()).thenReturn(mockIter);
+               Mockito.when(mockIter.hasNext()).thenReturn(false);
+
+               // default test
+               result = testSubject.unDeclarePropertiesAsListInputs(component, inputToDelete);
+       }
+
+       @Test
+       public void testGetPropOwnerId() throws Exception {
+               ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap();
+               Map<String, List<ComponentInstancePropInput>> componentInstanceInputsMap = new HashMap<>();
+               List<ComponentInstancePropInput> value = new LinkedList<>();
+               componentInstanceInputsMap.put("mock", value);
+               componentInstInputsMap.setComponentInstanceInputsMap(componentInstanceInputsMap);
+               String result;
+
+               // default test
+               result = Deencapsulation.invoke(testSubject, "getPropOwnerId", componentInstInputsMap);
+       }
+
        @Test(expected = IllegalStateException.class)
        public void testGetPropertyDecelerator() throws Exception {
                ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap();
index bd21f68..f1f4d0a 100644 (file)
@@ -77,6 +77,10 @@ public class PropertyDeclaratorTestBase {
         return String.format("{\"%s\":\"%s\"}", GET_INPUT, value);
     }
 
+    String generateGetInputValueAsListInput(String inputName, String inputProperty) {
+        return String.format("{\"%s\":[\"%s\",\"INDEX\",\"%s\"]}", GET_INPUT, inputName, inputProperty);
+    }
+
     private void verifyInputPropertiesList(PropertyDataDefinition updatedProperty, InputDefinition input) {
         assertThat(input.getProperties()).hasSize(1);
         assertThat(new ComponentInstanceProperty(updatedProperty)).isEqualTo(input.getProperties().get(0));
index eb12377..3922dd8 100644 (file)
@@ -218,14 +218,16 @@ public class UiComponentDataConverterTest {
     public void getUiDataTransferFromResourceByParams_policies() {
         Resource resourceWithPolicies = buildResourceWithPolicies();
         UiComponentDataTransfer componentDTO = uiComponentDataConverter.getUiDataTransferFromResourceByParams(resourceWithPolicies, Collections.singletonList("policies"));
-        assertThat(componentDTO.getPolicies()).isEqualTo(resourceWithPolicies.resolvePoliciesList());
+        List<PolicyDefinition> expectedPolicies = resourceWithPolicies.resolvePoliciesList();
+        assertThat(componentDTO.getPolicies()).containsExactlyInAnyOrder((PolicyDefinition[]) expectedPolicies.toArray(new PolicyDefinition[expectedPolicies.size()]));
     }
 
     @Test
     public void getUiDataTransferFromServiceByParams_policies() {
         Service resourceWithPolicies = buildServiceWithPolicies();
         UiComponentDataTransfer componentDTO = uiComponentDataConverter.getUiDataTransferFromServiceByParams(resourceWithPolicies, Collections.singletonList("policies"));
-        assertThat(componentDTO.getPolicies()).isEqualTo(resourceWithPolicies.resolvePoliciesList());
+        List<PolicyDefinition> expectedPolicies = resourceWithPolicies.resolvePoliciesList();
+        assertThat(componentDTO.getPolicies()).containsExactlyInAnyOrder((PolicyDefinition[]) expectedPolicies.toArray(new PolicyDefinition[expectedPolicies.size()]));
     }
 
     @Test
index 9ff55c2..0718470 100644 (file)
-package org.openecomp.sdc.be.servlets;
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019 Fujitsu Limited. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
 
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.core.Response;
+package org.openecomp.sdc.be.servlets;
 
+import fj.data.Either;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.grizzly.http.util.HttpStatus;
+import org.junit.Before;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.openecomp.sdc.be.components.impl.DataTypeBusinessLogic;
 import org.openecomp.sdc.be.components.impl.InputsBusinessLogic;
+import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.impl.ServletUtils;
+import org.openecomp.sdc.be.impl.WebAppContextWrapper;
 import org.openecomp.sdc.be.model.ComponentInstInputsMap;
+import org.openecomp.sdc.be.model.ComponentInstListInput;
+import org.openecomp.sdc.be.model.ComponentInstancePropInput;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
+import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
+import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.exception.ResponseFormat;
+import org.springframework.web.context.WebApplicationContext;
 
-import fj.data.Either;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpSession;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.*;
+
+public class InputsServletTest extends JerseySpringBaseTest {
+
+    /* Constants */
+    private static final String RESOURCE_ID = "serviceId";
+    private static final String USER_ID = "userId";
+    private static final String COMPONENT_INSTANCE_ID = "instanceId";
+    private static final String COMPONENT_ID = "componentId";
+    private static final String INSTANCE_INPUT_ID = "inputId";
+    private static final String LISTINPUT_NAME = "listInput";
+    private static final String LISTINPUT_SCHEMA_TYPE = "org.onap.datatypes.listinput";
+    private static final String LISTINPUT_PROP1_NAME = "prop1";
+    private static final String LISTINPUT_PROP1_TYPE = "string";
+    private static final String LISTINPUT_PROP2_NAME = "prop2";
+    private static final String LISTINPUT_PROP2_TYPE = "integer";
+
+    /* Test subject */
+    private InputsServletForTest testSubject;
+
+    /* Mocks */
+    private InputsBusinessLogic inputsBusinessLogic;
+    private DataTypeBusinessLogic dataTypeBusinessLogic;
+    private HttpSession httpSession;
+    private ServletContext servletContext;
+    private WebApplicationContext webApplicationContext;
+    private ComponentsUtils componentsUtils;
+    private ServletUtils servletUtils;
+
+    /**
+     * This class extends the original InputsServlet
+     * and provides methods to inject mocks
+     */
+    class InputsServletForTest extends InputsServlet {
+        public void setComponentsUtils(ComponentsUtils componentsUtils) {
+            this.componentsUtils = componentsUtils;
+        }
+
+        public void setServletUtils(ServletUtils servletUtils) {
+            this.servletUtils = servletUtils;
+        }
+    }
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        inputsBusinessLogic = mock(InputsBusinessLogic.class);
+        dataTypeBusinessLogic = mock(DataTypeBusinessLogic.class);
+        servletContext = mock(ServletContext.class);
+        httpSession = mock(HttpSession.class);
+        webApplicationContext = mock(WebApplicationContext.class);
+        componentsUtils = mock(ComponentsUtils.class);
+        servletUtils = mock(ServletUtils.class);
+        when(request.getSession()).thenReturn(httpSession);
+        when(httpSession.getServletContext()).thenReturn(servletContext);
+        when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR)).thenReturn(new WebAppContextWrapper());
+        when(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)).thenReturn(webApplicationContext);
+        when(webApplicationContext.getBean(InputsBusinessLogic.class)).thenReturn(inputsBusinessLogic);
+        when(webApplicationContext.getBean(DataTypeBusinessLogic.class)).thenReturn(dataTypeBusinessLogic);
+        testSubject.setComponentsUtils(componentsUtils);
+        testSubject.setServletUtils(servletUtils);
+        when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils);
+    }
+
+
+    @Override
+    protected ResourceConfig configure() {
+        testSubject = new InputsServletForTest();
+        return super.configure().register(testSubject);
+    }
+
+
+    private InputDefinition setUpListInput() {
+        InputDefinition listInput = new InputDefinition();
+        listInput.setName(LISTINPUT_NAME);
+        listInput.setType("list");
+        SchemaDefinition listInputSchema = new SchemaDefinition();
+        listInputSchema.setProperty(new PropertyDataDefinitionBuilder()
+                .setType(LISTINPUT_SCHEMA_TYPE)
+                .setIsRequired(false)
+                .build()
+        );
+        listInput.setSchema(listInputSchema);
+        return listInput;
+    }
+
+    private ComponentInstListInput setUpCreateListInputParams() {
+        ComponentInstListInput componentInstListInput = new ComponentInstListInput();
+
+        // Create a "list input"
+        InputDefinition listInput = setUpListInput();
+        componentInstListInput.setListInput(listInput);
+
+        // Create ComponentInstancePropInputs
+        // for inputs in the ComponentInstance
+        Map<String, List<ComponentInstancePropInput>> propInputsListMap = new HashMap<>();
+        // Add 2 PropInputs. property owner is COMPONENT_INSTANCE_ID
+        List<ComponentInstancePropInput> propInputsList = new ArrayList<>();
+        ComponentInstancePropInput propInput = new ComponentInstancePropInput();
+        propInput.setName(LISTINPUT_PROP1_NAME);
+        propInput.setType(LISTINPUT_PROP1_TYPE);
+        propInput.setUniqueId(COMPONENT_INSTANCE_ID + "." + LISTINPUT_PROP1_NAME);
+        propInputsList.add(propInput);
+        propInput = new ComponentInstancePropInput();
+        propInput.setName(LISTINPUT_PROP2_NAME);
+        propInput.setType(LISTINPUT_PROP2_TYPE);
+        propInput.setUniqueId(COMPONENT_INSTANCE_ID + "." + LISTINPUT_PROP2_NAME);
+        propInputsList.add(propInput);
+        propInputsListMap.put(COMPONENT_INSTANCE_ID, propInputsList);
+        ComponentInstInputsMap componentInstInputsMap = new ComponentInstInputsMap();
+        componentInstInputsMap.setComponentInstanceInputsMap(propInputsListMap);
+        componentInstListInput.setComponentInstInputsMap(componentInstInputsMap);
+
+        return componentInstListInput;
+    }
+
+    @Test
+    public void test_createListInput_success() throws Exception {
+        ComponentInstListInput requestBodyObj = setUpCreateListInputParams();
+        Entity<ComponentInstListInput> entity = Entity.entity(requestBodyObj, MediaType.APPLICATION_JSON);
+
+        // for parseToComponentInstListInput
+        when(componentsUtils.convertJsonToObjectUsingObjectMapper(any(), any(), eq(ComponentInstListInput.class),
+                eq(AuditingActionEnum.CREATE_RESOURCE), eq(ComponentTypeEnum.SERVICE)))
+                .thenReturn(Either.left(requestBodyObj));
+
+        when(inputsBusinessLogic.createListInput(eq(USER_ID), eq(RESOURCE_ID), eq(ComponentTypeEnum.SERVICE),
+                any(), eq(true), eq(false)))
+                .thenReturn(Either.left(Collections.emptyList()));
+        when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode()));
+
+        Response response = buildCreateListInputCall().post(entity);
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200.getStatusCode());
+        verify(inputsBusinessLogic, times(1)).createListInput(USER_ID, RESOURCE_ID,
+                ComponentTypeEnum.SERVICE, requestBodyObj, true, false);
+    }
+
+    @Test
+    public void test_createListInput_fail_parse() throws Exception {
+        ComponentInstListInput requestBodyObj = setUpCreateListInputParams();
+        Entity<ComponentInstListInput> entity = Entity.entity(requestBodyObj, MediaType.APPLICATION_JSON);
+
+        // for parseToComponentInstListInput
+        ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
+        when(componentsUtils.convertJsonToObjectUsingObjectMapper(any(), userCaptor.capture(), eq(ComponentInstListInput.class),
+                eq(AuditingActionEnum.CREATE_RESOURCE), eq(ComponentTypeEnum.SERVICE)))
+                .thenReturn(Either.right(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode())));
+
+        when(inputsBusinessLogic.createListInput(eq(USER_ID), eq(RESOURCE_ID), eq(ComponentTypeEnum.SERVICE),
+                any(), eq(true), eq(false)))
+                .thenReturn(Either.left(Collections.emptyList()));
+
+        Response response = buildCreateListInputCall().post(entity);
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode());
+        verify(componentsUtils, times(1))
+                .convertJsonToObjectUsingObjectMapper(any(), any(), eq(ComponentInstListInput.class),
+                eq(AuditingActionEnum.CREATE_RESOURCE), eq(ComponentTypeEnum.SERVICE));
+        assertThat(userCaptor.getValue().getUserId()).isEqualTo(USER_ID);
+        verify(inputsBusinessLogic, never()).createListInput(USER_ID, RESOURCE_ID,
+                ComponentTypeEnum.SERVICE, requestBodyObj, true, false);
+    }
+
+
+    @Test
+    public void test_createListInput_fail_createInput() throws Exception {
+        ComponentInstListInput requestBodyObj = setUpCreateListInputParams();
+        Entity<ComponentInstListInput> entity = Entity.entity(requestBodyObj, MediaType.APPLICATION_JSON);
+
+        // for parseToComponentInstListInput
+        ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
+        when(componentsUtils.convertJsonToObjectUsingObjectMapper(any(), userCaptor.capture(), eq(ComponentInstListInput.class),
+                eq(AuditingActionEnum.CREATE_RESOURCE), eq(ComponentTypeEnum.SERVICE)))
+                .thenReturn(Either.left(requestBodyObj));
+
+        when(inputsBusinessLogic.createListInput(eq(USER_ID), eq(RESOURCE_ID), eq(ComponentTypeEnum.SERVICE),
+                any(), eq(true), eq(false)))
+                .thenReturn(Either.right(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode())));
+
+        Response response = buildCreateListInputCall().post(entity);
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode());
+        verify(inputsBusinessLogic, times(1))
+                .createListInput(eq(USER_ID), eq(RESOURCE_ID), eq(ComponentTypeEnum.SERVICE),
+                        any(), eq(true), eq(false));
+    }
+
+
+    @Test
+    public void test_createListInput_fail_exception() throws Exception {
+        ComponentInstListInput requestBodyObj = setUpCreateListInputParams();
+        Entity<ComponentInstListInput> entity = Entity.entity(requestBodyObj, MediaType.APPLICATION_JSON);
+
+        when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode()));
+
+        Response response = buildCreateListInputCall().post(entity);
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode());
+    }
+
+    @Test
+    public void test_getDataType_success() throws Exception {
+        when(dataTypeBusinessLogic.getPrivateDataType(eq(RESOURCE_ID),eq(LISTINPUT_SCHEMA_TYPE))).thenReturn(Either.left(new DataTypeDefinition()));
+
+        ResponseFormat responseFormat = new ResponseFormat();
+        responseFormat.setStatus(HttpStatus.OK_200.getStatusCode());
+        when(componentsUtils.getResponseFormat(eq(ActionStatus.OK))).thenReturn(responseFormat);
+
+        Response response = buildGetDataTypeCall().get();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200.getStatusCode());
+    }
+
+    @Test
+    public void test_getDataType_fail() throws Exception {
+        when(dataTypeBusinessLogic.getPrivateDataType(eq(RESOURCE_ID),eq(LISTINPUT_SCHEMA_TYPE))).thenReturn(Either.right(StorageOperationStatus.BAD_REQUEST));
+
+        ResponseFormat responseFormat = new ResponseFormat();
+        responseFormat.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode());
+        when(componentsUtils.convertFromStorageResponse(eq(StorageOperationStatus.BAD_REQUEST))).thenReturn(ActionStatus.GENERAL_ERROR);
+        when(componentsUtils.getResponseFormat(eq(ActionStatus.GENERAL_ERROR))).thenReturn(responseFormat);
+
+        Response response = buildGetDataTypeCall().get();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode());
+    }
+
+    @Test
+    public void test_getDataType_fail_exception() throws Exception {
+        when(dataTypeBusinessLogic.getPrivateDataType(eq(RESOURCE_ID),eq(LISTINPUT_SCHEMA_TYPE))).thenReturn(Either.right(StorageOperationStatus.BAD_REQUEST));
+        when(componentsUtils.getResponseFormat(eq(ActionStatus.GENERAL_ERROR))).thenReturn(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode()));
+
+        Response response = buildGetDataTypeCall().get();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode());
+    }
+
+    @Test
+    public void test_getDataTypes_success() throws Exception {
+        when(dataTypeBusinessLogic.getPrivateDataTypes(eq(RESOURCE_ID))).thenReturn(Either.left(Collections.emptyList()));
+
+        ResponseFormat responseFormat = new ResponseFormat();
+        responseFormat.setStatus(HttpStatus.OK_200.getStatusCode());
+        when(componentsUtils.getResponseFormat(eq(ActionStatus.OK))).thenReturn(responseFormat);
+
+        Response response = buildGetDataTypesCall().get();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200.getStatusCode());
+    }
+
+    @Test
+    public void test_getDataTypes_fail() throws Exception {
+        when(dataTypeBusinessLogic.getPrivateDataTypes(eq(RESOURCE_ID))).thenReturn(Either.right(StorageOperationStatus.BAD_REQUEST));
+
+        ResponseFormat responseFormat = new ResponseFormat();
+        responseFormat.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode());
+        when(componentsUtils.convertFromStorageResponse(eq(StorageOperationStatus.BAD_REQUEST))).thenReturn(ActionStatus.GENERAL_ERROR);
+        when(componentsUtils.getResponseFormat(eq(ActionStatus.GENERAL_ERROR))).thenReturn(responseFormat);
+
+        Response response = buildGetDataTypesCall().get();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode());
+    }
+
+    @Test
+    public void test_getDataTypes_fail_exception() throws Exception {
+        when(dataTypeBusinessLogic.getPrivateDataType(eq(RESOURCE_ID),eq(LISTINPUT_SCHEMA_TYPE))).thenReturn(Either.right(StorageOperationStatus.BAD_REQUEST));
+        when(componentsUtils.getResponseFormat(eq(ActionStatus.GENERAL_ERROR))).thenReturn(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode()));
+
+        Response response = buildGetDataTypesCall().get();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode());
+    }
+
+
+    @Test
+    public void test_deleteDataType_success() throws Exception {
+        when(dataTypeBusinessLogic.deletePrivateDataType(RESOURCE_ID, LISTINPUT_SCHEMA_TYPE)).thenReturn(Either.left(new DataTypeDefinition()));
+
+        when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode()));
+
+        Response response = buildGetDataTypeCall().delete();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200.getStatusCode());
+    }
+
+    @Test
+    public void test_deleteDataType_failure_exception() throws Exception {
+        when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode()));
+        when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(new ResponseFormat(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode()));
+        Response response = buildGetDataTypeCall().delete();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500.getStatusCode());
+        verify(componentsUtils, never()).getResponseFormat(ActionStatus.OK);
+    }
+
+    @Test
+    public void test_deleteDataType_failure_notFound() throws Exception {
+        when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode()));
+        when(dataTypeBusinessLogic.deletePrivateDataType(RESOURCE_ID, LISTINPUT_SCHEMA_TYPE)).thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        when(componentsUtils.convertFromStorageResponse(StorageOperationStatus.NOT_FOUND)).thenReturn(ActionStatus.ARTIFACT_NOT_FOUND);
+        when(componentsUtils.getResponseFormat(ActionStatus.ARTIFACT_NOT_FOUND)).thenReturn(new ResponseFormat(HttpStatus.NOT_FOUND_404.getStatusCode()));
+        Response response = buildGetDataTypeCall().delete();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND_404.getStatusCode());
+        verify(componentsUtils, never()).getResponseFormat(ActionStatus.OK);
+    }
+
+    @Test
+    public void test_deleteInput_success() throws Exception {
+        when(inputsBusinessLogic.deleteInput(RESOURCE_ID, USER_ID, LISTINPUT_NAME))
+                .thenReturn(Either.left(new InputDefinition()));
+        when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode()));
+
+        // invoke delete call
+        Response response = target("/v1/catalog/services/{id}/delete/{inputId}/input")
+                .resolveTemplate("id", RESOURCE_ID)
+                .resolveTemplate("inputId", LISTINPUT_NAME)
+                .request(MediaType.APPLICATION_JSON)
+                .header(Constants.USER_ID_HEADER, USER_ID)
+                .delete();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK_200.getStatusCode());
+        verify(inputsBusinessLogic, times(1)).deleteInput(RESOURCE_ID, USER_ID, LISTINPUT_NAME);
+    }
+
+
+    @Test
+    public void test_deleteInput_failure_deleteInput() throws Exception {
+        when(inputsBusinessLogic.deleteInput(RESOURCE_ID, USER_ID, LISTINPUT_NAME))
+                .thenReturn(Either.right(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode())));
+        when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode()));
+
+        // invoke delete call
+        Response response = target("/v1/catalog/services/{id}/delete/{inputId}/input")
+                .resolveTemplate("id", RESOURCE_ID)
+                .resolveTemplate("inputId", LISTINPUT_NAME)
+                .request(MediaType.APPLICATION_JSON)
+                .header(Constants.USER_ID_HEADER, USER_ID)
+                .delete();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode());
+        verify(componentsUtils, never()).getResponseFormat(ActionStatus.OK);
+    }
+
+
+    @Test
+    public void test_deleteInput_failure_exception() throws Exception {
+        when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(new ResponseFormat(HttpStatus.OK_200.getStatusCode()));
+        when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(new ResponseFormat(HttpStatus.BAD_REQUEST_400.getStatusCode()));
+
+        // invoke delete call
+        Response response = target("/v1/catalog/services/{id}/delete/{inputId}/input")
+                .resolveTemplate("id", RESOURCE_ID)
+                .resolveTemplate("inputId", LISTINPUT_NAME)
+                .request(MediaType.APPLICATION_JSON)
+                .header(Constants.USER_ID_HEADER, USER_ID)
+                .delete();
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST_400.getStatusCode());
+        verify(componentsUtils, never()).getResponseFormat(ActionStatus.OK);
+    }
+
+
+    private Invocation.Builder buildCreateListInputCall() {
+        return target("/v1/catalog/services/{id}/create/listInput")
+                .resolveTemplate("id", RESOURCE_ID)
+                .request(MediaType.APPLICATION_JSON)
+                .header(Constants.USER_ID_HEADER, USER_ID);
+    }
+
+    private Invocation.Builder buildGetDataTypeCall() {
+        return target("/v1/catalog/services/{id}/dataType/{dataTypeName}")
+                .resolveTemplate("id", RESOURCE_ID)
+                .resolveTemplate("dataTypeName", LISTINPUT_SCHEMA_TYPE)
+                .request(MediaType.APPLICATION_JSON)
+                .header(Constants.USER_ID_HEADER, USER_ID);
+    }
+
+    private Invocation.Builder buildGetDataTypesCall() {
+        return target("/v1/catalog/services/{id}/dataTypes")
+                .resolveTemplate("id", RESOURCE_ID)
+                .request(MediaType.APPLICATION_JSON)
+                .header(Constants.USER_ID_HEADER, USER_ID);
+    }
 
-public class InputsServletTest {
-
-       private InputsServlet createTestSubject() {
-               return new InputsServlet();
-       }
-
-       
-       @Test
-       public void testGetComponentInputs() throws Exception {
-               InputsServlet testSubject;
-               String componentType = "";
-               String componentId = "";
-               HttpServletRequest request = null;
-               String fromName = "";
-               int amount = 0;
-               String userId = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testUpdateComponentInputs() throws Exception {
-               InputsServlet testSubject;
-               String containerComponentType = "";
-               String componentId = "";
-               String data = "";
-               HttpServletRequest request = null;
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testGetComponentInstanceInputs() throws Exception {
-               InputsServlet testSubject;
-               String componentType = "";
-               String componentId = "";
-               String instanceId = "";
-               String originComonentUid = "";
-               HttpServletRequest request = null;
-               String userId = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testGetInputPropertiesForComponentInstance() throws Exception {
-               InputsServlet testSubject;
-               String componentType = "";
-               String componentId = "";
-               String instanceId = "";
-               String inputId = "";
-               HttpServletRequest request = null;
-               String userId = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testGetInputsForComponentInput() throws Exception {
-               InputsServlet testSubject;
-               String componentType = "";
-               String componentId = "";
-               String inputId = "";
-               HttpServletRequest request = null;
-               String userId = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testGetInputsAndPropertiesForComponentInput() throws Exception {
-               InputsServlet testSubject;
-               String componentType = "";
-               String componentId = "";
-               String inputId = "";
-               HttpServletRequest request = null;
-               String userId = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testParseToComponentInstanceMap() throws Exception {
-               InputsServlet testSubject;
-               String serviceJson = "";
-               User user = null;
-               Either<ComponentInstInputsMap, ResponseFormat> result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testCreateMultipleInputs() throws Exception {
-               InputsServlet testSubject;
-               String componentType = "";
-               String componentId = "";
-               HttpServletRequest request = null;
-               String userId = "";
-               String componentInstInputsMapObj = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testDeleteInput() throws Exception {
-               InputsServlet testSubject;
-               String componentType = "";
-               String componentId = "";
-               String inputId = "";
-               HttpServletRequest request = null;
-               String userId = "";
-               String componentInstInputsMapObj = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testGetInputBL() throws Exception {
-               InputsServlet testSubject;
-               ServletContext context = null;
-               InputsBusinessLogic result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-}
\ No newline at end of file
+}
index d46d234..78ed40a 100644 (file)
@@ -1,12 +1,14 @@
 package org.openecomp.sdc.be.tosca;
 
+import fj.data.Either;
 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 java.util.function.Supplier;
-
+import java.util.stream.Collectors;
+import mockit.Deencapsulation;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Triple;
 import org.junit.Before;
@@ -17,10 +19,12 @@ import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.openecomp.sdc.be.components.BeConfDependentTest;
+import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder;
 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathElementDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
@@ -56,9 +60,6 @@ import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
 import org.openecomp.sdc.be.tosca.model.ToscaTemplate;
 import org.openecomp.sdc.be.tosca.model.ToscaTemplateRequirement;
 import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
-
-import fj.data.Either;
-import mockit.Deencapsulation;
 import org.openecomp.sdc.be.tosca.utils.InputConverter;
 
 public class ToscaExportHandlerTest extends BeConfDependentTest {
@@ -98,6 +99,20 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
                CategoryDefinition category = new CategoryDefinition();
                List<SubCategoryDefinition> subcategories = new ArrayList<>();
                SubCategoryDefinition subcategory = new SubCategoryDefinition();
+               List<DataTypeDefinition> dataTypes = new ArrayList<>();
+               DataTypeDefinition dataType = new DataTypeDefinition();
+               dataType.setName("dataTypeName");
+               dataType.setDerivedFromName("tosca.datatypes.Root");
+               PropertyDataDefinition propData = new PropertyDataDefinitionBuilder()
+                               .setName("property")
+                               .setType("type")
+                               .build();
+               List<PropertyDataDefinition> propDataList = Arrays.asList(propData);
+               dataType.setPropertiesData(propDataList);
+               List<PropertyDefinition> propList = propDataList.stream().map(PropertyDefinition::new)
+                               .collect(Collectors.toList());
+               dataType.setProperties(propList);
+               dataTypes.add(dataType);
 
                subcategory.setName("name");
                subcategories.add(subcategory);
@@ -110,6 +125,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
                resource.setVendorName("vendorName");
                resource.setVendorRelease("vendorRelease");
                resource.setResourceVendorModelNumber("resourceVendorModelNumber");
+               resource.setDataTypes(dataTypes);
 
                return resource;
        }
@@ -1193,4 +1209,4 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
                // default test
                result = Deencapsulation.invoke(testSubject, "convertCapabilities", component, nodeType, dataTypes);
        }
-}
\ No newline at end of file
+}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaDataTypeTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaDataTypeTest.java
new file mode 100644 (file)
index 0000000..94a7d05
--- /dev/null
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019 Fujitsu Limited. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.tosca.model;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ToscaDataTypeTest {
+    private static final String DERIVED_FROM = "tosca.datatypes.Root";
+    private static final String VERSION = "1.1";
+    private static final String DESCRIPTION = "data type description";
+    private static final String PROPERTY_NAME = "prop1";
+    private static final String METADATA_KEY = "foo";
+    private static final String METADATA_VALUE = "bar";
+
+    private ToscaDataType testSubject;
+
+    @Test
+    public void testToscaDataType() throws Exception {
+        testSubject = new ToscaDataType();
+        testSubject.setDerived_from(DERIVED_FROM);
+        testSubject.setVersion(VERSION);
+        testSubject.setDescription(DESCRIPTION);
+        Map<String, String> metadata = new HashMap<>();
+        metadata.put(METADATA_KEY, METADATA_VALUE);
+        testSubject.setMetadata(metadata);
+        Map<String, ToscaProperty> properties = new HashMap<>();
+        properties.put(PROPERTY_NAME, new ToscaProperty());
+        testSubject.setProperties(properties);
+
+        assertThat(testSubject.getDerived_from(), is(DERIVED_FROM));
+        assertThat(testSubject.getVersion(), is(VERSION));
+        assertThat(testSubject.getDescription(), is(DESCRIPTION));
+        assertThat(testSubject.getMetadata(), is(metadata));
+        assertThat(testSubject.getProperties(), is(properties));
+    }
+}
index 613c7ed..c250b4e 100644 (file)
@@ -1,10 +1,12 @@
 package org.openecomp.sdc.be.tosca.model;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.junit.Test;
 
+import static org.junit.Assert.*;
 
 public class ToscaTemplateTest {
 
@@ -122,9 +124,24 @@ public class ToscaTemplateTest {
                testSubject.setTopology_template(topology_template);
        }
 
-       
 
+       @Test
+       public void testGetSetData_types() throws Exception {
+               ToscaTemplate testSubject = createTestSubject();
+               Map<String, ToscaDataType> dataTypes = new HashMap<>();
+               dataTypes.put("datatype", new ToscaDataType());
+               testSubject.setData_types(dataTypes);
+               assertEquals(dataTypes, testSubject.getData_types());
+       }
 
-       
+
+       @Test
+       public void testGetSetInterface_types() throws Exception {
+               ToscaTemplate testSubject = createTestSubject();
+               Map<String, Object> interfaceTypes = new HashMap<>();
+               interfaceTypes.put("id", new Object());
+               testSubject.setInterface_types(interfaceTypes);
+               assertEquals(interfaceTypes, testSubject.getInterface_types());
+       }
 
 }
\ No newline at end of file
index 2c84f5a..9dc9c84 100644 (file)
@@ -65,7 +65,8 @@ public enum EdgeLabelEnum {
        INTERFACE,
        INTERFACE_OPERATION,
        INST_INTERFACES,
-       NODE_FILTER_TEMPLATE;
+       NODE_FILTER_TEMPLATE,
+       DATA_TYPES;
 
     /**
         * Returns EdgeLabelEnum according received name
index 288b1ba..053a690 100644 (file)
@@ -21,6 +21,7 @@
 package org.openecomp.sdc.be.dao.jsongraph.types;
 
 import org.openecomp.sdc.be.datatypes.elements.*;
+import org.openecomp.sdc.be.resources.data.DataTypeData;
 
 
 public enum VertexTypeEnum {
@@ -62,7 +63,8 @@ public enum VertexTypeEnum {
        INTERFACE                           ("interface",                               InterfaceDataDefinition.class),
        INTERFACE_OPERATION                     ("interfaceOperation",                  OperationDataDefinition.class),
        NODE_FILTER_TEMPLATE            ("NodeTemplateFilter",          CINodeFilterDataDefinition.class),
-       INST_INTERFACES             ("InstInterfaces",              MapInterfaceDataDefinition.class);
+       INST_INTERFACES             ("InstInterfaces",              MapInterfaceDataDefinition.class),
+       DATA_TYPES                                      ("data_types",                                  DataTypeDataDefinition.class);
 
        private String name;
        private Class classOfJson;
index 65ad149..b65997c 100644 (file)
@@ -51,6 +51,8 @@ import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum;
 import org.openecomp.sdc.common.api.ArtifactTypeEnum;
 
+import static java.util.stream.Collectors.toMap;
+
 public abstract class Component implements PropertiesOwner {
 
        private ComponentMetadataDefinition componentMetadataDefinition;
@@ -78,8 +80,17 @@ public abstract class Component implements PropertiesOwner {
        private Map<String, List<UploadNodeFilterInfo>> serviceFilters;
        protected List<PropertyDefinition> properties;
        private Map<String, InterfaceDefinition> interfaces;
+    private List<DataTypeDefinition> dataTypes;
+
+    public List<DataTypeDefinition> getDataTypes() {
+        return dataTypes;
+    }
+
+    public void setDataTypes(List<DataTypeDefinition> dataTypes) {
+        this.dataTypes = dataTypes;
+    }
 
-       public Map<String, InterfaceDefinition> getInterfaces() {
+    public Map<String, InterfaceDefinition> getInterfaces() {
                return interfaces;
        }
 
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstListInput.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstListInput.java
new file mode 100644 (file)
index 0000000..ee4bef2
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019 Fujitsu Limited. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.model;
+
+/**
+ * Represents a pair of a list of properties to be declared and a "list input" to be created.
+ * This class is used for passing parameters on creating a list input.
+ */
+public class ComponentInstListInput {
+    private ComponentInstInputsMap componentInstInputsMap;
+    private InputDefinition listInput;
+
+    /**
+     * Gets componentInstInputsMap which includes properties to be declared.
+     *
+     * @return componentInstInputsMap
+     */
+    public ComponentInstInputsMap getComponentInstInputsMap() {
+        return componentInstInputsMap;
+    }
+
+    /**
+     * Sets componentInstInputsMap.
+     *
+     * @param componentInstInputsMap
+     */
+    public void setComponentInstInputsMap(ComponentInstInputsMap componentInstInputsMap) {
+        this.componentInstInputsMap = componentInstInputsMap;
+    }
+
+    /**
+     * Gets the input to be created.
+     *
+     * @return the list input
+     */
+    public InputDefinition getListInput() {
+        return listInput;
+    }
+
+    /**
+     * Sets the input to be created.
+     *
+     * @param listInput
+     */
+    public void setListInput(InputDefinition listInput) {
+        this.listInput = listInput;
+    }
+}
index 05d9a57..3edb8de 100644 (file)
@@ -51,6 +51,7 @@ public class ComponentParametersView {
     private boolean ignorePolicies = false;
     private boolean ignoreNodeFilterRequirements = false;
     private boolean ignoreNodeFilter = false;
+    private boolean ignoreDataType = false;
 
     public ComponentParametersView() {
     }
@@ -154,6 +155,9 @@ public class ComponentParametersView {
                     this.setIgnoreComponentInstances(false);
                     this.setIgnoreComponentInstancesInterfaces(false);
                     break;
+                case DATA_TYPES:
+                    this.setIgnoreDataType(false);
+                    break;
                 default:
                     break;
             }
@@ -167,120 +171,114 @@ public class ComponentParametersView {
 
     public Component filter(Component component, ComponentTypeEnum componentType) {
 
-               if (ignoreUsers) {
-                       component.setCreatorUserId(null);
-                       component.setCreatorFullName(null);
-                       component.setLastUpdaterUserId(null);
-                       component.setLastUpdaterFullName(null);
-               }
-
-               if (ignoreGroups) {
-                       component.setGroups(null);
-               }
-
-               if (ignoreComponentInstances) {
-                       component.setComponentInstances(null);
-                       component.setComponentInstancesRelations(null);
-               }
-
-               if (ignoreComponentInstancesProperties) {
-                       component.setComponentInstancesProperties(null);
-               }
-
-    if (ignoreProperties && componentType == ComponentTypeEnum.RESOURCE) {
-      ((Resource) component).setProperties(null);
-    }
-
-               if (ignoreCapabilities) {
-                       component.setCapabilities(null);
-               }
-
-               if (ignoreRequirements) {
-                       component.setRequirements(null);
-               }
-
-               if (ignoreCategories) {
-                       component.setCategories(null);
-               }
-
-               if (ignoreAllVersions) {
-                       component.setAllVersions(null);
-               }
-    if (ignoreAdditionalInformation && componentType == ComponentTypeEnum.RESOURCE) {
-      ((Resource) component).setAdditionalInformation(null);
-    }
-
-               if (ignoreArtifacts) {
-                       component.setArtifacts(null);
-                       component.setSpecificComponetTypeArtifacts(null);
-                       component.setDeploymentArtifacts(null);
-                       component.setToscaArtifacts(null);
-               }
-    if (ignoreNodeFilterRequirements){
-      component.setNodeFilterComponents(null);
-    }
-    if (ignoreInterfaces && ignoreInterfaceInstances &&
-        componentType == ComponentTypeEnum.RESOURCE) {
-        component.setInterfaces(null);
-    }
-    if (ignoreDerivedFrom && componentType == ComponentTypeEnum.RESOURCE) {
-      ((Resource) component).setDerivedFrom(null);
-    }
-    if (ignoreAttributesFrom && componentType == ComponentTypeEnum.RESOURCE) {
-      ((Resource) component).setAttributes(null);
-    }
-               if (ignoreComponentInstancesAttributesFrom) {
-                       component.setComponentInstancesAttributes(null);
-               }
-               if (ignoreInputs) {
-                       component.setInputs(null);
-               }
-               if (ignoreComponentInstancesInputs) {
-                       component.setComponentInstancesInputs(null);
-               }
-    if (ignoreServicePath && componentType == ComponentTypeEnum.SERVICE) {
-      ((Service) component).setForwardingPaths(null);
-    }
-    if (ignoreNodeFilter){
-      component.setNodeFilterComponents(null);
-    }
-    return component;
-
-       }
-
-       public boolean isIgnoreNodeFilterRequirements() {
-               return ignoreNodeFilterRequirements;
-       }
-
-       public void setIgnoreNodeFilterRequirements(boolean ignoreNodeFilter) {
-               this.ignoreNodeFilterRequirements = ignoreNodeFilter;
-       }
-
-       public void disableAll() {
-               ignoreUsers = true;
-               ignoreGroups = true;
-    ignorePolicies = true;
-               ignoreComponentInstances = true;
-               ignoreComponentInstancesProperties = true;
-               ignoreProperties = true;
-               ignoreCapabilities = true;
-               ignoreRequirements = true;
-               ignoreCategories = true;
-               ignoreAllVersions = true;
-               ignoreAdditionalInformation = true;
-               ignoreArtifacts = true;
-               ignoreInterfaces = true;
-               ignoreInterfaceInstances = true;
-               ignoreDerivedFrom = true;
-               ignoreAttributesFrom = true;
-               ignoreInputs = true;
-               ignoreComponentInstancesAttributesFrom = true;
-               ignoreComponentInstancesInputs = true;
-               ignoreCapabiltyProperties = true;
-               ignoreServicePath = true;
-               ignoreNodeFilterRequirements = true;
+        if (ignoreUsers) {
+            component.setCreatorUserId(null);
+            component.setCreatorFullName(null);
+            component.setLastUpdaterUserId(null);
+            component.setLastUpdaterFullName(null);
+        }
+        if (ignoreGroups) {
+            component.setGroups(null);
+        }
+        if (ignoreComponentInstances) {
+            component.setComponentInstances(null);
+            component.setComponentInstancesRelations(null);
+        }
+        if (ignoreComponentInstancesProperties) {
+            component.setComponentInstancesProperties(null);
+        }
+        if (ignoreProperties && componentType == ComponentTypeEnum.RESOURCE) {
+            ((Resource) component).setProperties(null);
+        }
+        if (ignoreCapabilities) {
+            component.setCapabilities(null);
+        }
+        if (ignoreRequirements) {
+            component.setRequirements(null);
+        }
+        if (ignoreCategories) {
+            component.setCategories(null);
+        }
+        if (ignoreAllVersions) {
+            component.setAllVersions(null);
+        }
+        if (ignoreAdditionalInformation && componentType == ComponentTypeEnum.RESOURCE) {
+            ((Resource) component).setAdditionalInformation(null);
+        }
+        if (ignoreArtifacts) {
+            component.setArtifacts(null);
+            component.setSpecificComponetTypeArtifacts(null);
+            component.setDeploymentArtifacts(null);
+            component.setToscaArtifacts(null);
+        }
+        if (ignoreNodeFilterRequirements){
+          component.setNodeFilterComponents(null);
+        }
+        if (ignoreInterfaces && ignoreInterfaceInstances &&
+            componentType == ComponentTypeEnum.RESOURCE) {
+            component.setInterfaces(null);
+        }
+        if (ignoreDerivedFrom && componentType == ComponentTypeEnum.RESOURCE) {
+            ((Resource) component).setDerivedFrom(null);
+        }
+        if (ignoreAttributesFrom && componentType == ComponentTypeEnum.RESOURCE) {
+            ((Resource) component).setAttributes(null);
+        }
+        if (ignoreComponentInstancesAttributesFrom) {
+            component.setComponentInstancesAttributes(null);
+        }
+        if (ignoreInputs) {
+            component.setInputs(null);
+        }
+        if (ignoreComponentInstancesInputs) {
+            component.setComponentInstancesInputs(null);
+        }
+        if (ignoreServicePath && componentType == ComponentTypeEnum.SERVICE) {
+            ((Service) component).setForwardingPaths(null);
+        }
+        if (ignoreNodeFilter){
+            component.setNodeFilterComponents(null);
+        }
+        if (ignoreDataType) {
+            component.setDataTypes(null);
+        }
+        return component;
+    }
+
+    public boolean isIgnoreNodeFilterRequirements() {
+        return ignoreNodeFilterRequirements;
+    }
+
+    public void setIgnoreNodeFilterRequirements(boolean ignoreNodeFilter) {
+        this.ignoreNodeFilterRequirements = ignoreNodeFilter;
+    }
+
+    public void disableAll() {
+        ignoreUsers = true;
+        ignoreGroups = true;
+        ignorePolicies = true;
+        ignoreComponentInstances = true;
+        ignoreComponentInstancesProperties = true;
+        ignoreProperties = true;
+        ignoreCapabilities = true;
+        ignoreRequirements = true;
+        ignoreCategories = true;
+        ignoreAllVersions = true;
+        ignoreAdditionalInformation = true;
+        ignoreArtifacts = true;
+        ignoreInterfaces = true;
+        ignoreInterfaceInstances = true;
+        ignoreDerivedFrom = true;
+        ignoreAttributesFrom = true;
+        ignoreInputs = true;
+        ignoreComponentInstancesAttributesFrom = true;
+        ignoreComponentInstancesInputs = true;
+        ignoreCapabiltyProperties = true;
+        ignoreServicePath = true;
+        ignoreNodeFilterRequirements = true;
         ignoreNodeFilter = true;
-       }
+        ignoreDataType = true;
+    }
 
     public boolean isIgnoreGroups() {
         return ignoreGroups;
@@ -462,6 +460,14 @@ public class ComponentParametersView {
         this.ignoreNodeFilter = ignoreNodeFilter;
     }
 
+    public boolean isIgnoreDataType() {
+        return ignoreDataType;
+    }
+
+    public void setIgnoreDataType(boolean ignoreDataType) {
+        this.ignoreDataType = ignoreDataType;
+    }
+
     public JsonParseFlagEnum detectParseFlag() {
         JsonParseFlagEnum parseFlag;
         if (isIgnoreComponentInstances()) {
index 44c6b7b..4dc952d 100644 (file)
 package org.openecomp.sdc.be.model;
 
 import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 public class DataTypeDefinition extends DataTypeDataDefinition {
 
index 14b7a2f..8c0253a 100644 (file)
@@ -25,6 +25,7 @@ import org.openecomp.sdc.be.datatypes.elements.*;
 import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
 import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.MapInterfaceInstanceDataDefinition;
 import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum;
 
@@ -57,6 +58,7 @@ public class TopologyTemplate extends ToscaElement{
     private Map<String, InterfaceDataDefinition> interfaces;
     private Map<String, MapInterfaceInstanceDataDefinition> instInterfaces;
     private Map<String, MapInterfaceDataDefinition> componentInstInterfaces;
+    private Map<String, DataTypeDataDefinition> dataTypes;
 
     private Map<String, CINodeFilterDataDefinition> nodeFilterComponents;
     //Component Instances External References (instanceId -> ExternalRefsMap)
@@ -239,6 +241,22 @@ public class TopologyTemplate extends ToscaElement{
         this.nodeFilterComponents = nodeFilters;
     }
 
+    /**
+     * Gets data types.
+     * @return Current data types.
+     */
+    public Map<String, DataTypeDataDefinition> getDataTypes() {
+        return dataTypes;
+    }
+
+    /**
+     * Sets data types.
+     * @param dataTypes New data types.
+     */
+    public void setDataTypes(Map<String, DataTypeDataDefinition> dataTypes) {
+        this.dataTypes = dataTypes;
+    }
+
       /**
      * Adds component instance to composition of topology template
      * Note that component instance will be overrided in case if the topology template already contains a component instance with the same name
index 4175773..b0bfc15 100644 (file)
@@ -22,19 +22,8 @@ package org.openecomp.sdc.be.model.jsontitan.operations;
 
 import com.google.gson.reflect.TypeToken;
 import fj.data.Either;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
 import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
 import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
@@ -47,6 +36,7 @@ import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
@@ -72,7 +62,6 @@ 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.GroupDefinition;
-
 import org.openecomp.sdc.be.model.PolicyDefinition;
 import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.category.CategoryDefinition;
@@ -92,6 +81,19 @@ import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.ValidationUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 @org.springframework.stereotype.Component("topology-template-operation")
 public class TopologyTemplateOperation extends ToscaElementOperation {
 
@@ -777,9 +779,29 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
                 return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(storageStatus));
             }
         }
+
+        if (!componentParametersView.isIgnoreDataType()) {
+            TitanOperationStatus storageStatus = setDataTypesFromGraph(componentV, toscaElement);
+            if (storageStatus != TitanOperationStatus.OK) {
+                return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(storageStatus));
+            }
+        }
+
         return Either.left(toscaElement);
     }
 
+    private TitanOperationStatus setDataTypesFromGraph(GraphVertex componentV, TopologyTemplate toscaElement) {
+        Either<Map<String, DataTypeDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.DATA_TYPES);
+        if (result.isLeft()) {
+            toscaElement.setDataTypes(result.left().value());
+        } else {
+            if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
+                return result.right().value();
+            }
+        }
+        return TitanOperationStatus.OK;
+    }
+
     private TitanOperationStatus setPoliciesFromGraph(GraphVertex componentV, TopologyTemplate toscaElement) {
         Either<Map<String, PolicyDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.POLICIES);
         if (result.isLeft()) {
index 10dd919..8456486 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.openecomp.sdc.be.model.jsontitan.operations;
 
+import com.datastax.driver.core.DataType;
 import fj.data.Either;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
@@ -46,6 +47,7 @@ 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.UniqueIdBuilder;
 import org.openecomp.sdc.be.resources.data.ComponentMetadataData;
+import org.openecomp.sdc.be.resources.data.DataTypeData;
 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
 import org.openecomp.sdc.common.log.wrappers.Logger;
@@ -171,6 +173,7 @@ public class ToscaOperationFacade {
         VertexTypeEnum label = componentV.getLabel();
 
         ToscaElementOperation toscaOperation = getToscaElementOperation(componentV);
+        log.debug("getToscaElementByOperation: toscaOperation={}", toscaOperation.getClass());
         Either<ToscaElement, StorageOperationStatus> toscaElement;
         String componentId = componentV.getUniqueId();
         if (toscaOperation != null) {
@@ -971,7 +974,74 @@ public class ToscaOperationFacade {
 
     }
 
-       public Either<List<InputDefinition>, StorageOperationStatus> getComponentInputs(String componentId) {
+    /**
+     * Add data types into a Component.
+     *
+     * @param dataTypes   datatypes to be added. the key should be each name of data type.
+     * @param componentId unique ID of Component.
+     * @return list of data types.
+     */
+    public Either<List<DataTypeDefinition>, StorageOperationStatus> addDataTypesToComponent(Map<String, DataTypeDefinition> dataTypes, String componentId) {
+
+        log.trace("#addDataTypesToComponent - enter, componentId={}", componentId);
+
+        /* get component vertex */
+        Either<GraphVertex, TitanOperationStatus> getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse);
+        if (getVertexEither.isRight()) {
+            /* not found / error */
+            log.debug(COULDNT_FETCH_COMPONENT_WITH_AND_UNIQUE_ID_ERROR, componentId, getVertexEither.right().value());
+            return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value()));
+        }
+        GraphVertex vertex = getVertexEither.left().value();
+        log.trace("#addDataTypesToComponent - get vertex ok");
+
+        // convert DataTypeDefinition to DataTypeDataDefinition
+        Map<String, DataTypeDataDefinition> dataTypeDataMap = dataTypes.entrySet().stream()
+                .collect(Collectors.toMap(Map.Entry::getKey, e -> convertDataTypeToDataTypeData(e.getValue())));
+
+        // add datatype(s) to the Component.
+        // if child vertex does not exist, it will be created.
+        StorageOperationStatus status = topologyTemplateOperation.addToscaDataToToscaElement(vertex,
+                EdgeLabelEnum.DATA_TYPES, VertexTypeEnum.DATA_TYPES, dataTypeDataMap, JsonPresentationFields.NAME);
+
+        if (StorageOperationStatus.OK == status) {
+            log.debug(COMPONENT_CREATED_SUCCESSFULLY);
+            List<DataTypeDefinition> inputsResList = null;
+            if (!dataTypes.isEmpty()) {
+                inputsResList = new ArrayList<>(dataTypes.values());
+            }
+            return Either.left(inputsResList);
+        }
+
+        log.trace("#addDataTypesToComponent - leave");
+        return Either.right(status);
+    }
+
+    private DataTypeDataDefinition convertDataTypeToDataTypeData(DataTypeDefinition dataType) {
+        DataTypeDataDefinition dataTypeData = new DataTypeDataDefinition(dataType);
+        if (CollectionUtils.isNotEmpty(dataType.getProperties())) {
+            List<PropertyDataDefinition> propertyDataList = dataType.getProperties().stream()
+                    .map(PropertyDataDefinition::new).collect(Collectors.toList());
+            dataTypeData.setPropertiesData(propertyDataList);
+        }
+
+        // if "derivedFrom" data_type exists, copy the name to "derivedFromName"
+        if (dataType.getDerivedFrom() != null && StringUtils.isNotEmpty(dataType.getDerivedFrom().getName())) {
+            // if names are different, log it
+            if (!StringUtils.equals(dataTypeData.getDerivedFromName(), dataType.getDerivedFrom().getName())) {
+                log.debug("#convertDataTypeToDataTypeData - derivedFromName(={}) overwritten by derivedFrom.name(={})",
+                        dataType.getDerivedFromName(), dataType.getDerivedFrom().getName());
+            }
+            dataTypeData.setDerivedFromName(dataType.getDerivedFrom().getName());
+        }
+
+        // supply "name" field to toscaPresentationValue in each datatype object for DAO operations
+        dataTypeData.setToscaPresentationValue(JsonPresentationFields.NAME, dataType.getName());
+        return dataTypeData;
+    }
+
+
+    public Either<List<InputDefinition>, StorageOperationStatus> getComponentInputs(String componentId) {
 
                Either<GraphVertex, TitanOperationStatus> getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse);
                if (getVertexEither.isRight()) {
@@ -2068,6 +2138,16 @@ public class ToscaOperationFacade {
         return getToscaElementOperation(resource).deleteToscaDataElement(resource.getUniqueId(), EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, inputName, JsonPresentationFields.NAME);
     }
 
+    /**
+     * Deletes a data type from a component.
+     * @param component the container which has the data type
+     * @param dataTypeName the data type name to be deleted
+     * @return Operation result.
+     */
+    public StorageOperationStatus deleteDataTypeOfComponent(Component component, String dataTypeName) {
+        return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.DATA_TYPES, VertexTypeEnum.DATA_TYPES, dataTypeName, JsonPresentationFields.NAME);
+    }
+
        public Either<PropertyDefinition, StorageOperationStatus> updatePropertyOfComponent(Component component,
                                                                                                                                                                                PropertyDefinition newPropertyDefinition) {
 
index 808fdbd..cfd00a5 100644 (file)
@@ -23,9 +23,11 @@ package org.openecomp.sdc.be.model.jsontitan.utils;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.ListUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
 import org.openecomp.sdc.be.datatypes.elements.*;
@@ -152,6 +154,8 @@ public class ModelConverter {
 
         convertServiceInterfaces(topologyTemplate, service);
 
+        convertDataTypes(topologyTemplate, service);
+
         convertNodeFiltersComponents(topologyTemplate, service);
         setCapabilitiesToComponent(topologyTemplate, service);
         setRequirementsToComponent(topologyTemplate, service);
@@ -205,6 +209,7 @@ public class ModelConverter {
             convertProperties(topologyTemplate, resource);
             setCapabilitiesToComponent(topologyTemplate, resource);
             setRequirementsToComponent(topologyTemplate, resource);
+            convertDataTypes(topologyTemplate, resource);
         }
         convertArtifacts(toscaElement, resource);
         convertAdditionalInformation(toscaElement, resource);
@@ -1106,6 +1111,26 @@ public class ModelConverter {
                }
        }
 
+    private static void convertDataTypes(TopologyTemplate topologyTemplate, Component component) {
+        Map<String, DataTypeDataDefinition> dataTypeDataMap = topologyTemplate.getDataTypes();
+        if (MapUtils.isNotEmpty(dataTypeDataMap)) {
+            List<DataTypeDefinition> dataTypeMap = dataTypeDataMap.values().stream().map(e -> {
+                DataTypeDefinition dataType = new DataTypeDefinition(e);
+
+                if(CollectionUtils.isNotEmpty(e.getPropertiesData())) {
+                    log.debug("#convertDataTypes - propertiesData is not null. {}",
+                            ReflectionToStringBuilder.toString(e.getPropertiesData()));
+                    dataType.setProperties(e.getPropertiesData().stream()
+                            .map(PropertyDefinition::new).collect(Collectors.toList()));
+                } else {
+                    log.debug("#convertDataTypes - propertiesData is null. ignore.");
+                }
+                return dataType;
+            }).collect(Collectors.toList());
+            component.setDataTypes(dataTypeMap);
+        }
+    }
+
 
     private static void convertCommonToscaData(Component component, ToscaElement toscaElement) {
         toscaElement.setUUID(component.getUUID());
@@ -1168,6 +1193,7 @@ public class ModelConverter {
 
 
 
+
     private static void setComponentInstancesToComponent(TopologyTemplate topologyTemplate, Component component) {
 
         List<ComponentInstance> componentInstances = new ArrayList<>();
index d84b821..7f8ea51 100644 (file)
@@ -7,6 +7,8 @@ import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 
 import java.util.LinkedList;
 
+import static org.junit.Assert.assertSame;
+
 public class ComponentParametersViewTest {
 
        private ComponentParametersView createTestSubject() {
@@ -448,6 +450,26 @@ public class ComponentParametersViewTest {
        }
 
        
+       @Test
+       public void testIsIgnoreNodeFilterWithTrue() throws Exception {
+               ComponentParametersView testSubject;
+
+               testSubject = createTestSubject();
+               testSubject.setIgnoreNodeFilter(true);
+               assertSame(testSubject.isIgnoreNodeFilter(), true);
+       }
+
+       
+       @Test
+       public void testIsIgnoreNodeFilterWithFalse() throws Exception {
+               ComponentParametersView testSubject;
+
+               testSubject = createTestSubject();
+               testSubject.setIgnoreNodeFilter(false);
+               assertSame(testSubject.isIgnoreNodeFilter(), false);
+       }
+
+
        @Test
        public void testDetectParseFlag() throws Exception {
                ComponentParametersView testSubject;
@@ -457,4 +479,4 @@ public class ComponentParametersViewTest {
                testSubject = createTestSubject();
                result = testSubject.detectParseFlag();
        }
-}
\ No newline at end of file
+}
index 72ca0c0..c13ddd3 100644 (file)
@@ -5,6 +5,7 @@ import java.util.Map;
 import org.junit.Test;
 import org.openecomp.sdc.be.datatypes.elements.*;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
 
 
 public class TopologyTemplateTest {
@@ -366,9 +367,28 @@ public class TopologyTemplateTest {
        }
 
        
+       @Test
+       public void testGetDataTypes() throws Exception {
+               TopologyTemplate testSubject;
+               Map<String, DataTypeDataDefinition> result;
 
+               // default test
+               testSubject = createTestSubject();
+               result = testSubject.getDataTypes();
+       }
 
        
+       @Test
+       public void testSetDataTypes() throws Exception {
+               TopologyTemplate testSubject;
+               Map<String, DataTypeDataDefinition> dataTypes = null;
+
+               // default test
+               testSubject = createTestSubject();
+               testSubject.setDataTypes(dataTypes);
+       }
+
+
        @Test
        public void testGetComponentInstances() throws Exception {
                TopologyTemplate testSubject;
index 8bb252e..4ace70b 100644 (file)
@@ -26,11 +26,10 @@ import org.openecomp.sdc.be.model.PolicyDefinition;
 import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
+import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.*;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertEquals;
@@ -106,6 +105,23 @@ public class TopologyTemplateOperationTest {
         assertEquals(StorageOperationStatus.OK, result);
     }
 
+    @Test
+    public void testSetDataTypesFromGraph() {
+        GraphVertex containerVertex = new GraphVertex();
+        ComponentParametersView filter = new ComponentParametersView(true);
+        filter.setIgnoreComponentInstancesInterfaces(true);
+        filter.setIgnoreDataType(false);
+        String componentName = "componentName";
+        String componentId = UniqueIdBuilder.buildResourceUniqueId();
+        containerVertex.setVertex(Mockito.mock(TitanVertex.class));
+        containerVertex.setJsonMetadataField(JsonPresentationFields.NAME, componentName);
+        containerVertex.setUniqueId(componentId);
+        containerVertex.setLabel(VertexTypeEnum.TOPOLOGY_TEMPLATE);
+        when(titanDao.getChildVertex(any(GraphVertex.class), any(EdgeLabelEnum.class), any(JsonParseFlagEnum.class))).thenReturn(Either.right(TitanOperationStatus.GENERAL_ERROR));
+        Either<ToscaElement, StorageOperationStatus> storageOperationStatus = topologyTemplateOperation.getToscaElement(containerVertex, filter);
+        assertThat(storageOperationStatus).isEqualTo(Either.right(StorageOperationStatus.GENERAL_ERROR));
+    }
+
     @Test
     public void testUpdateDistributionStatus() {
         Either<GraphVertex, StorageOperationStatus> result;
index 63856e6..0eb0b3c 100644 (file)
@@ -61,6 +61,9 @@ import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElementTypeEnum;
 import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.datatypes.elements.DataTypeDataDefinition;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -73,6 +76,8 @@ import java.util.Set;
 import java.util.HashSet;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
+import java.util.Collections;
+import java.util.Arrays;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
@@ -81,11 +86,11 @@ import static org.mockito.Mockito.when;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyMap;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 
 @RunWith(MockitoJUnitRunner.class)
 public class ToscaOperationFacadeTest {
-
     @InjectMocks
     private ToscaOperationFacade testInstance;
 
@@ -482,6 +487,103 @@ public class ToscaOperationFacadeTest {
         return toscaElement;
     }
 
+    @Test
+    public void addDataTypesToComponentSuccessTest(){
+        Either<List<DataTypeDefinition>, StorageOperationStatus> result = addDataTypesToComponentWithStatus(StorageOperationStatus.OK);
+        assertTrue(result.isLeft());
+    }
+
+    @Test
+    public void addDataTypesToComponentFailureTest_BadRequest(){
+        Either<List<DataTypeDefinition>, StorageOperationStatus> result = addDataTypesToComponentWithStatus(StorageOperationStatus.BAD_REQUEST);
+        assertTrue(result.isRight() && result.right().value() == StorageOperationStatus.BAD_REQUEST);
+    }
+
+    private Either<List<DataTypeDefinition>, StorageOperationStatus> addDataTypesToComponentWithStatus(StorageOperationStatus status) {
+        Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
+        String componentId = "componentid";
+        String Id = "id";
+
+        PropertyDefinition noDefaultProp = new PropertyDefinition();
+        noDefaultProp.setName("noDefaultProp");
+        PropertyDefinition prop1 = new PropertyDefinition();
+        prop1.setDefaultValue("def1");
+        prop1.setName("prop1");
+        PropertyDefinition prop2 = new PropertyDefinition();
+        prop2.setType("dataType1");
+        prop2.setName("prop2");
+        PropertyDefinition prop3 = new PropertyDefinition();
+        prop3.setDefaultValue("def3");
+        prop3.setName("prop3");
+
+        DataTypeDefinition noDefaultValue = new DataTypeDefinition();
+        noDefaultValue.setProperties(Collections.singletonList(noDefaultProp));
+        noDefaultValue.setDerivedFromName("name0");
+
+        DataTypeDefinition dataType1 = new DataTypeDefinition();
+        dataType1.setProperties(Arrays.asList(prop1, prop3));
+        dataType1.setName("name1");
+        dataType1.setDerivedFromName("derivedfromname1");
+
+        DataTypeDefinition dataType2 = new DataTypeDefinition();
+        dataType2.setDerivedFrom(dataType1);
+        dataType2.setName("name2");
+        dataType2.setDerivedFromName("derivedfromname2");
+
+        DataTypeDefinition dataType3 = new DataTypeDefinition();
+        dataType3.setProperties(Collections.singletonList(prop2));
+        dataType3.setDerivedFrom(noDefaultValue);
+        dataType3.setName("name3");
+        dataType3.setDerivedFromName("derivedfromname3");
+
+        dataTypes.put("noDefault", noDefaultValue);
+        dataTypes.put("dataType1", dataType1);
+        dataTypes.put("dataType2", dataType2);
+        dataTypes.put("dataType3", dataType3);
+
+        GraphVertex vertex;
+        if(status == StorageOperationStatus.OK){
+            vertex = getTopologyTemplateVertex();
+        } else {
+            vertex = getNodeTypeVertex();
+        }
+        Either<GraphVertex, TitanOperationStatus> getVertexEither = Either.left(vertex);
+        when(titanDaoMock.getVertexById(componentId, JsonParseFlagEnum.NoParse)).thenReturn(getVertexEither);
+        when(topologyTemplateOperationMock.addToscaDataToToscaElement(eq(vertex),
+                eq(EdgeLabelEnum.DATA_TYPES), eq(VertexTypeEnum.DATA_TYPES), anyMap(), eq(JsonPresentationFields.NAME))).thenReturn(status);
+        return testInstance.addDataTypesToComponent(dataTypes, componentId);
+    }
+
+    @Test
+    public void testDataTypesToComponentFailureTest_NotFound() {
+        Either<List<DataTypeDefinition>, StorageOperationStatus> result;
+        String componentId = "componentId";
+        GraphVertex vertex = getNodeTypeVertex();
+        Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
+        when(titanDaoMock.getVertexById(componentId, JsonParseFlagEnum.NoParse)).thenReturn(Either.right(TitanOperationStatus.NOT_FOUND));
+        result = testInstance.addDataTypesToComponent(dataTypes, componentId);
+        assertTrue(result.isRight() && result.right().value() == StorageOperationStatus.NOT_FOUND);
+    }
+
+    @Test
+    public void testDeleteDataTypeOfComponent() {
+        StorageOperationStatus result;
+        Component component = new Resource();
+        String id = "id";
+        component.setUniqueId(id);
+        String datatype = null;
+
+        DataTypeDefinition dataType1 = new DataTypeDefinition();
+        dataType1.setName("name1");
+        Map<String, DataTypeDataDefinition> dataTypeDataMap = new HashMap<>();
+        dataTypeDataMap.put("datatype1", dataType1);
+        List<DataTypeDefinition> dataTypeMap = dataTypeDataMap.values().stream().map(e -> { DataTypeDefinition dataType = new DataTypeDefinition(e);return dataType; }).collect(Collectors.toList());
+        component.setDataTypes(dataTypeMap);
+        GraphVertex graphVertex = getTopologyTemplateVertex();
+        result = testInstance.deleteDataTypeOfComponent(component, "datatype1");
+        assertEquals(datatype, result);
+    }
+
     private Either<PolicyDefinition, StorageOperationStatus> associatePolicyToComponentWithStatus(StorageOperationStatus status) {
         PolicyDefinition policy = new PolicyDefinition();
         String componentId = "componentId";
index cd488d9..b541beb 100644 (file)
@@ -81,6 +81,7 @@ import {RequirementsEditorModule} from "./pages/req-and-capabilities-editor/requ
 import {CapabilitiesEditorModule} from "./pages/req-and-capabilities-editor/capabilities-editor/capabilities-editor.module"
 import {GenericArtifactBrowserModule} from "./components/logic/generic-artifact-browser/generic-artifact-browser.module";
 import {GabService} from "./services/gab.service";
+import {DeclareListModule} from "./pages/properties-assignment/declare-list/declare-list.module"
 
 export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule));
 
@@ -114,6 +115,7 @@ export function configServiceFactory(config: ConfigService) {
         ConnectionWizardModule,
         PropertiesAssignmentModule,
         PropertyCreatorModule,
+        DeclareListModule,
         PluginFrameModule,
         InterfaceOperationModule,
         OperationCreatorModule,
index 167509b..0cc1881 100644 (file)
@@ -45,7 +45,8 @@ export class PropertiesTableComponent {
     
     @Output('propertyChanged') emitter: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>();
     @Output() selectPropertyRow: EventEmitter<PropertyRowSelectedEvent> = new EventEmitter<PropertyRowSelectedEvent>();
-    @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareOption
+    @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareOption and hasDeclareListOption
+    @Output() updateCheckedChildPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareListOption
     @Output() deleteProperty: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>();
     private selectedPropertyToDelete: PropertyFEModel;
 
@@ -94,6 +95,11 @@ export class PropertiesTableComponent {
             this.propertiesService.disableRelatedProperties(prop, childPropName);
         }
         this.updateCheckedPropertyCount.emit(isChecked);
+
+        if (childPropName) {
+            let isCount: boolean = (isChecked)? true : false ;
+            this.updateCheckedChildPropertyCount.emit(isCount);
+        }
     }
 
     onDeleteProperty = () => {
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.html
new file mode 100644 (file)
index 0000000..c0bcc78
--- /dev/null
@@ -0,0 +1,83 @@
+<!--
+* ============LICENSE_START=======================================================
+* SDC
+* ================================================================================
+* Copyright (C) 2019 Fujitsu Limited. All rights reserved.
+* ================================================================================
+* 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.
+* ============LICENSE_END=========================================================
+*/
+-->
+
+<div class="declare-list">
+    <loader [display]="isLoading" [size]="'large'" [relative]="true" [loaderDelay]="500"></loader>
+    <form class="w-sdc-form">
+
+        <div class="side-by-side">
+            <div class="i-sdc-form-item">
+                <label class="i-sdc-form-label required">Name</label>
+                <input class="i-sdc-form-input"
+                       type="text"
+                       name="propertyName"
+                       data-tests-id="property-name"
+                       [(ngModel)]="propertyModel.name"
+                       [ngModelOptions]="{ debounce: 200 }"
+                       autofocus/>
+            </div>
+            <!-- Type -->
+            <div class="i-sdc-form-item">
+                <label class="i-sdc-form-label">Type</label>
+                <input class="i-sdc-form-input"
+                       type="text"
+                       data-tests-id="property-type"
+                       value="list"
+                       disabled
+                       autofocus/>
+            </div>
+        </div>
+
+        <!-- Schema Type -->
+        <div class="i-sdc-form-item">
+            <label class="i-sdc-form-label required">New Schema Type for List</label>
+            <input class="i-sdc-form-input"
+                    type="text"
+                    name="typeName"
+                    [(ngModel)]="propertyModel.simpleType"
+                    [ngModelOptions]="{ debounce: 200 }">
+        </div>
+        
+        <!-- Properties -->
+        <div class="i-sdc-form-item">
+            <label class="i-sdc-form-label">Properties</label>
+            <input class="i-sdc-form-input"
+                   type="text"
+                   name="properties"
+                   data-tests-id="properties"
+                   value="{{propertiesListString}}"
+                   disabled>
+        </div>
+
+        <!-- Description -->
+        <div class="i-sdc-form-item">
+            <label class="i-sdc-form-label">Description</label>
+            <textarea  class="i-sdc-form-textarea"
+                       [pattern]="commentValidationPattern"
+                       name="propertyDescription"
+                       [(ngModel)]="propertyModel.description"
+                       [ngModelOptions]="{ debounce: 200 }"
+                       data-tests-id="property-description"
+            ></textarea>
+        </div>
+
+    </form>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.less
new file mode 100644 (file)
index 0000000..8d66389
--- /dev/null
@@ -0,0 +1,35 @@
+@import '../../../../../assets/styles/variables.less';
+
+.declare-list {
+    font-family: @font-opensans-regular;
+    user-select: none;
+    padding-top: 12px;
+    padding-bottom: 20px;
+
+    .i-sdc-form-label {
+        font-size: 12px;
+    }
+
+    .w-sdc-form .i-sdc-form-item {
+        margin-bottom: 15px;
+    }
+
+    .side-by-side {
+        display: flex;
+
+        .i-sdc-form-item {
+            flex-basis: 100%;
+
+            &:first-child {
+                flex-basis: 50%;
+                margin-right: 10px;
+            }
+
+        }
+        .propertySchemaType{
+            margin-left: 10px;
+        }
+    }
+
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.component.ts
new file mode 100644 (file)
index 0000000..20e04f8
--- /dev/null
@@ -0,0 +1,114 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019 Fujitsu Limited. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+import * as _ from "lodash";
+import {Component} from '@angular/core';
+import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
+import { DataTypeService } from "app/ng2/services/data-type.service";
+import {PropertyBEModel, DataTypesMap} from "app/models";
+import {PROPERTY_DATA} from "app/utils";
+import {PROPERTY_TYPES} from "../../../../utils";
+import { ModalService } from "app/ng2/services/modal.service";
+import { InstancePropertiesAPIMap } from "app/models/properties-inputs/property-fe-map";
+import { ModalModel } from "app/models/modal";
+import { DataTypeModel } from "app/models/data-types";
+
+
+
+@Component({
+    selector: 'declare-list',
+    templateUrl: './declare-list.component.html',
+    styleUrls:['./declare-list.component.less'],
+})
+
+export class DeclareListComponent {
+
+    typesProperties: Array<DropdownValue>;
+    typesSchemaProperties: Array<DropdownValue>;
+    propertyModel: PropertyBEModel;
+    //propertyNameValidationPattern:RegExp = /^[a-zA-Z0-9_:-]{1,50}$/;
+    //commentValidationPattern:RegExp = /^[\u0000-\u00BF]*$/;
+    //types:Array<string>;
+    dataTypes:DataTypesMap;
+    isLoading:boolean;
+    inputsToCreate:InstancePropertiesAPIMap;
+    propertiesListString:string;
+    privateDataType: DataTypeModel;
+
+    constructor(protected dataTypeService:DataTypeService, private modalService:ModalService) {}
+
+    ngOnInit() {
+        console.log('DeclareListComponent.ngOnInit() - enter');
+        this.propertyModel = new PropertyBEModel();
+        this.propertyModel.type = '';
+        this.propertyModel.schema.property.type = '';
+        const types: Array<string> =  PROPERTY_DATA.TYPES; //All types - simple type + map + list
+        this.dataTypes = this.dataTypeService.getAllDataTypes(); //Get all data types in service
+        const nonPrimitiveTypes :Array<string> = _.filter(Object.keys(this.dataTypes), (type:string)=> {
+            return types.indexOf(type) == -1;
+        });
+
+        this.typesProperties = _.map(PROPERTY_DATA.TYPES,
+            (type: string) => new DropdownValue(type, type)
+        );
+        let typesSimpleProperties = _.map(PROPERTY_DATA.SIMPLE_TYPES,
+            (type: string) => new DropdownValue(type, type)
+        );
+        let nonPrimitiveTypesValues = _.map(nonPrimitiveTypes,
+            (type: string) => new DropdownValue(type,
+                    type.replace("org.openecomp.datatypes.heat.",""))
+        );
+        this.typesProperties = _.concat(this.typesProperties,nonPrimitiveTypesValues);
+        this.typesSchemaProperties = _.concat(typesSimpleProperties,nonPrimitiveTypesValues);
+        this.typesProperties.unshift(new DropdownValue('','Select Type...'));
+        this.typesSchemaProperties.unshift(new DropdownValue('','Select Schema Type...'));
+
+        this.inputsToCreate = this.modalService.currentModal.instance.dynamicContent.instance.input.properties;
+
+        this.propertiesListString = this.modalService.currentModal.instance.dynamicContent.instance.input.propertyNameList.join(", ");
+
+        this.privateDataType = new DataTypeModel(null);
+        this.privateDataType.name = "datatype";
+
+        console.log('DeclareListComponent.ngOnInit() - leave');
+    }
+
+    checkFormValidForSubmit(){
+        const showSchema:boolean = this.showSchema();
+        let isSchemaValid: boolean = (showSchema && !this.propertyModel.schema.property.type)? false : true;
+        if (!showSchema){
+            this.propertyModel.schema.property.type = '';
+        }
+        return this.propertyModel.name && this.propertyModel.type && isSchemaValid;
+    }
+
+    showSchema():boolean {
+        return [PROPERTY_TYPES.LIST, PROPERTY_TYPES.MAP].indexOf(this.propertyModel.type) > -1;
+    };
+
+    onSchemaTypeChange():void {
+        if (this.propertyModel.type == PROPERTY_TYPES.MAP) {
+            this.propertyModel.value = JSON.stringify({'': null});
+        } else if (this.propertyModel.type == PROPERTY_TYPES.LIST) {
+            this.propertyModel.value = JSON.stringify([]);
+        }
+    };
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/declare-list/declare-list.module.ts
new file mode 100644 (file)
index 0000000..54af76a
--- /dev/null
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019 Fujitsu Limited. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {DeclareListComponent} from "./declare-list.component";
+import {FormsModule} from "@angular/forms";
+import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module";
+import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
+import {TranslateModule} from "../../../shared/translator/translate.module";
+
+@NgModule({
+    declarations: [
+        DeclareListComponent,
+    ],
+    imports: [
+        CommonModule,
+        FormsModule,
+        FormElementsModule,
+        UiElementsModule,
+        TranslateModule
+    ],
+    exports: [],
+    entryComponents: [
+        DeclareListComponent
+    ],
+    providers: []
+})
+
+export class DeclareListModule {}
index 1ec6df9..580c362 100644 (file)
@@ -35,6 +35,7 @@
                             (selectPropertyRow)="selectPropertyRow($event)"
                             (selectChildProperty)="selectChildProperty($event)"
                             (updateCheckedPropertyCount)="updateCheckedPropertyCount($event)"
+                            (updateCheckedChildPropertyCount)="updateCheckedChildPropertyCount($event)"
                             (selectInstanceRow)="selectInstanceRow($event)"
                             (deleteProperty)="deleteProperty($event)">
                         </properties-table>
@@ -73,6 +74,7 @@
                 </div>
                 <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="declareProperties()" data-tests-id="declare-button declare-input">Declare Input</button>
                 <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData || isSelf()" (click)="declarePropertiesToPolicies()" data-tests-id="declare-button declare-policy">Declare Policy</button>
+                <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || checkedChildPropertiesCount || isReadonly || hasChangedData" (click)="declareListProperties()" data-tests-id="declare-button declare-list-input">Create List Input</button>
             </div>
         </div>
         <div class="right-column">
index 523eda2..1401552 100644 (file)
         }
 
         .declare-button{
-            &:first-of-type {
+            &:not(:last-of-type) {
                 margin-right: 10px;
             }
         }
index 38278c9..9f406f8 100644 (file)
@@ -39,11 +39,16 @@ import {ModalService} from "../../services/modal.service";
 import {Tabs, Tab} from "../../components/ui/tabs/tabs.component";
 import {InputsUtils} from "./services/inputs.utils";
 import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
+import {DeclareListComponent} from "./declare-list/declare-list.component";
 import { InstanceFeDetails } from "../../../models/instance-fe-details";
 import { SdcUiComponents } from "sdc-ui/lib/angular";
 //import { ModalService as ModalServiceSdcUI} from "sdc-ui/lib/angular/modals/modal.service";
 import { IModalButtonComponent } from "sdc-ui/lib/angular/modals/models/modal-config";
 import { UnsavedChangesComponent } from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component";
+import { DataTypeService } from "app/ng2/services/data-type.service";
+import { DataTypeModel } from "app/models";
+import { PROPERTY_DATA, PROPERTY_TYPES } from "app/utils";
+import { PropertyDeclareAPIModel} from "app/models";
 
 const SERVICE_SELF_TITLE = "SELF";
 @Component({
@@ -69,6 +74,7 @@ export class PropertiesAssignmentComponent {
     selectedFlatProperty: SimpleFlatProperty = new SimpleFlatProperty();
     selectedInstanceData: ComponentInstance|GroupInstance|PolicyInstance = null;
     checkedPropertiesCount: number = 0;
+    checkedChildPropertiesCount: number = 0;
 
     hierarchyPropertiesDisplayOptions:HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens');
     hierarchyInstancesDisplayOptions:HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass');
@@ -296,6 +302,7 @@ export class PropertiesAssignmentComponent {
     processInstancePropertiesResponse = (instanceBePropertiesMap: InstanceBePropertiesMap, originTypeIsVF: boolean) => {
         this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values
         this.checkedPropertiesCount = 0;
+        this.checkedChildPropertiesCount = 0;
     };
 
 
@@ -418,6 +425,7 @@ export class PropertiesAssignmentComponent {
             let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
             if (selectedInstanceData instanceof ComponentInstance) {
                 if (!this.isInput(selectedInstanceData.originType)) {
+                    // convert Property FE model -> Property BE model, extract only checked
                     selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
                 } else {
                     selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
@@ -436,6 +444,7 @@ export class PropertiesAssignmentComponent {
             .subscribe(response => {
                 this.setInputTabIndication(response.length);
                 this.checkedPropertiesCount = 0;
+                this.checkedChildPropertiesCount = 0;
                 _.forEach(response, (input: InputBEModel) => {
                     let newInput: InputFEModel = new InputFEModel(input);
                     this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
@@ -445,6 +454,123 @@ export class PropertiesAssignmentComponent {
             }, error => {}); //ignore error
     };
 
+    declareListProperties = (): void => {
+        console.log('declareListProperties() - enter');
+
+        // get selected properties
+        let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
+        let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
+        let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
+        let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
+        let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
+        let propertyNameList: Array<string> = [];
+        let insId :string;
+
+        angular.forEach(instancesIds, (instanceId: string): void => {
+            console.log("instanceId="+instanceId);
+            insId = instanceId;
+            let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
+            let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
+
+            if (selectedInstanceData instanceof ComponentInstance) {
+                if (!this.isInput(selectedInstanceData.originType)) {
+                    // convert Property FE model -> Property BE model, extract only checked
+                    selectedComponentInstancesProperties[instanceId] = checkedProperties;
+                } else {
+                    selectedComponentInstancesInputs[instanceId] = checkedProperties;
+                }
+            } else if (selectedInstanceData instanceof GroupInstance) {
+                selectedGroupInstancesProperties[instanceId] = checkedProperties;
+            } else if (selectedInstanceData instanceof PolicyInstance) {
+                selectedPolicyInstancesProperties[instanceId] = checkedProperties;
+            }
+
+            angular.forEach(checkedProperties, (property: PropertyBEModel) => {
+                propertyNameList.push(property.name);
+            });
+        });
+
+        let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
+
+        let modalTitle = 'Declare Properties as List Input';
+        const modal = this.ModalService.createCustomModal(new ModalModel(
+            'sm', /* size */
+            modalTitle, /* title */
+            null, /* content */
+            [ /* buttons */
+                new ButtonModel(
+                    'Save', /* text */
+                    'blue', /* css class */
+                    () => { /* callback */
+                        let content:any = modal.instance.dynamicContent.instance;
+
+                        /* listInput */
+                        let reglistInput: InstanceBePropertiesMap = new InstanceBePropertiesMap();
+                        let typelist: any = PROPERTY_TYPES.LIST;
+                        let uniID: any = insId;
+                        let boolfalse: any = false;
+                        let schem :any = {
+                            "empty": boolfalse,
+                            "property": {
+                                "type": content.propertyModel.simpleType,
+                                "required": boolfalse
+                            }
+                        }
+                        let schemaProp :any = {
+                            "type": content.propertyModel.simpleType,
+                            "required": boolfalse
+                        }
+
+                        reglistInput.description = content.propertyModel.description;
+                        reglistInput.name = content.propertyModel.name;
+                        reglistInput.type = typelist;
+                        reglistInput.schemaType = content.propertyModel.simpleType;
+                        reglistInput.instanceUniqueId = uniID;
+                        reglistInput.uniqueId = uniID;
+                        reglistInput.required =boolfalse;
+                        reglistInput.schema = schem;
+                        reglistInput.schemaProperty = schemaProp;
+
+                        let input = {
+                            componentInstInputsMap: content.inputsToCreate,
+                            listInput: reglistInput
+                        };
+                        console.log("save button clicked. input=", input);
+
+                        this.componentServiceNg2
+                        .createListInput(this.component, input, this.isSelf())
+                        .subscribe(response => {
+                            this.setInputTabIndication(response.length);
+                            this.checkedPropertiesCount = 0;
+                            this.checkedChildPropertiesCount = 0;
+                            _.forEach(response, (input: InputBEModel) => {
+                                let newInput: InputFEModel = new InputFEModel(input);
+                                this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
+                                this.inputs.push(newInput);
+                                // create list input does not return updated properties info, so need to reload
+                                //this.updatePropertyValueAfterDeclare(newInput);
+                                // Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
+                                this.changeSelectedInstance(this.selectedInstanceData);
+
+                                modal.instance.close();
+                            });
+                        }, error => {}); //ignore error
+            
+                    }
+                    /*, getDisabled: function */
+                ),
+                new ButtonModel('Cancel', 'outline grey', () => {
+                    modal.instance.close();
+                }),
+            ],
+            null /* type */
+        ));
+        // 3rd arg is passed to DeclareListComponent instance
+        this.ModalService.addDynamicContentToModal(modal, DeclareListComponent, {properties: inputsToCreate, propertyNameList: propertyNameList});
+        modal.instance.open();
+        console.log('declareListProperties() - leave');
+    };
+
     /*** DECLARE PROPERTIES/POLICIES ***/
     declarePropertiesToPolicies = (): void => {
         let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
@@ -609,6 +735,8 @@ export class PropertiesAssignmentComponent {
             handleReverseItem = (changedItem) => {
                 changedItem = <PropertyFEModel>changedItem;
                 this.propertiesUtils.resetPropertyValue(changedItem, changedItem.value);
+                this.checkedPropertiesCount = 0;
+                this.checkedChildPropertiesCount = 0;
             };
         } else if (this.isInputsTabSelected) {
             handleReverseItem = (changedItem) => {
@@ -643,6 +771,10 @@ export class PropertiesAssignmentComponent {
                     title: 'Saved'
                 });
                 if(onSuccessFunction) onSuccessFunction();
+                if(this.isPropertiesTabSelected){
+                    this.checkedPropertiesCount = 0;
+                    this.checkedChildPropertiesCount = 0;
+                }
             },
             () => {
                 this.Notification.error({
@@ -698,6 +830,10 @@ export class PropertiesAssignmentComponent {
         console.log("CheckedProperties count is now.... " + this.checkedPropertiesCount);
     };
 
+    updateCheckedChildPropertyCount = (increment: boolean): void => {
+        this.checkedChildPropertiesCount += (increment) ? 1 : -1;
+    };
+
     setInputTabIndication = (numInputs: number): void => {
         this.propertyInputTabs.setTabIndication('Inputs', numInputs);
     };
index e0884d7..c313a3f 100644 (file)
@@ -307,6 +307,25 @@ export class ComponentServiceNg2 {
             })
     }
 
+    createListInput(component:Component, input:any, isSelf:boolean):Observable<any> {
+        let inputs: any;
+        if(isSelf) {
+            // change componentInstanceProperties -> serviceProperties
+            inputs = {
+                componentInstInputsMap: {
+                    serviceProperties: input.componentInstInputsMap.componentInstanceProperties
+                },
+                listInput: input.listInput
+            };
+        } else {
+            inputs = input;
+        }
+        return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/listInput', inputs)
+            .map(res => {
+                return res.json();
+            })
+    }
+
     createPolicy(component:Component, policiesToCreate:InstancePropertiesAPIMap, isSelf:boolean):Observable<any> {
         const policiesList =
             isSelf ?
index 358f8ef..a4042d9 100644 (file)
@@ -22,6 +22,8 @@ package org.openecomp.sdc.be.datatypes.elements;
 
 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
 
+import java.util.List;
+
 public class DataTypeDataDefinition extends ToscaDataDefinition {
 
        private String name;
@@ -43,6 +45,8 @@ public class DataTypeDataDefinition extends ToscaDataDefinition {
         */
        private Long modificationTime;
 
+       private List<PropertyDataDefinition> propertiesData;
+
        public DataTypeDataDefinition() {
 
        }
@@ -104,11 +108,19 @@ public class DataTypeDataDefinition extends ToscaDataDefinition {
                this.modificationTime = modificationTime;
        }
 
+       public List<PropertyDataDefinition> getPropertiesData() {
+               return propertiesData;
+       }
+
+       public void setPropertiesData(List<PropertyDataDefinition> propertiesData) {
+               this.propertiesData = propertiesData;
+       }
+
        @Override
        public String toString() {
                return "DataTypeDataDefinition [name=" + name + ", uniqueId=" + uniqueId + ", derivedFromName="
                                + derivedFromName + ", description=" + description + ", creationTime=" + creationTime
-                               + ", modificationTime=" + modificationTime + "]";
+                               + ", modificationTime=" + modificationTime + ", propertiesData=" + propertiesData + "]";
        }
 
 }
index fed728d..218b648 100644 (file)
@@ -75,6 +75,8 @@ public class PropertyDataDefinition extends ToscaDataDefinition {
 
        private List<GetInputValueDataDefinition> getInputValues;
 
+       private Boolean isDeclaredListInput = Boolean.FALSE;
+
        private List<GetPolicyValueDataDefinition> getPolicyValues;
 
        public PropertyDataDefinition() {
@@ -86,35 +88,36 @@ public class PropertyDataDefinition extends ToscaDataDefinition {
 
        }
 
-       public PropertyDataDefinition(PropertyDataDefinition p) {
+       public PropertyDataDefinition(PropertyDataDefinition propertyDataDefinition) {
                super();
-               this.setUniqueId(p.getUniqueId());
-               this.setRequired(p.isRequired());
-               this.setDefaultValue(p.getDefaultValue());
-               this.setDescription(p.getDescription());
-               this.setSchema(p.getSchema());
-               this.setPassword(p.isPassword());
-               this.setType(p.getType());
-               this.setName(p.getName());
-               this.setValue(p.getValue());
-               this.setRequired(p.isRequired());
-               this.setHidden(p.isHidden());
-               this.setLabel(p.getLabel());
-               this.setImmutable(p.isImmutable());
-               this.setParentUniqueId(p.getParentUniqueId());
-               this.setOwnerId(p.getOwnerId());
-               this.setGetInputValues(p.getGetInputValues());
-               this.setGetPolicyValues(p.getGetPolicyValues());
-               this.setInputPath(p.getInputPath());
-               this.setStatus(p.getStatus());
-               this.setInputId(p.getInputId());
-               this.setInstanceUniqueId(p.getInstanceUniqueId());
-               this.setPropertyId(p.getPropertyId());
-               this.parentPropertyType = p.getParentPropertyType();
-               this.subPropertyInputPath = p.getSubPropertyInputPath();
-               if(isNotEmpty(p.annotations)){
-                   this.setAnnotations(p.annotations);
+               this.setUniqueId(propertyDataDefinition.getUniqueId());
+               this.setRequired(propertyDataDefinition.isRequired());
+               this.setDefaultValue(propertyDataDefinition.getDefaultValue());
+               this.setDescription(propertyDataDefinition.getDescription());
+               this.setSchema(propertyDataDefinition.getSchema());
+               this.setPassword(propertyDataDefinition.isPassword());
+               this.setType(propertyDataDefinition.getType());
+               this.setName(propertyDataDefinition.getName());
+               this.setValue(propertyDataDefinition.getValue());
+               this.setRequired(propertyDataDefinition.isRequired());
+               this.setHidden(propertyDataDefinition.isHidden());
+               this.setLabel(propertyDataDefinition.getLabel());
+               this.setImmutable(propertyDataDefinition.isImmutable());
+               this.setParentUniqueId(propertyDataDefinition.getParentUniqueId());
+               this.setOwnerId(propertyDataDefinition.getOwnerId());
+               this.setGetInputValues(propertyDataDefinition.getGetInputValues());
+               this.setGetPolicyValues(propertyDataDefinition.getGetPolicyValues());
+               this.setInputPath(propertyDataDefinition.getInputPath());
+               this.setStatus(propertyDataDefinition.getStatus());
+               this.setInputId(propertyDataDefinition.getInputId());
+               this.setInstanceUniqueId(propertyDataDefinition.getInstanceUniqueId());
+               this.setPropertyId(propertyDataDefinition.getPropertyId());
+               this.parentPropertyType = propertyDataDefinition.getParentPropertyType();
+               this.subPropertyInputPath = propertyDataDefinition.getSubPropertyInputPath();
+               if(isNotEmpty(propertyDataDefinition.annotations)){
+                   this.setAnnotations(propertyDataDefinition.annotations);
         }
+               this.setIsDeclaredListInput(propertyDataDefinition.getIsDeclaredListInput());
        }
 
        public String getParentPropertyType() {
@@ -321,13 +324,21 @@ public class PropertyDataDefinition extends ToscaDataDefinition {
                this.propertyId = propertyId;
        }
 
+       public Boolean getIsDeclaredListInput() {
+               return isDeclaredListInput;
+       }
+
+       public void setIsDeclaredListInput(Boolean isDeclaredListInput) {
+               this.isDeclaredListInput = isDeclaredListInput;
+       }
+
        @Override
        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
-                               +  "parentPropertyType" + parentPropertyType
-                               +  "subPropertyInputPath" + subPropertyInputPath +"]";
+                               + instanceUniqueId + ", propertyId=" + propertyId + ", parentUniqueId=" + parentUniqueId + ", getInputValues=" + getInputValues + ", isDeclaredListInput=" + isDeclaredListInput
+                               +  ", parentPropertyType=" + parentPropertyType
+                               +  ", subPropertyInputPath=" + subPropertyInputPath +"]";
        }
 
        @Override
@@ -344,6 +355,7 @@ public class PropertyDataDefinition extends ToscaDataDefinition {
                result = prime * result + ((uniqueId == null) ? 0 : uniqueId.hashCode());
                result = prime * result + ((parentUniqueId == null) ? 0 : parentUniqueId.hashCode());
                result = prime * result + ((status == null) ? 0 : status.hashCode());
+               result = prime * result + ((isDeclaredListInput == null) ? 0 : isDeclaredListInput.hashCode());
                return result;
        }
 
@@ -446,6 +458,13 @@ public class PropertyDataDefinition extends ToscaDataDefinition {
                } else if (!status.equals(other.status)) {
             return false;
         }
+               if (isDeclaredListInput == null) {
+                       if (other.isDeclaredListInput != null) {
+                               return false;
+                       }
+               } else if (!isDeclaredListInput.equals(other.isDeclaredListInput)) {
+                       return false;
+               }
                return true;
        }
 
index a0843eb..8d83be4 100644 (file)
@@ -45,7 +45,8 @@ public enum ComponentFieldsEnum {
     POLICIES("policies"),
     NON_EXCLUDED_POLICIES("nonExcludedPolicies"),
     NODE_FILTER("nodeFilter"),
-    COMPONENT_INSTANCES_INTERFACES("componentInstancesInterfaces")
+    COMPONENT_INSTANCES_INTERFACES("componentInstancesInterfaces"),
+    DATA_TYPES("dataTypes")
     ;