Add property mapping feature to ONAP 59/77659/4
authorTalio <tali.orenbach@amdocs.com>
Thu, 31 Jan 2019 16:00:36 +0000 (18:00 +0200)
committerAvi Gaffa <avi.gaffa@amdocs.com>
Mon, 4 Feb 2019 11:00:09 +0000 (11:00 +0000)
Add service property assignment

Change-Id: I29748ce12bacab06b8bc27f8875b39d80ffe5af7
Issue-ID: SDC-1988
Signed-off-by: Talio <tali.orenbach@amdocs.com>
56 files changed:
catalog-be/pom.xml
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/PropertyBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclarator.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/DefaultPropertyDeclarator.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/property/PropertyDeclarationOrchestrator.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentPropertyServlet.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/PropertyServlet.java [deleted file]
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.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/ToscaNodeTemplate.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InputConverter.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtil.java
catalog-be/src/main/java/org/openecomp/sdc/externalupload/utils/ServiceUtils.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/PropertyBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/InterfaceOperationValidationTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/servlets/PropertyServletTest.java [deleted file]
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/PropertyConvertorTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/utils/InterfacesOperationsToscaUtilTest.java
catalog-be/src/test/java/org/openecomp/sdc/test/utils/InterfaceOperationTestUtils.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
catalog-model/pom.xml
catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstInputsMap.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceInterface.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/InterfaceInstanceDefinition.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceDataDefinition.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceInstanceDataDefinition.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/OperationInstance.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/Resource.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/Service.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/ToscaOperationFacade.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java
catalog-ui/src/app/ng2/app.module.ts
catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html
catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.less
catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts
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/pages/properties-assignment/property-creator/property-creator.component.html [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.less [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts
catalog-ui/src/app/ng2/services/component-services/component.service.ts
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/InterfaceInstanceDataDefinition.java [new file with mode: 0644]
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationImplementation.java [new file with mode: 0644]
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInstance.java [new file with mode: 0644]

index 8bbe456..4c0cbbf 100644 (file)
             <groupId>io.netty</groupId>
             <artifactId>netty-handler</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.onap.sdc.common</groupId>
+            <artifactId>onap-tosca-datatype</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-collections4</artifactId>
+            <version>4.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.openecomp.sdc.be</groupId>
+            <artifactId>catalog-model</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.sdc.common</groupId>
+            <artifactId>onap-tosca-datatype</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-collections4</artifactId>
+            <version>4.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.openecomp.sdc.be</groupId>
+            <artifactId>catalog-model</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 
     <build>
index 5f40606..f49f531 100644 (file)
@@ -7,9 +7,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,19 +22,27 @@ package org.openecomp.sdc.be.components.impl;
 
 import com.google.gson.JsonElement;
 import fj.data.Either;
+import java.util.Map.Entry;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.openecomp.sdc.be.config.BeEcompErrorManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstanceInterface;
+import org.openecomp.sdc.be.model.ComponentParametersView;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.IComplexDefaultValue;
+import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.PropertyDefinition;
-import org.openecomp.sdc.be.model.Resource;
 import org.openecomp.sdc.be.model.operations.api.IElementOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
@@ -45,17 +53,13 @@ import org.openecomp.sdc.be.resources.data.EntryData;
 import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.exception.ResponseFormat;
-import org.springframework.stereotype.Component;
 import org.springframework.web.context.WebApplicationContext;
 
 import javax.servlet.ServletContext;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
+import java.util.*;
 import java.util.function.Supplier;
 
-@Component("propertyBusinessLogic")
+@org.springframework.stereotype.Component("propertyBusinessLogic")
 public class PropertyBusinessLogic extends BaseBusinessLogic {
 
     private static final String CREATE_PROPERTY = "CreateProperty";
@@ -77,262 +81,368 @@ public class PropertyBusinessLogic extends BaseBusinessLogic {
     }
 
     /**
-     * Create new property on resource in graph
+     * Create new property on component in graph
      *
-     * @param resourceId
+     * @param componentId
      * @param propertyName
      * @param newPropertyDefinition
      * @param userId
      * @return either properties or response format
      */
-    public Either<EntryData<String, PropertyDefinition>, ResponseFormat> createProperty(String resourceId, String propertyName, PropertyDefinition newPropertyDefinition, String userId) {
 
+    public Either<EntryData<String, PropertyDefinition>, ResponseFormat> addPropertyToComponent(String componentId,
+                                                                                                String propertyName,
+                                                                                                PropertyDefinition newPropertyDefinition,
+                                                                                                String userId) {
         Either<EntryData<String, PropertyDefinition>, ResponseFormat> result = null;
 
         validateUserExists(userId, "create Property", false);
 
-        StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource);
+        Either<Component, StorageOperationStatus> serviceElement =
+                toscaOperationFacade.getToscaElement(componentId);
+        if (serviceElement.isRight()) {
+            result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
+            return result;
+        }
+        Component component = serviceElement.left().value();
+        NodeTypeEnum nodeType = component.getComponentType().getNodeType();
+        StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType );
         if (!lockResult.equals(StorageOperationStatus.OK)) {
-            BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId);
-            log.info("Failed to lock component {}. Error - {}", resourceId, lockResult);
+            BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, nodeType.name().toLowerCase(), componentId);
+            log.info("Failed to lock component {}. Error - {}", componentId, lockResult);
             result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
             return result;
         }
 
         try {
-            // Get the resource from DB
-            Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId);
-            if (status.isRight()) {
-                result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
-                return result;
-            }
-            Resource resource = status.left().value();
-
-            // verify that resource is checked-out and the user is the last
-            // updater
-            if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) {
+            if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) {
                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
                 return result;
             }
 
-            // verify property not exist in resource
-            List<PropertyDefinition> resourceProperties = resource.getProperties();
+            List<PropertyDefinition> properties = component.getProperties();
 
-            if (resourceProperties != null && isPropertyExist(resourceProperties, resourceId, propertyName, newPropertyDefinition.getType())) {
-                result = Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_ALREADY_EXIST, propertyName));
-                return result;
+            if(CollectionUtils.isEmpty(properties)) {
+                properties = new ArrayList<>();
             }
 
-            Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache);
-            if (allDataTypes.isRight()) {
-                result = Either.right(allDataTypes.right().value());
+            if(isPropertyExistInComponent(properties, propertyName)) {
+
+                result =
+                    Either.right(componentsUtils.getResponseFormat(ActionStatus
+                        .PROPERTY_ALREADY_EXIST, propertyName));
                 return result;
-            }
 
-            Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value();
+            } else {
 
-            // validate property default values
-            Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newPropertyDefinition, dataTypes);
-            if (defaultValuesValidation.isRight()) {
-                result = Either.right(defaultValuesValidation.right().value());
-                return result;
-            }
-            convertProperty(newPropertyDefinition, allDataTypes);
+                Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache);
+                if (allDataTypes.isRight()) {
+                    result = Either.right(allDataTypes.right().value());
+                    return result;
+                }
 
+                Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value();
 
-            // add the new property to resource on graph
-            // need to get StorageOpaerationStatus and convert to ActionStatus
-            // from componentsUtils
-            Either<PropertyDefinition, StorageOperationStatus> either = toscaOperationFacade.addPropertyToResource(propertyName, newPropertyDefinition, resource);
-            if (either.isRight()) {
-                result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName()));
-                return result;
+                // validate property default values
+                Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newPropertyDefinition, dataTypes);
+                if (defaultValuesValidation.isRight()) {
+                    result = Either.right(defaultValuesValidation.right().value());
+                    return result;
+                }
+                // convert property
+                ToscaPropertyType type = getType(newPropertyDefinition.getType());
+                if (type != null) {
+                    PropertyValueConverter converter = type.getConverter();
+                    // get inner type
+                    String innerType = null;
+                    if (newPropertyDefinition != null) {
+                        SchemaDefinition schema = newPropertyDefinition.getSchema();
+                        if (schema != null) {
+                            PropertyDataDefinition prop = schema.getProperty();
+                            if (prop != null) {
+                                innerType = prop.getType();
+                            }
+                        }
+                        String convertedValue = null;
+                        if (newPropertyDefinition.getDefaultValue() != null) {
+                            convertedValue = converter.convert(
+                                (String) newPropertyDefinition.getDefaultValue(), innerType, allDataTypes.left().value());
+                            newPropertyDefinition.setDefaultValue(convertedValue);
+                        }
+                    }
+                }
+                Either<PropertyDefinition, StorageOperationStatus> addPropertyEither =
+                    toscaOperationFacade
+                        .addPropertyToComponent(propertyName, newPropertyDefinition, component);
+
+                if (addPropertyEither.isRight()) {
+                    log.info("Failed to add new property {}. Error - {}", componentId,
+                        addPropertyEither.right().value());
+                    result = Either.right(componentsUtils.getResponseFormat(ActionStatus
+                        .GENERAL_ERROR));
+                    return result;
+                }
             }
 
-            PropertyDefinition createdPropertyDefinition = either.left().value();
-            EntryData<String, PropertyDefinition> property = new EntryData<>(propertyName, createdPropertyDefinition);
-            result = Either.left(property);
+            result = Either.left(new EntryData<>(propertyName, newPropertyDefinition));
             return result;
 
         } finally {
             commitOrRollback(result);
             // unlock component
-            graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource);
+            graphLockOperation.unlockComponent(componentId, nodeType);
         }
 
     }
 
-    private void convertProperty(PropertyDefinition newPropertyDefinition, Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes) {
-        ToscaPropertyType type = getType(newPropertyDefinition.getType());
-        if (type != null) {
-            String innerType = null;
-            SchemaDefinition schema = newPropertyDefinition.getSchema();
-            if (schema != null && schema.getProperty() != null) {
-                innerType = schema.getProperty().getType();
-            }
-            if (newPropertyDefinition.getDefaultValue() != null) {
-                newPropertyDefinition.setDefaultValue(
-                        type.getConverter().convert(
-                                newPropertyDefinition.getDefaultValue(), innerType, allDataTypes.left().value()));
-            }
-        }
-    }
-
     /**
-     * Get property of resource
+     * Get property of component
      *
-     * @param resourceId
+     * @param componentId
      * @param propertyId
      * @param userId
      * @return either properties or response format
      */
-    public Either<Entry<String, PropertyDefinition>, ResponseFormat> getProperty(String resourceId, String propertyId, String userId) {
+
+    public Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> getComponentProperty(String componentId, String propertyId, String userId) {
 
         validateUserExists(userId, "create Component Instance", false);
         // Get the resource from DB
-        Either<Resource, StorageOperationStatus> status =  toscaOperationFacade.getToscaElement(resourceId);
+        Either<Component, StorageOperationStatus> status =
+            toscaOperationFacade.getToscaElement(componentId);
         if (status.isRight()) {
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
         }
-        Resource resource = status.left().value();
-
-        // verify property exist in resource
-        List<PropertyDefinition> properties = resource.getProperties();
-        if (properties == null) {
+        Component component = status.left().value();
+        List<PropertyDefinition> properties = component.getProperties();
+        if(CollectionUtils.isEmpty(properties)) {
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, ""));
         }
-        for (PropertyDefinition property : properties) {
-            if (property.getUniqueId().equals(propertyId) ) {
-                Map<String, PropertyDefinition> propMap = new HashMap<>();
-                propMap.put(property.getName(), property);
-                return Either.left(propMap.entrySet().iterator().next());
+
+        for(PropertyDefinition property : properties) {
+            if(property.getUniqueId().equals(propertyId)) {
+                return Either.left(new EntryData<>(property.getName(), property));
             }
         }
         return Either.right(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, ""));
     }
 
+
+    public Either<List<PropertyDefinition>, ResponseFormat> getPropertiesList(String componentId,
+                                                                              String userId) {
+        validateUserExists(userId, "create Component Instance", false);
+
+        // Get the resource from DB
+        ComponentParametersView filter = new ComponentParametersView(true);
+        filter.setIgnoreProperties(false);
+        Either<Component, StorageOperationStatus> status =
+            toscaOperationFacade.getToscaElement(componentId);
+        if (status.isRight()) {
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
+        }
+        Component component = status.left().value();
+        List<PropertyDefinition> properties = component.getProperties();
+
+        return Either.left(properties);
+    }
+
+
     /**
-     * delete property of resource from graph
+     * delete property of component from graph
      *
-     * @param resourceId
+     * @param componentId
      * @param propertyId
      * @param userId
      * @return either properties or response format
      */
-    public Either<Entry<String, PropertyDefinition>, ResponseFormat> deleteProperty(String resourceId, String propertyId, String userId) {
 
-        Either<Entry<String, PropertyDefinition>, ResponseFormat> result = null;
+    public Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> deletePropertyFromComponent(String componentId, String propertyId, String userId) {
+
+        Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> result = null;
 
         validateUserExists(userId, "delete Property", false);
 
-        StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource);
+        // Get the resource from DB
+        Either<Component, StorageOperationStatus> getComponentRes = toscaOperationFacade.getToscaElement(componentId);
+        if (getComponentRes.isRight()) {
+            result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
+            return result;
+        }
+        Component component = getComponentRes.left().value();
+        NodeTypeEnum nodeType = component.getComponentType().getNodeType();
+        StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType);
         if (!lockResult.equals(StorageOperationStatus.OK)) {
-            BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId);
+            BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, nodeType.name().toLowerCase(),
+                    componentId);
             result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
             return result;
         }
 
         try {
-
-            // Get the resource from DB
-            Either<Resource, StorageOperationStatus> getResourceRes = toscaOperationFacade.getToscaElement(resourceId);
-            if (getResourceRes.isRight()) {
-                result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
-                return result;
-            }
-            Resource resource = getResourceRes.left().value();
-
             // verify that resource is checked-out and the user is the last
             // updater
-            if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) {
+            if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) {
                 result = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
                 return result;
             }
 
             // verify property exist in resource
-            Either<Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty = getProperty(resourceId, propertyId, userId);
+            Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty =
+                getComponentProperty(componentId, propertyId, userId);
             if (statusGetProperty.isRight()) {
                 result = Either.right(statusGetProperty.right().value());
                 return result;
             }
 
-            StorageOperationStatus status = toscaOperationFacade.deletePropertyOfResource(resource, statusGetProperty.left().value().getKey());
+            Map.Entry<String, PropertyDefinition> propertyDefinitionEntry = statusGetProperty.left().value();
+
+            // verify that the property is not used by operation
+            if (isPropertyUsedByOperation(component, propertyDefinitionEntry.getValue())) {
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus
+                    .PROPERTY_USED_BY_OPERATION));
+            }
+
+            StorageOperationStatus status =
+                toscaOperationFacade.deletePropertyOfComponent(component, propertyDefinitionEntry.getKey());
             if (status != StorageOperationStatus.OK) {
-                result = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(status), resource.getName()));
+                result = Either.right(componentsUtils.getResponseFormat(componentsUtils
+                    .convertFromStorageResponse(status), component.getName()));
                 return result;
             }
-            result = Either.left(statusGetProperty.left().value());
+            result = Either.left(propertyDefinitionEntry);
             return result;
 
         } finally {
             commitOrRollback(result);
             // unlock component
-            graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource);
+            graphLockOperation.unlockComponent(componentId, nodeType);
+        }
+    }
+
+    public boolean isPropertyUsedByOperation(Component component,
+                                             PropertyDefinition propertyDefinitionEntry) {
+
+        // Component's own interfaces
+        Map<String, InterfaceDefinition> interfaces = component.getInterfaces();
+        if(MapUtils.isNotEmpty(interfaces)){
+          for(Map.Entry<String, InterfaceDefinition> interfaceEntry : interfaces.entrySet()) {
+            if (isPropertyExistInOperationInterface(propertyDefinitionEntry, interfaceEntry.getValue())) {
+              return true;
+            }
+          }
+        }
+
+        // Component's child's component interfaces
+        if(isPropertyUsedInCIInterfaces(component.getComponentInstancesInterfaces(), propertyDefinitionEntry)){
+            return true;
+        }
+
+        // Component's parent's component interfaces
+        Either<List<Component>, StorageOperationStatus> componentList = toscaOperationFacade.getParentComponents(component.getUniqueId());
+        if(componentList.isLeft()){
+            for (Component parentComponent : componentList.left().value()) {
+                if(isPropertyUsedInCIInterfaces(parentComponent.getComponentInstancesInterfaces(), propertyDefinitionEntry)){
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private boolean isPropertyUsedInCIInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces, PropertyDefinition propertyDefinitionEntry){
+        if(MapUtils.isNotEmpty(componentInstanceInterfaces)){
+            for (Entry<String, List<ComponentInstanceInterface>> interfaceEntry : componentInstanceInterfaces.entrySet()) {
+                for (ComponentInstanceInterface instanceInterface : interfaceEntry.getValue()) {
+                    if (isPropertyExistInOperationInterface(propertyDefinitionEntry, instanceInterface)) {
+                        return true;
+                    }
+                }
+            }
         }
+        return false;
+    }
+
+    private boolean isPropertyExistInOperationInterface(PropertyDefinition propertyDefinition,
+                                                        InterfaceDefinition interfaceDefinition) {
+        Map<String, OperationDataDefinition> operations =
+            interfaceDefinition.getOperations();
+        for(Map.Entry<String, OperationDataDefinition> operationEntry : operations
+            .entrySet()) {
+            Optional<OperationInputDefinition> inputWithDeletedPropertyCandidate =
+                getInputWithDeclaredProperty(propertyDefinition, operationEntry);
+
+            if(inputWithDeletedPropertyCandidate.isPresent()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Optional<OperationInputDefinition> getInputWithDeclaredProperty(PropertyDefinition propertyDefinition,
+                                                                            Map.Entry<String, OperationDataDefinition> operationEntry) {
+        ListDataDefinition<OperationInputDefinition> inputs =
+            operationEntry.getValue().getInputs();
+        List<OperationInputDefinition> operationInputsList =
+            Objects.isNull(inputs) ? null : inputs.getListToscaDataDefinition();
+
+        if(CollectionUtils.isEmpty(operationInputsList)) {
+            return Optional.empty();
+        }
+
+        return operationInputsList.stream().filter(input -> input.getInputId().equals(propertyDefinition.getUniqueId())).findAny();
     }
 
     /**
      * update property
      *
-     * @param resourceId
+     * @param componentId
      * @param propertyId
      * @param newPropertyDefinition
      * @param userId
      * @return either properties or response format
      */
-    public Either<EntryData<String, PropertyDefinition>, ResponseFormat> updateProperty(String resourceId, String propertyId, PropertyDefinition newPropertyDefinition, String userId) {
+
+    public Either<EntryData<String, PropertyDefinition>, ResponseFormat> updateComponentProperty(String componentId,
+                                                                        String propertyId,
+                                                                        PropertyDefinition newPropertyDefinition,
+                                                                        String userId) {
 
         Either<EntryData<String, PropertyDefinition>, ResponseFormat> result = null;
 
-        Either<Resource, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(resourceId);
+        Either<Component, StorageOperationStatus> status = toscaOperationFacade.getToscaElement(
+                componentId);
         if (status.isRight()) {
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, ""));
         }
-        Resource resource = status.left().value();
+        Component component = status.left().value();
+        NodeTypeEnum nodeType = component.getComponentType().getNodeType();
 
-        if (!ComponentValidationUtils.canWorkOnResource(resource, userId)) {
+        if (!ComponentValidationUtils.canWorkOnComponent(component, userId)) {
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
         }
 
-        StorageOperationStatus lockResult = graphLockOperation.lockComponent(resourceId, NodeTypeEnum.Resource);
+        StorageOperationStatus lockResult = graphLockOperation.lockComponent(componentId, nodeType);
         if (!lockResult.equals(StorageOperationStatus.OK)) {
-            BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, NodeTypeEnum.Resource.name().toLowerCase(), resourceId);
+            BeEcompErrorManager.getInstance().logBeFailedLockObjectError(CREATE_PROPERTY, nodeType.name().toLowerCase(),
+                    componentId);
             result = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
             return result;
         }
 
         try {
-            Either<Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty = getProperty(resourceId, propertyId, userId);
+            Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> statusGetProperty =
+                getComponentProperty(componentId, propertyId, userId);
             if (statusGetProperty.isRight()) {
                 result = Either.right(statusGetProperty.right().value());
                 return result;
             }
             String propertyName = statusGetProperty.left().value().getKey();
 
-            Either<Map<String, DataTypeDefinition>, ResponseFormat> allDataTypes = getAllDataTypes(applicationDataTypeCache);
-            if (allDataTypes.isRight()) {
-                result = Either.right(allDataTypes.right().value());
-                return result;
-            }
-            Map<String, DataTypeDefinition> dataTypes = allDataTypes.left().value();
-
-            Either<Boolean, ResponseFormat> defaultValuesValidation = validatePropertyDefaultValue(newPropertyDefinition, dataTypes);
-            if (defaultValuesValidation.isRight()) {
-                result = Either.right(defaultValuesValidation.right().value());
-                return result;
-            }
-
-            Either<PropertyDefinition, StorageOperationStatus> either = handleProperty(newPropertyDefinition, dataTypes);
-            if (either.isRight()) {
-                log.debug("Problem while updating property with id {}. Reason - {}", propertyId, either.right().value());
-                result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName()));
-                return result;
-            }
-
-
-            either = toscaOperationFacade.updatePropertyOfResource(resource, newPropertyDefinition);
+            Either<PropertyDefinition, StorageOperationStatus> either =
+                toscaOperationFacade.updatePropertyOfComponent(component, newPropertyDefinition);
             if (either.isRight()) {
-                result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(either.right().value()), resource.getName()));
+                result = Either.right(componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(either.right().value()), component.getName()));
                 return result;
             }
 
@@ -342,18 +452,30 @@ public class PropertyBusinessLogic extends BaseBusinessLogic {
 
         } finally {
             commitOrRollback(result);
-            graphLockOperation.unlockComponent(resourceId, NodeTypeEnum.Resource);
+            graphLockOperation.unlockComponent(componentId, nodeType);
         }
 
     }
 
+    private boolean isPropertyExistInComponent(List<PropertyDefinition> properties, String propertyName) {
+        if(CollectionUtils.isEmpty(properties)) {
+            return false;
+        }
+
+        Optional<PropertyDefinition> propertyCandidate =
+            properties.stream().filter(property -> property.getName().equals(propertyName))
+                .findAny();
+
+        return propertyCandidate.isPresent();
+    }
+
     private boolean isPropertyExist(List<PropertyDefinition> properties, String resourceUid, String propertyName, String propertyType) {
         boolean result = false;
         if (!CollectionUtils.isEmpty(properties)) {
             for (PropertyDefinition propertyDefinition : properties) {
 
                 if ( propertyDefinition.getName().equals(propertyName) &&
-                        (propertyDefinition.getParentUniqueId().equals(resourceUid) || !propertyDefinition.getType().equals(propertyType)) ) {
+                    (propertyDefinition.getParentUniqueId().equals(resourceUid) || !propertyDefinition.getType().equals(propertyType)) ) {
                     result = true;
                     break;
                 }
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclarator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/property/ComponentPropertyDeclarator.java
new file mode 100644 (file)
index 0000000..7f49e38
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.be.components.property;
+
+import fj.data.Either;
+import org.apache.commons.collections.CollectionUtils;
+import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
+import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstanceProperty;
+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 java.util.Optional;
+
+@org.springframework.stereotype.Component
+public class ComponentPropertyDeclarator extends DefaultPropertyDeclarator<Component, PropertyDataDefinition> {
+
+  private ToscaOperationFacade toscaOperationFacade;
+  PropertyBusinessLogic propertyBL;
+
+
+  public ComponentPropertyDeclarator(ComponentsUtils componentsUtils,
+                                     PropertyOperation propertyOperation,
+                                     ToscaOperationFacade toscaOperationFacade,
+                                     PropertyBusinessLogic propertyBL) {
+    super(componentsUtils, propertyOperation);
+    this.toscaOperationFacade = toscaOperationFacade;
+    this.propertyBL = propertyBL;
+  }
+
+  @Override
+  PropertyDataDefinition createDeclaredProperty(PropertyDataDefinition prop) {
+    return new PropertyDataDefinition(prop);
+  }
+
+  @Override
+  Either<?, StorageOperationStatus> updatePropertiesValues(Component component,
+                                                           String propertiesOwnerId,
+                                                           List<PropertyDataDefinition> properties) {
+    if(CollectionUtils.isNotEmpty(properties)) {
+      for(PropertyDataDefinition property : properties) {
+        Either<PropertyDefinition, StorageOperationStatus>
+            storageStatus = toscaOperationFacade
+            .updatePropertyOfComponent(component, new PropertyDefinition(property));
+        if(storageStatus.isRight()) {
+          return Either.right(storageStatus.right().value());
+        }
+      }
+    }
+    return Either.left(properties);
+  }
+
+  @Override
+  Optional<Component> resolvePropertiesOwner(Component component, String propertiesOwnerId) {
+    return Optional.of( component);
+  }
+
+  @Override
+  void addPropertiesListToInput(PropertyDataDefinition declaredProp,
+                                InputDefinition input) {
+
+    List<ComponentInstanceProperty> propertiesList = input.getProperties();
+    if(propertiesList == null) {
+      propertiesList = new ArrayList<>(); // adding the property with the new value for UI
+    }
+    propertiesList.add(new ComponentInstanceProperty(declaredProp));
+    input.setProperties(propertiesList);
+  }
+
+  @Override
+  public StorageOperationStatus unDeclarePropertiesAsInputs(Component component,
+                                                            InputDefinition input) {
+    PropertyDefinition propertyDefinition = new PropertyDefinition(input);
+
+    if(propertyBL.isPropertyUsedByOperation(component, propertyDefinition)) {
+      return StorageOperationStatus.DECLARED_INPUT_USED_BY_OPERATION;
+    }
+
+    Optional<PropertyDefinition> propertyToUpdateCandidate =
+        getDeclaredPropertyByInputId(component, input.getUniqueId());
+
+    if(propertyToUpdateCandidate.isPresent()) {
+      PropertyDefinition propertyToUpdate = propertyToUpdateCandidate.get();
+      return unDeclareInput(component, input, propertyToUpdate);
+    }
+
+
+    return StorageOperationStatus.OK;
+  }
+
+  private StorageOperationStatus unDeclareInput(Component component,
+                                                InputDefinition input,
+                                                PropertyDefinition propertyToUpdate) {
+    prepareValueBeforeDelete(input, propertyToUpdate, Collections.emptyList());
+    propertyToUpdate.setValue(input.getDefaultValue());
+    Either<PropertyDefinition, StorageOperationStatus> status = toscaOperationFacade
+        .updatePropertyOfComponent(component, propertyToUpdate);
+    if(status.isRight()) {
+      return status.right().value();
+    }
+
+    return StorageOperationStatus.OK;
+  }
+
+  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();
+  }
+}
index a5ba000..437ae2d 100644 (file)
@@ -87,20 +87,44 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
     }
 
     private InputDefinition createInput(String componentId, PROPERTYOWNER propertiesOwner, ComponentInstancePropInput propInput, PropertyDataDefinition prop) {
-        String generatedInputName = generateInputName(propertiesOwner.getNormalizedName(), propInput);
+        String generatedInputName = generateInputName(propertiesOwner instanceof
+                Service ? null : propertiesOwner.getNormalizedName(),
+            propInput);
         return createInputFromProperty(componentId, propertiesOwner, generatedInputName, propInput, prop);
     }
 
     private String generateInputName(String inputName, ComponentInstancePropInput propInput) {
+        String declaredInputName = inputName;
         String[] parsedPropNames = propInput.getParsedPropNames();
+
         if(parsedPropNames != null){
-            for(String str: parsedPropNames){
-                inputName += "_"  + str;
-            }
+            declaredInputName = handleInputName(inputName, parsedPropNames);
         } else {
-            inputName += "_"  + propInput.getName();
+            String[] propName = {propInput.getName()};
+            declaredInputName = handleInputName(inputName, propName);
         }
-        return inputName;
+
+        return declaredInputName;
+    }
+
+    private String handleInputName(String inputName, String[] parsedPropNames) {
+        String prefix;
+        int startingIndex;
+
+        if(Objects.isNull(inputName)) {
+            prefix = parsedPropNames[0];
+            startingIndex = 1;
+        } else {
+            prefix = inputName;
+            startingIndex = 0;
+        }
+
+        while(startingIndex < parsedPropNames.length){
+            prefix += "_"  + parsedPropNames[startingIndex];
+            startingIndex ++;
+        }
+
+        return prefix;
     }
 
     private PropertyDataDefinition resolveProperty(List<PROPERTYTYPE> propertiesToCreate, ComponentInstancePropInput propInput) {
@@ -131,14 +155,20 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
         input.setPropertyId(propInput.getUniqueId());
         input.setValue(null);
         changePropertyValueToGetInputValue(inputName, parsedPropNames, input, prop, complexProperty);
-        ((IComponentInstanceConnectedElement)prop).setComponentInstanceId(propertiesOwner.getUniqueId());
-        ((IComponentInstanceConnectedElement)prop).setComponentInstanceName(propertiesOwner.getName());
+
+        if(prop instanceof IComponentInstanceConnectedElement) {
+            ((IComponentInstanceConnectedElement) prop)
+                .setComponentInstanceId(propertiesOwner.getUniqueId());
+            ((IComponentInstanceConnectedElement) prop)
+                .setComponentInstanceName(propertiesOwner.getName());
+        }
         return input;
     }
 
     private void changePropertyValueToGetInputValue(String inputName, String[] parsedPropNames, InputDefinition input, PropertyDataDefinition prop, boolean complexProperty) {
         JSONObject jobject = new JSONObject();
-        if(prop.getValue() == null || prop.getValue().isEmpty()){
+        String value = (String) prop.getValue();
+        if(value == null || value.isEmpty()){
             if(complexProperty){
 
                 jobject = createJSONValueForProperty(parsedPropNames.length -1, parsedPropNames, jobject, inputName);
@@ -153,7 +183,7 @@ public abstract class DefaultPropertyDeclarator<PROPERTYOWNER extends Properties
 
         }else{
 
-            String value = prop.getValue();
+            //String value = value;
             Object objValue =  new Yaml().load(value);
             if( objValue instanceof Map || objValue  instanceof List){
                 if(!complexProperty){
index 937e2cc..babddc4 100644 (file)
@@ -22,14 +22,21 @@ public class PropertyDeclarationOrchestrator {
     private ComponentInstancePropertyDeclarator componentInstancePropertyDeclarator;
     private PolicyPropertyDeclarator policyPropertyDeclarator;
     private GroupPropertyDeclarator groupPropertyDeclarator;
+    private ComponentPropertyDeclarator servicePropertyDeclarator;
     private List<PropertyDeclarator> propertyDeclarators;
 
-    public PropertyDeclarationOrchestrator(ComponentInstanceInputPropertyDeclarator componentInstanceInputPropertyDeclarator, ComponentInstancePropertyDeclarator componentInstancePropertyDeclarator, PolicyPropertyDeclarator policyPropertyDeclarator, GroupPropertyDeclarator groupPropertyDeclarator) {
+    public PropertyDeclarationOrchestrator(
+        ComponentInstanceInputPropertyDeclarator componentInstanceInputPropertyDeclarator,
+        ComponentInstancePropertyDeclarator componentInstancePropertyDeclarator,
+        PolicyPropertyDeclarator policyPropertyDeclarator,
+        GroupPropertyDeclarator groupPropertyDeclarator,
+        ComponentPropertyDeclarator servicePropertyDeclarator) {
         this.componentInstanceInputPropertyDeclarator = componentInstanceInputPropertyDeclarator;
         this.componentInstancePropertyDeclarator = componentInstancePropertyDeclarator;
         this.policyPropertyDeclarator = policyPropertyDeclarator;
         this.groupPropertyDeclarator = groupPropertyDeclarator;
-        propertyDeclarators = Arrays.asList(componentInstanceInputPropertyDeclarator, componentInstancePropertyDeclarator, policyPropertyDeclarator, groupPropertyDeclarator);
+        this.servicePropertyDeclarator = servicePropertyDeclarator;
+        propertyDeclarators = Arrays.asList(componentInstanceInputPropertyDeclarator, componentInstancePropertyDeclarator, policyPropertyDeclarator, groupPropertyDeclarator, servicePropertyDeclarator);
     }
 
     public Either<List<InputDefinition>, StorageOperationStatus> declarePropertiesToInputs(Component component, ComponentInstInputsMap componentInstInputsMap) {
@@ -64,6 +71,9 @@ public class PropertyDeclarationOrchestrator {
         if (isNotEmpty(componentInstInputsMap.getGroupProperties())) {
             return groupPropertyDeclarator;
         }
+        if(isNotEmpty(componentInstInputsMap.getServiceProperties())) {
+            return servicePropertyDeclarator;
+        }
         throw new IllegalStateException("there are no properties selected for declaration");
 
     }
index 5b8d6dc..4502012 100644 (file)
@@ -23,8 +23,27 @@ package org.openecomp.sdc.be.servlets;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
 import fj.data.Either;
-import org.openecomp.sdc.be.components.impl.*;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ElementBusinessLogic;
+import org.openecomp.sdc.be.components.impl.GroupBusinessLogic;
+import org.openecomp.sdc.be.components.impl.InterfaceOperationBusinessLogic;
+import org.openecomp.sdc.be.components.impl.MonitoringBusinessLogic;
+import org.openecomp.sdc.be.components.impl.PolicyBusinessLogic;
+import org.openecomp.sdc.be.components.impl.PolicyTypeBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ProductBusinessLogic;
+import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
 import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
 import org.openecomp.sdc.be.components.scheduledtasks.ComponentsCleanBusinessLogic;
 import org.openecomp.sdc.be.components.upgrade.UpgradeBusinessLogic;
@@ -35,8 +54,11 @@ import org.openecomp.sdc.be.ecomp.converters.AssetMetadataConverter;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
 import org.openecomp.sdc.be.model.PropertyConstraint;
+import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintJacksonDeserializer;
+import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
 import org.openecomp.sdc.be.user.UserBusinessLogic;
 import org.openecomp.sdc.common.api.Constants;
@@ -51,8 +73,12 @@ import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.function.Supplier;
 
 public class BeGenericServlet extends BasicServlet {
@@ -79,8 +105,8 @@ public class BeGenericServlet extends BasicServlet {
 
     private static Response buildOkResponseStatic(Object entity) {
         return Response.status(Response.Status.OK)
-                .entity(entity)
-                .build();
+            .entity(entity)
+            .build();
     }
 
     protected Response buildOkResponse(ResponseFormat errorResponseWrapper, Object entity) {
@@ -215,8 +241,8 @@ public class BeGenericServlet extends BasicServlet {
     protected String getContentDispositionValue(String artifactFileName) {
         return new StringBuilder().append("attachment; filename=\"").append(artifactFileName).append("\"").toString();
     }
-    
-    
+
+
 
     protected ComponentBusinessLogic getComponentBL(ComponentTypeEnum componentTypeEnum, ServletContext context) {
         ComponentBusinessLogic businessLogic;
@@ -243,8 +269,8 @@ public class BeGenericServlet extends BasicServlet {
     <T> void convertJsonToObjectOfClass(String json, Wrapper<T> policyWrapper, Class<T> clazz, Wrapper<Response> errorWrapper) {
         T object = null;
         ObjectMapper mapper = new ObjectMapper()
-                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
-                .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
+            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+            .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
         try {
             log.trace("Starting to convert json to object. Json=\n{}", json);
 
@@ -266,4 +292,143 @@ public class BeGenericServlet extends BasicServlet {
             errorWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)));
         }
     }
+
+    protected Either<Map<String, PropertyDefinition>, ActionStatus> getPropertyModel(String componentId,
+                                                                                     String data) {
+        JSONParser parser = new JSONParser();
+        JSONObject root;
+        try {
+            Map<String, PropertyDefinition> properties = new HashMap<String, PropertyDefinition>();
+            root = (JSONObject) parser.parse(data);
+
+            Set entrySet = root.entrySet();
+            Iterator iterator = entrySet.iterator();
+            while (iterator.hasNext()) {
+                Entry next = (Entry) iterator.next();
+                String propertyName = (String) next.getKey();
+                JSONObject value = (JSONObject) next.getValue();
+                String jsonString = value.toJSONString();
+                Either<PropertyDefinition, ActionStatus> convertJsonToObject = convertJsonToObject(jsonString, PropertyDefinition.class);
+                if (convertJsonToObject.isRight()) {
+                    return Either.right(convertJsonToObject.right().value());
+                }
+                PropertyDefinition propertyDefinition = convertJsonToObject.left().value();
+                String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(componentId, (String) propertyName);
+                propertyDefinition.setUniqueId(uniqueId);
+                properties.put(propertyName, propertyDefinition);
+            }
+
+            return Either.left(properties);
+        } catch (ParseException e) {
+            log.info("Property conetnt is invalid - {}", data);
+            return Either.right(ActionStatus.INVALID_CONTENT);
+        }
+    }
+
+    protected Either<Map<String, PropertyDefinition>, ActionStatus> getPropertiesListForUpdate(String data) {
+
+        Map<String, PropertyDefinition> properties = new HashMap<>();
+        JSONParser parser = new JSONParser();
+        JSONArray jsonArray;
+
+        try {
+            jsonArray = (JSONArray) parser.parse(data);
+            for (Object jsonElement : jsonArray) {
+                String propertyAsString = jsonElement.toString();
+                Either<PropertyDefinition, ActionStatus> convertJsonToObject = convertJsonToObject(propertyAsString, PropertyDefinition.class);
+
+                if (convertJsonToObject.isRight()) {
+                    return Either.right(convertJsonToObject.right().value());
+                }
+
+                PropertyDefinition propertyDefinition = convertJsonToObject.left().value();
+                properties.put(propertyDefinition.getName(), propertyDefinition);
+            }
+
+            return Either.left(properties);
+        } catch (Exception e) {
+            log.info("Property content is invalid - {}", data);
+            return Either.right(ActionStatus.INVALID_CONTENT);
+        }
+
+    }
+
+
+    protected String propertyToJson(Map.Entry<String, PropertyDefinition> property) {
+        JSONObject root = new JSONObject();
+        String propertyName = property.getKey();
+        PropertyDefinition propertyDefinition = property.getValue();
+        JSONObject propertyDefinitionO = getPropertyDefinitionJSONObject(propertyDefinition);
+        root.put(propertyName, propertyDefinitionO);
+        propertyDefinition.getType();
+        return root.toString();
+    }
+
+    private JSONObject getPropertyDefinitionJSONObject(PropertyDefinition propertyDefinition) {
+
+        Either<String, ActionStatus> either = convertObjectToJson(propertyDefinition);
+        if (either.isRight()) {
+            return new JSONObject();
+        }
+        String value = either.left().value();
+        try {
+            JSONObject root = (JSONObject) new JSONParser().parse(value);
+            return root;
+        } catch (ParseException e) {
+            log.info("failed to convert input to json");
+            log.debug("failed to convert to json", e);
+            return new JSONObject();
+        }
+
+    }
+
+    protected  <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) {
+        T t = null;
+        Type constraintType = new TypeToken<PropertyConstraint>() {
+        }.getType();
+        Gson
+            gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyOperation.PropertyConstraintDeserialiser()).create();
+        try {
+            log.trace("convert json to object. json=\n {}", data);
+            t = gson.fromJson(data, clazz);
+            if (t == null) {
+                log.info("object is null after converting from json");
+                return Either.right(ActionStatus.INVALID_CONTENT);
+            }
+        } catch (Exception e) {
+            // INVALID JSON
+            log.info("failed to convert from json");
+            log.debug("failed to convert from json", e);
+            return Either.right(ActionStatus.INVALID_CONTENT);
+        }
+        return Either.left(t);
+    }
+
+    private <T> Either<String, ActionStatus> convertObjectToJson(PropertyDefinition propertyDefinition) {
+        Type constraintType = new TypeToken<PropertyConstraint>() {
+        }.getType();
+        Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyOperation.PropertyConstraintSerialiser()).create();
+        try {
+            log.trace("convert object to json. propertyDefinition= {}", propertyDefinition);
+            String json = gson.toJson(propertyDefinition);
+            if (json == null) {
+                log.info("object is null after converting to json");
+                return Either.right(ActionStatus.INVALID_CONTENT);
+            }
+            return Either.left(json);
+        } catch (Exception e) {
+            // INVALID JSON
+            log.info("failed to convert to json");
+            log.debug("failed to convert fto json", e);
+            return Either.right(ActionStatus.INVALID_CONTENT);
+        }
+
+    }
+
+    protected PropertyBusinessLogic getPropertyBL(ServletContext context) {
+        WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
+        WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
+        PropertyBusinessLogic propertytBl = webApplicationContext.getBean(PropertyBusinessLogic.class);
+        return propertytBl;
+    }
 }
index 042303e..b5e2814 100644 (file)
@@ -1139,7 +1139,7 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet {
         return Either.left(requirementCapabilityRelDef);
     }
 
-    private <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) {
+    public  <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) {
         try {
             log.trace("convert json to object. json=\n {}", data);
             T t;
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentPropertyServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentPropertyServlet.java
new file mode 100644 (file)
index 0000000..0edce61
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.be.servlets;
+
+import com.jcabi.aspects.Loggable;
+import fj.data.Either;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
+import org.openecomp.sdc.be.config.BeEcompErrorManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.resources.data.EntryData;
+import org.openecomp.sdc.common.api.Constants;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Singleton;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.List;
+import java.util.Map;
+
+@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
+@Path("/v1/catalog")
+@Api(value = "Component Property Servlet", description = "Property Servlet - used to create properties in Service and Resource")
+@Singleton
+public class ComponentPropertyServlet extends BeGenericServlet {
+
+  private static final Logger log = LoggerFactory.getLogger(ComponentPropertyServlet.class);
+
+  @POST
+  @Path("services/{serviceId}/properties")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Create Service Property", httpMethod = "POST", notes = "Returns created service property", response = Response.class)
+  @ApiResponses(value = { @ApiResponse(code = 201, message = "Service property created"),
+      @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+      @ApiResponse(code = 409, message = "Service property already exist") })
+  public Response createPropertyInService(@ApiParam(value = "service id to update with new property", required = true) @PathParam("serviceId") final String serviceId,
+                                 @ApiParam(value = "Service property to be created", required = true) String data,
+                                 @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    return createProperty(serviceId, data, request, userId);
+  }
+
+  @POST
+  @Path("resources/{resourceId}/properties")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Create Resource Property", httpMethod = "POST", notes = "Returns created service property", response = Response.class)
+  @ApiResponses(value = { @ApiResponse(code = 201, message = "Resource property created"),
+          @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+          @ApiResponse(code = 409, message = "Resource property already exist") })
+  public Response createPropertyInResource(@ApiParam(value = "Resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId,
+                                           @ApiParam(value = "Resource property to be created", required = true) String data,
+                                           @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    return createProperty(resourceId, data, request, userId);
+  }
+
+
+  @GET
+  @Path("services/{serviceId}/properties/{propertyId}")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Get Service Property", httpMethod = "GET", notes = "Returns property of service", response = Response.class)
+  @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+          @ApiResponse(code = 404, message = "Service property not found") })
+  public Response getPropertyInService(@ApiParam(value = "service id of property", required = true)
+                                       @PathParam("serviceId") final String serviceId, @ApiParam(value = "property id to get", required = true) @PathParam("propertyId") final String propertyId,
+                                       @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    return getProperty(serviceId, propertyId, request, userId);
+  }
+
+  @GET
+  @Path("resources/{resourceId}/properties/{propertyId}")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Get Resource Property", httpMethod = "GET", notes = "Returns property of resource", response = Response.class)
+  @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+          @ApiResponse(code = 404, message = "Resource property not found") })
+  public Response getPropertyInResource(@ApiParam(value = "resource id of property", required = true)
+                                       @PathParam("resourceId") final String resourceId, @ApiParam(value = "property id to get", required = true) @PathParam("propertyId") final String propertyId,
+                                       @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    return getProperty(resourceId, propertyId, request, userId);
+  }
+
+  @GET
+  @Path("services/{serviceId}/properties")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Get Service Property", httpMethod = "GET", notes = "Returns property list of service", response = Response.class)
+  @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+      @ApiResponse(code = 404, message = "Service property not found") })
+  public Response getPropertyListInService(@ApiParam(value = "service id of property", required = true) @PathParam("serviceId") final String serviceId,
+                                  @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    return getPropertyList(serviceId, request, userId);
+  }
+
+  @GET
+  @Path("resources/{resourceId}/properties")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Get Resource Property", httpMethod = "GET", notes = "Returns property list of resource", response = Response.class)
+  @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+          @ApiResponse(code = 404, message = "Resource property not found") })
+  public Response getPropertyListInResource(@ApiParam(value = "resource id of property", required = true) @PathParam("resourceId") final String resourceId,
+                                           @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    return getPropertyList(resourceId, request, userId);
+  }
+
+  @DELETE
+  @Path("services/{serviceId}/properties/{propertyId}")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Delete Service Property", httpMethod = "DELETE", notes = "Returns deleted property", response = Response.class)
+  @ApiResponses(value = { @ApiResponse(code = 204, message = "deleted property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+          @ApiResponse(code = 404, message = "Service property not found") })
+  public Response deletePropertyInService(@ApiParam(value = "service id of property", required = true) @PathParam("serviceId") final String serviceId,
+                                          @ApiParam(value = "Property id to delete", required = true) @PathParam("propertyId") final String propertyId, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    return deleteProperty(serviceId, propertyId, request, userId);
+  }
+
+  @DELETE
+  @Path("resources/{resourceId}/properties/{propertyId}")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Delete Resource Property", httpMethod = "DELETE", notes = "Returns deleted property", response = Response.class)
+  @ApiResponses(value = { @ApiResponse(code = 204, message = "deleted property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+          @ApiResponse(code = 404, message = "Resource property not found") })
+  public Response deletePropertyInResource(@ApiParam(value = "resource id of property", required = true) @PathParam("resourceId") final String resourceId,
+                                          @ApiParam(value = "Property id to delete", required = true) @PathParam("propertyId") final String propertyId, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    return deleteProperty(resourceId, propertyId, request, userId);
+  }
+
+  @PUT
+  @Path("services/{serviceId}/properties")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Update Service Property", httpMethod = "PUT", notes = "Returns updated property", response = Response.class)
+  @ApiResponses(value = { @ApiResponse(code = 200, message = "Service property updated"),
+      @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content") })
+  public Response updatePropertyInService(@ApiParam(value = "service id to update with new property", required = true) @PathParam("serviceId") final String serviceId,
+                                 @ApiParam(value = "Service property to update", required = true) String data, @Context final HttpServletRequest request,
+                                 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    return updateProperty(serviceId, data, request, userId);
+  }
+
+  @PUT
+  @Path("resources/{resourceId}/properties")
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation(value = "Update Resource Property", httpMethod = "PUT", notes = "Returns updated property", response = Response.class)
+  @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource property updated"),
+          @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content") })
+  public Response updatePropertyInResource(@ApiParam(value = "resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId,
+                                          @ApiParam(value = "Resource property to update", required = true) String data, @Context final HttpServletRequest request,
+                                          @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+    return updateProperty(resourceId, data, request, userId);
+  }
+
+  private Response createProperty(String componentId, String data,  HttpServletRequest request,String userId) {
+    ServletContext context = request.getSession().getServletContext();
+
+    String url = request.getMethod() + " " + request.getRequestURI();
+    log.debug("Start handle request of {} modifier id is {} data is {}", url, userId, data);
+
+    try{
+      Either<Map<String, PropertyDefinition>, ActionStatus> propertyDefinition =
+              getPropertyModel(componentId, data);
+      if (propertyDefinition.isRight()) {
+        ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(propertyDefinition.right().value());
+        return buildErrorResponse(responseFormat);
+      }
+
+      Map<String, PropertyDefinition> properties = propertyDefinition.left().value();
+      if (properties == null || properties.size() != 1) {
+        log.info("Property content is invalid - {}", data);
+        ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
+        return buildErrorResponse(responseFormat);
+      }
+
+      Map.Entry<String, PropertyDefinition> entry = properties.entrySet().iterator().next();
+      PropertyDefinition newPropertyDefinition = entry.getValue();
+      newPropertyDefinition.setParentUniqueId(componentId);
+      String propertyName = newPropertyDefinition.getName();
+
+      PropertyBusinessLogic propertyBL = getPropertyBL(context);
+      Either<EntryData<String, PropertyDefinition>, ResponseFormat> addPropertyEither =
+              propertyBL.addPropertyToComponent(componentId, propertyName, newPropertyDefinition, userId);
+
+      if(addPropertyEither.isRight()) {
+        return buildErrorResponse(addPropertyEither.right().value());
+      }
+
+      return buildOkResponse(newPropertyDefinition);
+
+    } catch (Exception e) {
+      BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Property");
+      log.debug("create property failed with exception", e);
+      ResponseFormat responseFormat =
+              getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+      return buildErrorResponse(responseFormat);
+    }
+  }
+
+
+  private Response updateProperty(String componentId, String data, HttpServletRequest request, String userId) {
+    ServletContext context = request.getSession().getServletContext();
+
+    String url = request.getMethod() + " " + request.getRequestURI();
+    log.debug("Start handle request of {}", url);
+
+    // get modifier id
+    User modifier = new User();
+    modifier.setUserId(userId);
+    log.debug("modifier id is {}", userId);
+//
+    try {
+      // convert json to PropertyDefinition
+
+      Either<Map<String, PropertyDefinition>, ActionStatus> propertiesListEither =
+          getPropertiesListForUpdate(data);
+      if (propertiesListEither.isRight()) {
+        ResponseFormat responseFormat =
+            getComponentsUtils().getResponseFormat(propertiesListEither.right().value());
+        return buildErrorResponse(responseFormat);
+      }
+      Map<String, PropertyDefinition> properties = propertiesListEither.left().value();
+      if (properties == null) {
+        log.info("Property content is invalid - {}", data);
+        ResponseFormat responseFormat =
+            getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
+        return buildErrorResponse(responseFormat);
+      }
+
+      // update property
+
+      PropertyBusinessLogic businessLogic = getPropertyBL(context);
+      for(PropertyDefinition propertyDefinition : properties.values()) {
+        Either<EntryData<String, PropertyDefinition>, ResponseFormat> status =
+            businessLogic.updateComponentProperty(
+                componentId, propertyDefinition.getUniqueId(), propertyDefinition, userId);
+        if (status.isRight()) {
+          log.info("Failed to update Property. Reason - ", status.right().value());
+          return buildErrorResponse(status.right().value());
+        }
+        EntryData<String, PropertyDefinition> property = status.left().value();
+        PropertyDefinition updatedPropertyDefinition = property.getValue();
+
+        log.debug("Property id {} updated successfully ", updatedPropertyDefinition.getUniqueId());
+      }
+
+      ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
+      return buildOkResponse(responseFormat, properties);
+
+    } catch (Exception e) {
+      BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Property");
+      log.debug("update property failed with exception", e);
+      ResponseFormat responseFormat =
+          getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+      return buildErrorResponse(responseFormat);
+
+    }
+  }
+
+  private Response getProperty(String componentId, String propertyId, HttpServletRequest request, String userId) {
+    ServletContext context = request.getSession().getServletContext();
+
+    String url = request.getMethod() + " " + request.getRequestURI();
+    log.debug("Start handle request of {} modifier id is {}", url, userId);
+
+    try {
+      PropertyBusinessLogic propertyBL = getPropertyBL(context);
+      Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> retrievedPropertyEither =
+              propertyBL.getComponentProperty(componentId, propertyId, userId);
+
+      if(retrievedPropertyEither.isRight()) {
+        return buildErrorResponse(retrievedPropertyEither.right().value());
+      }
+
+      return buildOkResponse(retrievedPropertyEither.left().value());
+
+    } catch (Exception e) {
+      BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Property");
+      log.debug("get property failed with exception", e);
+      ResponseFormat responseFormat =
+              getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+      return buildErrorResponse(responseFormat);
+    }
+  }
+  private Response getPropertyList(String componentId, HttpServletRequest request, String userId) {
+    ServletContext context = request.getSession().getServletContext();
+
+    String url = request.getMethod() + " " + request.getRequestURI();
+    log.debug("Start handle request of {} modifier id is {}", url, userId);
+
+    try {
+      PropertyBusinessLogic propertyBL = getPropertyBL(context);
+      Either<List<PropertyDefinition>, ResponseFormat> propertiesListEither =
+              propertyBL.getPropertiesList(componentId, userId);
+
+      if(propertiesListEither.isRight()) {
+        return buildErrorResponse(propertiesListEither.right().value());
+      }
+
+      return buildOkResponse(propertiesListEither.left().value());
+
+    } catch (Exception e) {
+      BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Property");
+      log.debug("get property failed with exception", e);
+      ResponseFormat responseFormat =
+              getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+      return buildErrorResponse(responseFormat);
+    }
+  }
+  private Response deleteProperty(String componentId, String propertyId, HttpServletRequest request, String userId) {
+    ServletContext context = request.getSession().getServletContext();
+
+    String url = request.getMethod() + " " + request.getRequestURI();
+    log.debug("Start handle request of {} modifier id is {}", url, userId);
+
+    try {
+
+      // delete the property
+      PropertyBusinessLogic businessLogic = getPropertyBL(context);
+      Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> status =
+              businessLogic.deletePropertyFromComponent(componentId, propertyId, userId);
+      if (status.isRight()) {
+        log.debug("Failed to delete Property. Reason - ", status.right().value());
+        return buildErrorResponse(status.right().value());
+      }
+      Map.Entry<String, PropertyDefinition> property = status.left().value();
+      String name = property.getKey();
+      PropertyDefinition propertyDefinition = property.getValue();
+
+      log.debug("Property {} deleted successfully with id {}", name, propertyDefinition.getUniqueId());
+      ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT);
+      return buildOkResponse(responseFormat, propertyToJson(property));
+
+    } catch (Exception e) {
+      BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Property");
+      log.debug("delete property failed with exception", e);
+      ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+      return buildErrorResponse(responseFormat);
+
+    }
+  }
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/PropertyServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/PropertyServlet.java
deleted file mode 100644 (file)
index 12d788d..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. 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.servlets;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-import com.jcabi.aspects.Loggable;
-import fj.data.Either;
-import io.swagger.annotations.*;
-import org.json.simple.JSONObject;
-import org.json.simple.parser.JSONParser;
-import org.json.simple.parser.ParseException;
-import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
-import org.openecomp.sdc.be.config.BeEcompErrorManager;
-import org.openecomp.sdc.be.dao.api.ActionStatus;
-import org.openecomp.sdc.be.impl.WebAppContextWrapper;
-import org.openecomp.sdc.be.model.PropertyConstraint;
-import org.openecomp.sdc.be.model.PropertyDefinition;
-import org.openecomp.sdc.be.model.User;
-import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintDeserialiser;
-import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintSerialiser;
-import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
-import org.openecomp.sdc.be.resources.data.EntryData;
-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;
-
-import javax.inject.Singleton;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.*;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
-@Path("/v1/catalog")
-@Api(value = "Resource Property Servlet", description = "Resource Property Servlet")
-@Singleton
-public class PropertyServlet extends BeGenericServlet {
-
-    private static final Logger log = Logger.getLogger(PropertyServlet.class.getName());
-
-    @POST
-    @Path("resources/{resourceId}/properties")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    @ApiOperation(value = "Create Resource Property", httpMethod = "POST", notes = "Returns created resource property", response = Response.class)
-    @ApiResponses(value = { @ApiResponse(code = 201, message = "Resource property created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
-            @ApiResponse(code = 409, message = "Resource property already exist") })
-    public Response createProperty(@ApiParam(value = "resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId, @ApiParam(value = "Resource property to be created", required = true) String data,
-            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
-
-        ServletContext context = request.getSession().getServletContext();
-
-        String url = request.getMethod() + " " + request.getRequestURI();
-        log.debug("Start handle request of {} modifier id is {} data is {}", url, userId, data);
-
-        try {
-            // convert json to PropertyDefinition
-            Either<Map<String, PropertyDefinition>, ActionStatus> either = getPropertyModel(resourceId, data);
-            if (either.isRight()) {
-                ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(either.right().value());
-                return buildErrorResponse(responseFormat);
-            }
-            Map<String, PropertyDefinition> properties = either.left().value();
-            if (properties == null || properties.size() != 1) {
-                log.info("Property conetnt is invalid - {}", data);
-                ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
-                return buildErrorResponse(responseFormat);
-            }
-            Entry<String, PropertyDefinition> entry = properties.entrySet().iterator().next();
-            String propertyName = entry.getKey();
-            PropertyDefinition newPropertyDefinition = entry.getValue();
-
-            // create the new property
-            PropertyBusinessLogic businessLogic = getPropertyBL(context);
-            Either<EntryData<String, PropertyDefinition>, ResponseFormat> status = businessLogic.createProperty(resourceId, propertyName, newPropertyDefinition, userId);
-            if (status.isRight()) {
-                log.info("Failed to create Property. Reason - ", status.right().value());
-                return buildErrorResponse(status.right().value());
-            }
-            EntryData<String, PropertyDefinition> property = status.left().value();
-            String name = property.getKey();
-            PropertyDefinition propertyDefinition = property.getValue();
-
-            log.debug("Property {} created successfully with id {}", name, propertyDefinition.getUniqueId());
-            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.CREATED);
-            return buildOkResponse(responseFormat, propertyToJson(property));
-
-        } catch (Exception e) {
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Property");
-            log.debug("create property failed with exception", e);
-            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
-            return buildErrorResponse(responseFormat);
-
-        }
-    }
-
-    @GET
-    @Path("resources/{resourceId}/properties/{propertyId}")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    @ApiOperation(value = "Create Resource Property", httpMethod = "GET", notes = "Returns property of resource", response = Response.class)
-    @ApiResponses(value = { @ApiResponse(code = 200, message = "property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
-            @ApiResponse(code = 404, message = "Resource property not found") })
-    public Response getProperty(@ApiParam(value = "resource id of property", required = true) @PathParam("resourceId") final String resourceId, @ApiParam(value = "proerty id to get", required = true) @PathParam("propertyId") final String propertyId,
-            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
-
-        ServletContext context = request.getSession().getServletContext();
-
-        String url = request.getMethod() + " " + request.getRequestURI();
-        log.debug("Start handle request of {}, modifier id is {}", url, userId);
-
-        try {
-
-            //
-            PropertyBusinessLogic businessLogic = getPropertyBL(context);
-            Either<Entry<String, PropertyDefinition>, ResponseFormat> status = businessLogic.getProperty(resourceId, propertyId, userId);
-
-            if (status.isRight()) {
-                log.info("Failed to get Property. Reason - ", status.right().value());
-                return buildErrorResponse(status.right().value());
-            }
-            Entry<String, PropertyDefinition> property = status.left().value();
-            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
-            return buildOkResponse(responseFormat, propertyToJson(property));
-        } catch (Exception e) {
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Property");
-            log.debug("get property failed with exception", e);
-            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
-            return buildErrorResponse(responseFormat);
-
-        }
-    }
-
-    @DELETE
-    @Path("resources/{resourceId}/properties/{propertyId}")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    @ApiOperation(value = "Create Resource Property", httpMethod = "DELETE", notes = "Returns deleted property", response = Response.class)
-    @ApiResponses(value = { @ApiResponse(code = 204, message = "deleted property"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
-            @ApiResponse(code = 404, message = "Resource property not found") })
-    public Response deleteProperty(@ApiParam(value = "resource id of property", required = true) @PathParam("resourceId") final String resourceId,
-            @ApiParam(value = "Property id to delete", required = true) @PathParam("propertyId") final String propertyId, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
-
-        ServletContext context = request.getSession().getServletContext();
-
-        String url = request.getMethod() + " " + request.getRequestURI();
-        log.debug("Start handle request of {} modifier id is {}", url, userId);
-
-        try {
-
-            // delete the property
-            PropertyBusinessLogic businessLogic = getPropertyBL(context);
-            Either<Entry<String, PropertyDefinition>, ResponseFormat> status = businessLogic.deleteProperty(resourceId, propertyId, userId);
-            if (status.isRight()) {
-                log.debug("Failed to delete Property. Reason - ", status.right().value());
-                return buildErrorResponse(status.right().value());
-            }
-            Entry<String, PropertyDefinition> property = status.left().value();
-            String name = property.getKey();
-            PropertyDefinition propertyDefinition = property.getValue();
-
-            log.debug("Property {} deleted successfully with id {}", name, propertyDefinition.getUniqueId());
-            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT);
-            return buildOkResponse(responseFormat, propertyToJson(property));
-
-        } catch (Exception e) {
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Property");
-            log.debug("delete property failed with exception", e);
-            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
-            return buildErrorResponse(responseFormat);
-
-        }
-    }
-
-    @PUT
-    @Path("resources/{resourceId}/properties/{propertyId}")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    @ApiOperation(value = "Update Resource Property", httpMethod = "PUT", notes = "Returns updated property", response = Response.class)
-    @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource property updated"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content") })
-    public Response updateProperty(@ApiParam(value = "resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId,
-            @ApiParam(value = "proerty id to update", required = true) @PathParam("propertyId") final String propertyId, @ApiParam(value = "Resource property to update", required = true) String data, @Context final HttpServletRequest request,
-            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
-
-        ServletContext context = request.getSession().getServletContext();
-
-        String url = request.getMethod() + " " + request.getRequestURI();
-        log.debug("Start handle request of {}", url);
-
-        // get modifier id
-        User modifier = new User();
-        modifier.setUserId(userId);
-        log.debug("modifier id is {}", userId);
-
-        try {
-            // convert json to PropertyDefinition
-            Either<Map<String, PropertyDefinition>, ActionStatus> either = getPropertyModel(resourceId, data);
-            if (either.isRight()) {
-                ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(either.right().value());
-                return buildErrorResponse(responseFormat);
-            }
-            Map<String, PropertyDefinition> properties = either.left().value();
-            if (properties == null || properties.size() != 1) {
-                log.info("Property conetnt is invalid - {}", data);
-                ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
-                return buildErrorResponse(responseFormat);
-            }
-            Entry<String, PropertyDefinition> entry = properties.entrySet().iterator().next();
-            PropertyDefinition newPropertyDefinition = entry.getValue();
-
-            // update property
-            PropertyBusinessLogic businessLogic = getPropertyBL(context);
-            Either<EntryData<String, PropertyDefinition>, ResponseFormat> status = businessLogic.updateProperty(resourceId, propertyId, newPropertyDefinition, userId);
-            if (status.isRight()) {
-                log.info("Failed to update Property. Reason - ", status.right().value());
-                return buildErrorResponse(status.right().value());
-            }
-            EntryData<String, PropertyDefinition> property = status.left().value();
-            PropertyDefinition propertyDefinition = property.getValue();
-
-            log.debug("Property id {} updated successfully ", propertyDefinition.getUniqueId());
-            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
-            return buildOkResponse(responseFormat, propertyToJson(property));
-
-        } catch (Exception e) {
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Property");
-            log.debug("update property failed with exception", e);
-            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
-            return buildErrorResponse(responseFormat);
-
-        }
-    }
-
-    private Either<Map<String, PropertyDefinition>, ActionStatus> getPropertyModel(String resourceId, String data) {
-        JSONParser parser = new JSONParser();
-        JSONObject root;
-        try {
-            Map<String, PropertyDefinition> properties = new HashMap<>();
-            root = (JSONObject) parser.parse(data);
-
-            Set entrySet = root.entrySet();
-            Iterator iterator = entrySet.iterator();
-            while (iterator.hasNext()) {
-                Entry next = (Entry) iterator.next();
-                String propertyName = (String) next.getKey();
-                JSONObject value = (JSONObject) next.getValue();
-                String jsonString = value.toJSONString();
-                Either<PropertyDefinition, ActionStatus> convertJsonToObject = convertJsonToObject(jsonString, PropertyDefinition.class);
-                if (convertJsonToObject.isRight()) {
-                    return Either.right(convertJsonToObject.right().value());
-                }
-                PropertyDefinition propertyDefinition = convertJsonToObject.left().value();
-                String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(resourceId, (String) propertyName);
-                propertyDefinition.setUniqueId(uniqueId);
-                properties.put(propertyName, propertyDefinition);
-            }
-
-            return Either.left(properties);
-        } catch (ParseException e) {
-            log.info("Property conetnt is invalid - {}", data);
-            return Either.right(ActionStatus.INVALID_CONTENT);
-        }
-    }
-
-    private String propertyToJson(Map.Entry<String, PropertyDefinition> property) {
-        JSONObject root = new JSONObject();
-        String propertyName = property.getKey();
-        PropertyDefinition propertyDefinition = property.getValue();
-        JSONObject propertyDefinitionO = getPropertyDefinitionJSONObject(propertyDefinition);
-        root.put(propertyName, propertyDefinitionO);
-        propertyDefinition.getType();
-        return root.toString();
-    }
-
-    private JSONObject getPropertyDefinitionJSONObject(PropertyDefinition propertyDefinition) {
-
-        Either<String, ActionStatus> either = convertObjectToJson(propertyDefinition);
-        if (either.isRight()) {
-            return new JSONObject();
-        }
-        String value = either.left().value();
-        try {
-            return (JSONObject) new JSONParser().parse(value);
-        } catch (ParseException e) {
-            log.info("failed to convert input to json");
-            log.debug("failed to convert to json", e);
-            return new JSONObject();
-        }
-
-    }
-
-    private <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) {
-        T t = null;
-        Type constraintType = new TypeToken<PropertyConstraint>() {
-        }.getType();
-        Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintDeserialiser()).create();
-        try {
-            log.trace("convert json to object. json=\n {}", data);
-            t = gson.fromJson(data, clazz);
-            if (t == null) {
-                log.info("object is null after converting from json");
-                return Either.right(ActionStatus.INVALID_CONTENT);
-            }
-        } catch (Exception e) {
-            // INVALID JSON
-            log.info("failed to convert from json");
-            log.debug("failed to convert from json", e);
-            return Either.right(ActionStatus.INVALID_CONTENT);
-        }
-        return Either.left(t);
-    }
-
-    private <T> Either<String, ActionStatus> convertObjectToJson(PropertyDefinition propertyDefinition) {
-        Type constraintType = new TypeToken<PropertyConstraint>() {
-        }.getType();
-        Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyConstraintSerialiser()).create();
-        try {
-            log.trace("convert object to json. propertyDefinition= {}", propertyDefinition);
-            String json = gson.toJson(propertyDefinition);
-            if (json == null) {
-                log.info("object is null after converting to json");
-                return Either.right(ActionStatus.INVALID_CONTENT);
-            }
-            return Either.left(json);
-        } catch (Exception e) {
-            // INVALID JSON
-            log.info("failed to convert to json");
-            log.debug("failed to convert fto json", e);
-            return Either.right(ActionStatus.INVALID_CONTENT);
-        }
-
-    }
-
-    private PropertyBusinessLogic getPropertyBL(ServletContext context) {
-        WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
-        WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
-        return webApplicationContext.getBean(PropertyBusinessLogic.class);
-    }
-
-}
index ddb4057..00b04a4 100644 (file)
@@ -105,12 +105,6 @@ public class TypesFetchServlet extends AbstractValidationsServlet {
         }
     }
 
-    private PropertyBusinessLogic getPropertyBL(ServletContext context) {
-        WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
-        WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
-        return webApplicationContext.getBean(PropertyBusinessLogic.class);
-    }
-
     @GET
     @Path("interfaceLifecycleTypes")
     @Consumes(MediaType.APPLICATION_JSON)
index 6a06c94..04119fe 100644 (file)
@@ -488,7 +488,7 @@ public class CapabilityRequirementConverter {
         if (isNotEmpty(properties)) {
             Map<String, ToscaProperty> toscaProperties = new HashMap<>();
             for (PropertyDefinition property : properties) {
-                ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, true);
+                ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.CAPABILITY);
                 toscaProperties.put(property.getName(), toscaProperty);
             }
             toscaCapability.setProperties(toscaProperties);
@@ -520,7 +520,7 @@ public class CapabilityRequirementConverter {
         if (isNotEmpty(properties)) {
             Map<String, ToscaProperty> toscaProperties = new HashMap<>();
             for (PropertyDefinition property : properties) {
-                ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, true);
+                ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.CAPABILITY);
                 toscaProperties.put(property.getName(), toscaProperty);
             }
             toscaCapability.setProperties(toscaProperties);
index d128d53..04c7c69 100644 (file)
 
 package org.openecomp.sdc.be.tosca;
 
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParser;
-import com.google.gson.stream.JsonReader;
-import fj.data.Either;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Supplier;
+
 import org.apache.commons.lang3.StringUtils;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
@@ -35,6 +37,7 @@ import org.openecomp.sdc.be.model.Resource;
 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;
+import org.openecomp.sdc.be.model.tosca.converters.ToscaStringConvertor;
 import org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter;
 import org.openecomp.sdc.be.model.tosca.converters.ToscaValueConverter;
 import org.openecomp.sdc.be.tosca.model.EntrySchema;
@@ -42,18 +45,24 @@ import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 
-import java.io.StringReader;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Supplier;
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
+
+import fj.data.Either;
 
 public class PropertyConvertor {
     private static PropertyConvertor instance;
     private JsonParser jsonParser = new JsonParser();
     private static final Logger log = Logger.getLogger(PropertyConvertor.class);
+    public  enum PropertyType  {
+        CAPABILITY,
+        INPUT,
+        PROPERTY
+    }
     Gson gson = new Gson();
-    protected PropertyConvertor() {
+    public PropertyConvertor() {
 
     }
 
@@ -74,7 +83,7 @@ public class PropertyConvertor {
 
                 // take only the properties of this resource
                 props.stream().filter(p -> p.getOwnerId() == null || p.getOwnerId().equals(component.getUniqueId())).forEach(property -> {
-                    properties.put(property.getName(), convertProperty(dataTypes, property, false));
+                    properties.put(property.getName(), convertProperty(dataTypes, property, PropertyType.PROPERTY));
                  });
                 if (!properties.isEmpty()) {
                     toscaNodeType.setProperties(properties);
@@ -84,7 +93,7 @@ public class PropertyConvertor {
         return Either.left(toscaNodeType);
     }
 
-    public ToscaProperty convertProperty(Map<String, DataTypeDefinition> dataTypes, PropertyDataDefinition property, boolean isCapabiltyProperty) {
+    public ToscaProperty convertProperty(Map<String, DataTypeDefinition> dataTypes, PropertyDefinition property, PropertyType propertyType) {
         ToscaProperty prop = new ToscaProperty();
 
         String innerType = null;
@@ -96,22 +105,35 @@ public class PropertyConvertor {
             eschema.setDescription(schema.getProperty().getDescription());
             prop.setEntry_schema(eschema);
         }
-        return getToscaProperty(dataTypes, property, isCapabiltyProperty, prop, innerType);
+        return getToscaProperty(dataTypes, property, prop, innerType, propertyType);
 
     }
 
-    private ToscaProperty getToscaProperty(Map<String, DataTypeDefinition> dataTypes, PropertyDataDefinition property, boolean isCapabiltyProperty, ToscaProperty prop, String innerType) {
+    private ToscaProperty getToscaProperty(Map<String, DataTypeDefinition> dataTypes,
+                                           PropertyDataDefinition property,
+                                           ToscaProperty prop,
+                                           String innerType,
+                                           PropertyType propertyType) {
         log.trace("try to convert property {} from type {} with default value [{}]", property.getName(), property.getType(), property.getDefaultValue());
-        Object convertedObj = convertToToscaObject(property.getType(), property.getDefaultValue(), innerType, dataTypes, false);
+        String defaultValue = property.getDefaultValue();
+        if(Objects.isNull(defaultValue)) {
+            defaultValue = property.getValue();
+        }
+        Object convertedObj =
+            convertToToscaObject(property.getType(), defaultValue, innerType, dataTypes, false);
         if (convertedObj != null) {
             prop.setDefaultp(convertedObj);
         }
         prop.setType(property.getType());
         prop.setDescription(property.getDescription());
-        if (isCapabiltyProperty) {
-            prop.setStatus(property.getStatus());
-        }
         prop.setRequired(property.isRequired());
+        switch (propertyType) {
+            case CAPABILITY:
+                prop.setStatus(property.getStatus());
+                break;
+            default:
+                break;
+        }
         return prop;
     }
     
@@ -198,9 +220,9 @@ public class PropertyConvertor {
     }
 
     private boolean valueStartsWithNonJsonChar(String value) {
-        return value.startsWith("/") || value.startsWith(":") || value.startsWith("#");
+        return value.startsWith("/") || value.startsWith(":");
     }
-    
+
     public void convertAndAddValue(Map<String, DataTypeDefinition> dataTypes,
             Map<String, Object> props, PropertyDataDefinition prop, Supplier<String> supplier) {
         Object convertedValue = convertValue(dataTypes, prop, supplier);
index d0286d7..ecead12 100644 (file)
 
 package org.openecomp.sdc.be.tosca;
 
-import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceDefinitionElement;
-import static org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil.addInterfaceTypeElement;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
 import fj.data.Either;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.ImmutableTriple;
@@ -32,48 +33,24 @@ import org.openecomp.sdc.be.components.impl.exceptions.SdcResourceNotFoundExcept
 import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
 import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
-import org.openecomp.sdc.be.model.ArtifactDefinition;
-import org.openecomp.sdc.be.model.CapabilityDefinition;
-import org.openecomp.sdc.be.model.Component;
-import org.openecomp.sdc.be.model.ComponentInstance;
-import org.openecomp.sdc.be.model.ComponentInstanceInput;
-import org.openecomp.sdc.be.model.ComponentInstanceProperty;
-import org.openecomp.sdc.be.model.ComponentParametersView;
-import org.openecomp.sdc.be.model.DataTypeDefinition;
-import org.openecomp.sdc.be.model.GroupInstance;
-import org.openecomp.sdc.be.model.InputDefinition;
-import org.openecomp.sdc.be.model.InterfaceDefinition;
-import org.openecomp.sdc.be.model.PropertyDefinition;
-import org.openecomp.sdc.be.model.RelationshipInfo;
-import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
-import org.openecomp.sdc.be.model.RequirementDefinition;
-import org.openecomp.sdc.be.model.Resource;
-import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.*;
 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
 import org.openecomp.sdc.be.model.category.CategoryDefinition;
 import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade;
 import org.openecomp.sdc.be.model.jsontitan.utils.ModelConverter;
-import org.openecomp.sdc.be.model.operations.api.IInterfaceLifecycleOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
-import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
-import org.openecomp.sdc.be.tosca.model.ToscaCapability;
-import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
-import org.openecomp.sdc.be.tosca.model.ToscaMetadata;
-import org.openecomp.sdc.be.tosca.model.ToscaNodeTemplate;
-import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
-import org.openecomp.sdc.be.tosca.model.ToscaPolicyTemplate;
-import org.openecomp.sdc.be.tosca.model.ToscaProperty;
-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 org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter;
+import org.openecomp.sdc.be.tosca.model.*;
 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
 import org.openecomp.sdc.be.tosca.utils.InputConverter;
+import org.openecomp.sdc.be.tosca.utils.InterfacesOperationsToscaUtil;
 import org.openecomp.sdc.common.log.wrappers.Logger;
-import org.openecomp.sdc.exception.ResponseFormat;
+import org.openecomp.sdc.externalupload.utils.ServiceUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.yaml.snakeyaml.DumperOptions;
 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
@@ -89,15 +66,8 @@ import org.yaml.snakeyaml.representer.Represent;
 import org.yaml.snakeyaml.representer.Representer;
 
 import java.beans.IntrospectionException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
@@ -105,6 +75,8 @@ 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;
 
 @org.springframework.stereotype.Component("tosca-export-handler")
 public class ToscaExportHandler {
@@ -145,6 +117,8 @@ public class ToscaExportHandler {
     private static final List<Map<String, Map<String, String>>> DEFAULT_IMPORTS = ConfigurationManager
                                                                                           .getConfigurationManager().getConfiguration().getDefaultImports();
 
+    public ToscaExportHandler(){}
+
     public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
 
         Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertToToscaTemplate(component);
@@ -274,12 +248,16 @@ public class ToscaExportHandler {
         }
 
         List<ComponentInstance> componentInstances = component.getComponentInstances();
-        Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component
-                                                                                            .getComponentInstancesProperties();
+        Map<String, List<ComponentInstanceProperty>> componentInstancesProperties =
+                component.getComponentInstancesProperties();
+        Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces =
+            component.getComponentInstancesInterfaces();
         if (componentInstances != null && !componentInstances.isEmpty()) {
 
-            Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates = convertNodeTemplates(component,
-                    componentInstances, componentInstancesProperties, componentCache, dataTypes, topologyTemplate);
+            Either<Map<String, ToscaNodeTemplate>, ToscaError> nodeTemplates =
+                    convertNodeTemplates(component, componentInstances,
+                        componentInstancesProperties, componentInstanceInterfaces,
+                        componentCache, dataTypes, topologyTemplate);
             if (nodeTemplates.isRight()) {
                 return Either.right(nodeTemplates.right().value());
             }
@@ -335,7 +313,27 @@ public class ToscaExportHandler {
         return Either.left(toscaNode);
     }
 
-    private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
+    private Either<ToscaTopolgyTemplate, ToscaError> fillInputs(Component component,
+            ToscaTopolgyTemplate topologyTemplate, Map<String, DataTypeDefinition> dataTypes) {
+        if (log.isDebugEnabled()) {
+            log.debug("fillInputs for component {}", component.getUniqueId());
+        }
+        List<InputDefinition> inputDef = component.getInputs();
+        Map<String, ToscaProperty> inputs = new HashMap<>();
+
+        if (inputDef != null) {
+            inputDef.forEach(i -> {
+                ToscaProperty property = propertyConvertor.convertProperty(dataTypes, i, PropertyConvertor.PropertyType.INPUT);
+                inputs.put(i.getName(), property);
+            });
+            if (!inputs.isEmpty()) {
+                topologyTemplate.setInputs(inputs);
+            }
+        }
+        return Either.left(topologyTemplate);
+    }
+
+  private void addGroupsToTopologyTemplate(Component component, ToscaTopolgyTemplate topologyTemplate) {
 
 
         Map<String, ToscaGroupTemplate> groups = groupExportParser.getGroups(component);
@@ -436,8 +434,6 @@ public class ToscaExportHandler {
         Map<String, Component> componentCache = new HashMap<>();
 
         if (!ModelConverter.isAtomicComponent(component)) {
-            List<ComponentInstance> componentInstances = component.getComponentInstances();
-
             List<Map<String, Map<String, String>>> additionalImports = toscaTemplate.getImports() == null
                                                                                ? new ArrayList<>(DEFAULT_IMPORTS) : new ArrayList<>(toscaTemplate.getImports());
 
@@ -457,6 +453,7 @@ public class ToscaExportHandler {
                     additionalImports.add(importsListMember);
                 }
             }
+            List<ComponentInstance> componentInstances = component.getComponentInstances();
             if (componentInstances != null && !componentInstances.isEmpty()) {
                 componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependecies, ci));
             }
@@ -582,20 +579,35 @@ public class ToscaExportHandler {
         Map<String, DataTypeDefinition> dataTypes = dataTypesEither.left().value();
 
         List<InputDefinition> inputDef = component.getInputs();
-        Map<String, ToscaProperty> inputs = new HashMap<>();
-        addInterfaceDefinitionElement(component, toscaNodeType, isAssociatedResourceComponent);
+        Map<String, ToscaProperty> mergedProperties = new HashMap<>();
+        addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedResourceComponent);
         if (inputDef != null) {
-            inputDef.forEach(i -> {
-                ToscaProperty property = propertyConvertor.convertProperty(dataTypes, i, false);
-                inputs.put(i.getName(), property);
-            });
-            if (!inputs.isEmpty()) {
-                toscaNodeType.setProperties(inputs);
-            }
+            addInputsToProperties(dataTypes, inputDef, mergedProperties);
+        }
+
+        if(CollectionUtils.isNotEmpty(component.getProperties())) {
+            List<PropertyDefinition> properties = component.getProperties();
+            mergedProperties = properties.stream().collect(Collectors.toMap(
+                PropertyDataDefinition::getName,
+                property -> propertyConvertor.convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY)));
         }
+        if (!mergedProperties.isEmpty()) {
+            toscaNodeType.setProperties(mergedProperties);
+        }
+        // Extracted to method for code reuse
         return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
     }
 
+  private void addInputsToProperties(Map<String, DataTypeDefinition> dataTypes,
+                                     List<InputDefinition> inputDef,
+                                     Map<String, ToscaProperty> mergedProperties) {
+    for(InputDefinition input : inputDef) {
+      ToscaProperty property = propertyConvertor.convertProperty(dataTypes, input, PropertyConvertor.PropertyType.INPUT);
+      mergedProperties.put(input.getName(), property);
+    }
+  }
+
+
     private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache, Component component, ToscaTemplate toscaNode,
             Map<String, ToscaNodeType> nodeTypes, ToscaNodeType toscaNodeType,
             Map<String, DataTypeDefinition> dataTypes) {
@@ -635,9 +647,11 @@ public class ToscaExportHandler {
         return Either.left(toscaNode);
     }
 
-    private Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(Component component,
+    protected Either<Map<String, ToscaNodeTemplate>, ToscaError> convertNodeTemplates(
+            Component component,
             List<ComponentInstance> componentInstances,
             Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
+            Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
             Map<String, Component> componentCache, Map<String, DataTypeDefinition> dataTypes,
             ToscaTopolgyTemplate topologyTemplate) {
 
@@ -704,7 +718,11 @@ public class ToscaExportHandler {
                 addComponentInstanceInputs(dataTypes, componentInstancesInputs, instanceUniqueId,
                         props);
             }
-            if (!props.isEmpty()) {
+            //M3[00001] - NODE TEMPLATE INTERFACES  - START
+            handleInstanceInterfaces(componentInstanceInterfaces, componentInstance, dataTypes, nodeTemplate,
+                    instanceUniqueId, component);
+            //M3[00001] - NODE TEMPLATE INTERFACES  - END
+            if (props != null && !props.isEmpty()) {
                 nodeTemplate.setProperties(props);
             }
 
@@ -749,6 +767,70 @@ public class ToscaExportHandler {
         return convertNodeTemplatesRes;
     }
 
+    private void handleInstanceInterfaces(
+            Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces,
+            ComponentInstance componentInstance, Map<String, DataTypeDefinition> dataTypes, ToscaNodeTemplate nodeTemplate,
+            String instanceUniqueId,
+            Component parentComponent) {
+
+        Map<String, Object> interfaces;
+
+        // we need to handle service proxy interfaces
+        if(isComponentOfTypeServiceProxy(componentInstance)) {
+            if(MapUtils.isEmpty(componentInstanceInterfaces)
+                || !componentInstanceInterfaces.containsKey(instanceUniqueId)) {
+                interfaces = null;
+            } else {
+                List<ComponentInstanceInterface> currServiceInterfaces =
+                    componentInstanceInterfaces.get(instanceUniqueId);
+
+                Map<String, InterfaceDefinition> tmpInterfaces = new HashMap<>();
+                currServiceInterfaces.forEach(instInterface -> tmpInterfaces.put(instInterface
+                    .getUniqueId(), instInterface));
+
+                interfaces = InterfacesOperationsToscaUtil
+                        .getInterfacesMap(parentComponent, tmpInterfaces, dataTypes, true, true);
+            }
+        } else {
+            interfaces =
+                getComponentInstanceInterfaceInstances(componentInstanceInterfaces,
+                    componentInstance, instanceUniqueId);
+        }
+        nodeTemplate.setInterfaces(interfaces);
+    }
+
+    private boolean isComponentOfTypeServiceProxy(ComponentInstance componentInstance) {
+        return Objects.nonNull(componentInstance.getOriginType())
+            && componentInstance.getOriginType().getValue().equals("Service Proxy");
+    }
+
+    //M3[00001] - NODE TEMPLATE INTERFACES  - START
+    private Map<String, Object> getComponentInstanceInterfaceInstances(Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces,
+                                                                        ComponentInstance componentInstance,
+                                                                       String instanceUniqueId) {
+        if(MapUtils.isEmpty(componentInstancesInterfaces)) {
+            return null;
+        }
+
+        List<ComponentInstanceInterface> componentInstanceInterfaces =
+            componentInstancesInterfaces.get(instanceUniqueId);
+
+        if(CollectionUtils.isEmpty(componentInstanceInterfaces)) {
+          return null;
+        }
+
+        Map<String, Object> interfaces = new HashMap<>();
+        for(ComponentInstanceInterface componentInstanceInterface : componentInstanceInterfaces) {
+            interfaces.put(componentInstanceInterface.getInterfaceId(),
+                removeOperationsKeyFromInterface(componentInstanceInterface.getInterfaceInstanceDataDefinition()));
+        }
+
+        componentInstance.setInterfaces(interfaces);
+
+        return interfaces;
+    }
+    //M3[00001] - NODE TEMPLATE INTERFACES  - END
+
     private void addComponentInstanceInputs(Map<String, DataTypeDefinition> dataTypes,
             Map<String, List<ComponentInstanceInput>> componentInstancesInputs,
             String instanceUniqueId, Map<String, Object> props) {
@@ -791,6 +873,34 @@ public class ToscaExportHandler {
         }
     }
 
+    /**
+     * @param dataTypes
+     * @param componentInstance
+     * @param props
+     * @param prop
+     * @param supplier
+     */
+    private void convertAndAddValue(Map<String, DataTypeDefinition> dataTypes, ComponentInstance componentInstance,
+            Map<String, Object> props, PropertyDefinition prop, Supplier<String> supplier) {
+        Object convertedValue = convertValue(dataTypes, componentInstance, prop, supplier);
+        if (!ToscaValueBaseConverter.isEmptyObjectValue(convertedValue)) {
+            props.put(prop.getName(), convertedValue);
+        }
+    }
+
+    private <T extends PropertyDefinition> Object convertValue(Map<String, DataTypeDefinition> dataTypes,
+            ComponentInstance componentInstance, T input, Supplier<String> supplier) {
+        log.debug("Convert property or input value {} for instance {}", input.getName(),
+                componentInstance.getUniqueId());
+        String propertyType = input.getType();
+        String innerType = null;
+        if (input.getSchema() != null && input.getSchema().getProperty() != null) {
+            innerType = input.getSchema().getProperty().getType();
+        }
+        return propertyConvertor.convertToToscaObject(propertyType, supplier.get(), innerType,
+            dataTypes, true);
+    }
+
     private ToscaNodeType createNodeType(Component component) {
         ToscaNodeType toscaNodeType = new ToscaNodeType();
         if (ModelConverter.isAtomicComponent(component)) {
@@ -1128,5 +1238,22 @@ public class ToscaExportHandler {
         }
     }
 
+    private Object removeOperationsKeyFromInterface(Object interfaceInstanceDataDefinition) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
+
+            Map<String, Object> interfaceAsMap = ServiceUtils.getObjectAsMap(interfaceInstanceDataDefinition);
+            Map<String, Object> operations = (Map<String, Object>) interfaceAsMap.remove("operations");
+            interfaceAsMap.remove("empty");
+
+            if(MapUtils.isNotEmpty(operations)) {
+                interfaceAsMap.putAll(operations);
+            }
+
+            Object interfaceObject = objectMapper.convertValue(interfaceAsMap, Object.class);
+
+            return interfaceObject;
+
+    }
 }
 
index c27944e..b67a2cf 100644 (file)
@@ -20,6 +20,9 @@
 
 package org.openecomp.sdc.be.tosca.model;
 
+import org.apache.commons.collections.MapUtils;
+
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -30,6 +33,7 @@ public class ToscaNodeTemplate {
     private Map<String, Object> properties;
     private List<Map<String, ToscaTemplateRequirement>> requirements;
     private Map<String, ToscaTemplateCapability> capabilities;
+    private Map<String, Object> interfaces;
 
     public String getType() {
         return type;
@@ -78,4 +82,17 @@ public class ToscaNodeTemplate {
   public void setDescription(String description) {
     this.description = description;
   }
+
+    public void setInterfaces(
+            Map<String, Object> interfaces) {
+        this.interfaces = interfaces;
+    }
+
+    public void addInterface(String interfaceName, Object interfaceDataDefinition) {
+        if (MapUtils.isEmpty(this.interfaces)) {
+            this.interfaces = new HashMap<>();
+        }
+
+        this.interfaces.put(interfaceName, interfaceDataDefinition);
+    }
 }
index f6619b9..c7e4d9b 100644 (file)
@@ -42,7 +42,8 @@ public class InputConverter {
         if (inputDef != null) {
             inputDef.forEach(i -> {
                 //Extract input the same as property
-                ToscaProperty toscaProperty = propertyConvertor.convertProperty(dataTypes, i, false);
+                ToscaProperty toscaProperty = propertyConvertor.convertProperty(dataTypes, i,
+                    PropertyConvertor.PropertyType.INPUT);
                 //now that we have Tosca property we create new object called tosca input which drives from it
                 ToscaInput toscaInput = new ToscaInput(toscaProperty);
                 List<Annotation> annotations = i.getAnnotations();
index 106aa58..a72f57d 100644 (file)
@@ -30,6 +30,7 @@ import org.apache.commons.collections.MapUtils;
 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
 import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.Product;
 import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition;
@@ -103,6 +104,7 @@ public class InterfacesOperationsToscaUtil {
      * @param nodeType  to which the interfaces element will be added
      */
     public static void addInterfaceDefinitionElement(Component component, ToscaNodeType nodeType,
+                                                     Map<String, DataTypeDefinition> dataTypes,
                                                      boolean isAssociatedResourceComponent) {
         if (component instanceof Product) {
             return;
@@ -111,6 +113,28 @@ public class InterfacesOperationsToscaUtil {
         if (MapUtils.isEmpty(interfaces)) {
             return;
         }
+        Map<String, Object> toscaInterfaceDefinitions = getInterfacesMap(component, dataTypes,
+                isAssociatedResourceComponent);
+        if (MapUtils.isNotEmpty(toscaInterfaceDefinitions)) {
+            nodeType.setInterfaces(toscaInterfaceDefinitions);
+        }
+    }
+
+    private static Map<String, Object> getInterfacesMap(Component component,
+                                                        Map<String, DataTypeDefinition> dataTypes,
+                                                        boolean isAssociatedResourceComponent) {
+        return getInterfacesMap(component, component.getInterfaces(), dataTypes, isAssociatedResourceComponent, false);
+    }
+
+    public static Map<String, Object> getInterfacesMap(Component component,
+                                                       Map<String, InterfaceDefinition> interfaces,
+                                                       Map<String, DataTypeDefinition> dataTypes,
+                                                       boolean isAssociatedResourceComponent,
+                                                       boolean isServiceProxyInterface) {
+        if(MapUtils.isEmpty(interfaces)) {
+            return null;
+        }
+
         Map<String, Object> toscaInterfaceDefinitions = new HashMap<>();
         for (InterfaceDefinition interfaceDefinition : interfaces.values()) {
             ToscaInterfaceDefinition toscaInterfaceDefinition = new ToscaInterfaceDefinition();
@@ -137,13 +161,46 @@ public class InterfacesOperationsToscaUtil {
             toscaInterfaceDefinition.setOperations(toscaOperations);
             Map<String, Object> interfaceDefAsMap = getObjectAsMap(toscaInterfaceDefinition);
             Map<String, Object> operationsMap = (Map<String, Object>) interfaceDefAsMap.remove(OPERATIONS_KEY);
-            handleDefaults(operationsMap);
+            if (isServiceProxyInterface) {
+                handleServiceProxyOperationInputValue(operationsMap, interfaceType);
+            } else {
+                handleDefaults(operationsMap);
+            }
             interfaceDefAsMap.putAll(operationsMap);
             toscaInterfaceDefinitions.put(getLastPartOfName(interfaceType), interfaceDefAsMap);
         }
-        if (MapUtils.isNotEmpty(toscaInterfaceDefinitions)) {
-            nodeType.setInterfaces(toscaInterfaceDefinitions);
+
+        return toscaInterfaceDefinitions;
+    }
+
+    private static void handleServiceProxyOperationInputValue(Map<String, Object> operationsMap, String parentKey) {
+        for (Map.Entry<String, Object> operationEntry : operationsMap.entrySet()) {
+            final Object value = operationEntry.getValue();
+            final String key = operationEntry.getKey();
+            if (value instanceof Map) {
+                if ("inputs".equals(parentKey)) {
+                    Object defaultValue = getDefaultValue((Map<String, Object>) value);
+                    operationsMap.put(key, defaultValue);
+                } else {
+                    handleServiceProxyOperationInputValue((Map<String, Object>) value, key);
+                }
+            }
+        }
+    }
+
+    private static Object getDefaultValue(Map<String, Object> inputValueMap) {
+        Object defaultValue = null;
+        for (Map.Entry<String, Object> operationEntry : inputValueMap.entrySet()) {
+            final Object value = operationEntry.getValue();
+            if (value instanceof Map) {
+                getDefaultValue((Map<String, Object>) value);
+            }
+            final String key = operationEntry.getKey();
+            if (key.equals(DEFAULTP)) {
+                defaultValue = inputValueMap.remove(key);
+            }
         }
+        return defaultValue;
     }
 
     /*
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/externalupload/utils/ServiceUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/externalupload/utils/ServiceUtils.java
new file mode 100644 (file)
index 0000000..ba6f9c2
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.externalupload.utils;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.beanutils.BeanUtils;
+
+import java.lang.reflect.Field;
+import java.util.*;
+
+public class ServiceUtils {
+  private static final char[] CHARS = new char[]{
+      '0', '1', '2', '3', '4', '5', '6', '7',
+      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+  };
+  private static final String TYPE = "type";
+  private static final String NODE = "node";
+
+  public static <T> Optional<T> createObjectUsingSetters(Object objectCandidate,
+                                                         Class<T> classToCreate)
+      throws Exception {
+    if (Objects.isNull(objectCandidate)) {
+      return Optional.empty();
+    }
+
+    Map<String, Object> objectAsMap = getObjectAsMap(objectCandidate);
+    T result = classToCreate.newInstance();
+
+    List<Field> declaredFields = getAllFields(classToCreate);
+    for( Field field : declaredFields){
+      if(isComplexClass(field)){
+        Optional<?> objectUsingSetters =
+            createObjectUsingSetters(objectAsMap.get(field.getName()), field.getType());
+        if( objectUsingSetters.isPresent()){
+          objectAsMap.remove(field.getName());
+          objectAsMap.put(field.getName(), objectUsingSetters.get());
+        }
+      }
+    }
+    BeanUtils.populate(result, objectAsMap);
+
+    return Optional.of(result);
+  }
+
+  private static <T> List<Field> getAllFields(Class<T> clazz) {
+    List<Field> fields = new ArrayList<>();
+    for(Class<?> c = clazz; c != null; c = c.getSuperclass()) {
+      fields.addAll(Arrays.asList(c.getDeclaredFields()));
+    }
+
+    return fields;
+  }
+
+  private static boolean isComplexClass(Field field) {
+    return !field.getType().equals(Map.class)
+        && !field.getType().equals(String.class)
+        && !field.getType().equals(Integer.class)
+        && !field.getType().equals(Float.class)
+        && !field.getType().equals(Double.class)
+        && !field.getType().equals(Set.class)
+        && !field.getType().equals(Object.class)
+        && !field.getType().equals(List.class);
+  }
+  public static Map<String, Object> getObjectAsMap(Object obj) {
+    return new ObjectMapper().convertValue(obj, Map.class);
+  }
+
+  public static Set<String> getClassFieldNames(Class<? extends Object> classType) {
+    Set<String> fieldNames = new HashSet<>();
+    List<Field> allFields = getAllFields(classType);
+    allFields.forEach(field -> fieldNames.add(field.getName()));
+
+    return fieldNames;
+  }
+}
\ No newline at end of file
index f55f461..4f2bb78 100644 (file)
@@ -23,19 +23,15 @@ package org.openecomp.sdc.be.components;
 import fj.data.Either;
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.openecomp.sdc.be.components.impl.BaseBusinessLogic;
 import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
 import org.openecomp.sdc.be.components.validation.UserValidations;
 import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
-import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
 import org.openecomp.sdc.be.model.*;
@@ -50,27 +46,18 @@ import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.common.impl.ExternalConfiguration;
 import org.openecomp.sdc.common.impl.FSConfigurationSource;
 import org.openecomp.sdc.exception.ResponseFormat;
+import org.openecomp.sdc.test.utils.InterfaceOperationTestUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.web.context.WebApplicationContext;
+
 import javax.servlet.ServletContext;
 import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.runner.Request.method;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
+import java.util.*;
+
+import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.when;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
 
 public class PropertyBusinessLogicTest {
 
@@ -89,20 +76,22 @@ public class PropertyBusinessLogicTest {
     private ComponentsUtils componentsUtils;
     @Mock
     private ToscaOperationFacade toscaOperationFacade;
-
     @Mock
     private UserValidations userValidations;
-
     @Mock
     IGraphLockOperation graphLockOperation;
+    @Mock
+    TitanDao titanDao;
 
     @InjectMocks
     private PropertyBusinessLogic bl = new PropertyBusinessLogic();
     private User user = null;
     private String resourceId = "resourceforproperty.0.1";
-
-    @Mock
-    TitanDao titanDao;
+    private String serviceId = "serviceForProperty.0.1";
+    private static final String interfaceType = "interfaceType";
+    private static final String operationType = "operationType";
+    private static final String operationId = "operationId";
+    private static final String operationId2 = "operationId2";
 
     @Before
     public void setup() {
@@ -144,7 +133,7 @@ public class PropertyBusinessLogicTest {
         resource.setUniqueId(resourceId);
 
         Mockito.when(toscaOperationFacade.getToscaElement(resourceId)).thenReturn(Either.left(resource));
-        Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> nonExistingProperty = bl.getProperty(resourceId, "NonExistingProperty", user.getUserId());
+        Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> nonExistingProperty = bl.getComponentProperty(resourceId, "NonExistingProperty", user.getUserId());
         assertTrue(nonExistingProperty.isRight());
         Mockito.verify(componentsUtils).getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, "");
     }
@@ -158,7 +147,7 @@ public class PropertyBusinessLogicTest {
         resource.setUniqueId(resourceId);
 
         Mockito.when(toscaOperationFacade.getToscaElement(resourceId)).thenReturn(Either.left(resource));
-        Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> notFoundProperty = bl.getProperty(resourceId, "invalidId", user.getUserId());
+        Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> notFoundProperty = bl.getComponentProperty(resourceId, "invalidId", user.getUserId());
         assertTrue(notFoundProperty.isRight());
         Mockito.verify(componentsUtils).getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, "");
     }
@@ -171,11 +160,105 @@ public class PropertyBusinessLogicTest {
         resource.setProperties(Arrays.asList(property1));
 
         Mockito.when(toscaOperationFacade.getToscaElement(resourceId)).thenReturn(Either.left(resource));
-        Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> foundProperty = bl.getProperty(resourceId, property1.getUniqueId(), user.getUserId());
+        Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> foundProperty = bl.getComponentProperty(resourceId, property1.getUniqueId(), user.getUserId());
         assertTrue(foundProperty.isLeft());
         assertEquals(foundProperty.left().value().getValue().getUniqueId(), property1.getUniqueId());
     }
 
+    @Test
+    public void testGetPropertyFromService() {
+        Service service = new Service();
+        service.setUniqueId(serviceId);
+
+        PropertyDefinition property1 = createPropertyObject("someProperty", null);
+        service.setProperties(Arrays.asList(property1));
+
+        Mockito.when(toscaOperationFacade.getToscaElement(serviceId)).thenReturn(Either.left(service));
+        Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> serviceProperty =
+            bl.getComponentProperty(serviceId, property1.getUniqueId(), user.getUserId());
+
+        assertTrue(serviceProperty.isLeft());
+        assertEquals(serviceProperty.left().value().getValue().getUniqueId(), property1.getUniqueId());
+    }
+
+    @Test
+    public void testPropertyNotFoundOnService() {
+        Service service = new Service();
+        service.setUniqueId(serviceId);
+
+        PropertyDefinition property1 = createPropertyObject("someProperty", null);
+        service.setProperties(Arrays.asList(property1));
+
+        Mockito.when(toscaOperationFacade.getToscaElement(serviceId)).thenReturn(Either.left(service));
+        Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> serviceProperty =
+            bl.getComponentProperty(serviceId, "notExistingPropId", user.getUserId());
+
+        assertTrue(serviceProperty.isRight());
+    }
+
+    @Test
+    public void isPropertyUsedByComponentInterface(){
+        Service service = new Service();
+        service.setUniqueId(serviceId);
+        service.setInterfaces(InterfaceOperationTestUtils.createMockInterfaceDefinitionMap(interfaceType, operationId, operationType));
+
+        PropertyDefinition propDef1 = new PropertyDefinition();
+        propDef1.setUniqueId("ComponentInput1_uniqueId");
+        assertTrue(bl.isPropertyUsedByOperation(service, propDef1));
+
+        PropertyDefinition propDef2 = new PropertyDefinition();
+        propDef1.setUniqueId("inputId2");
+        Mockito.when(toscaOperationFacade.getParentComponents(serviceId)).thenReturn(Either.left(new ArrayList<>()));
+        assertFalse(bl.isPropertyUsedByOperation(service, propDef2));
+    }
+
+    @Test
+    public void isPropertyUsedByComponentInstanceInterface(){
+        Map<String, InterfaceDefinition> newInterfaceDefinition = InterfaceOperationTestUtils.createMockInterfaceDefinitionMap(interfaceType, operationId, operationType);
+        ComponentInstanceInterface componentInstanceInterface = new ComponentInstanceInterface(interfaceType, newInterfaceDefinition.get(interfaceType));
+
+        Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = new HashMap<>();
+        componentInstanceInterfaces.put("Test", Arrays.asList(componentInstanceInterface));
+
+        Service service = new Service();
+        service.setUniqueId(serviceId);
+        service.setComponentInstancesInterfaces(componentInstanceInterfaces);
+
+        PropertyDefinition propDef1 = new PropertyDefinition();
+        propDef1.setUniqueId("ComponentInput1_uniqueId");
+        assertTrue(bl.isPropertyUsedByOperation(service, propDef1));
+
+        PropertyDefinition propDef2 = new PropertyDefinition();
+        propDef1.setUniqueId("inputId2");
+        Mockito.when(toscaOperationFacade.getParentComponents(serviceId)).thenReturn(Either.left(new ArrayList<>()));
+        assertFalse(bl.isPropertyUsedByOperation(service, propDef2));
+    }
+
+    @Test
+    public void isPropertyUsedByComponentParentComponentInstanceInterface(){
+        Map<String, InterfaceDefinition> newInterfaceDefinition = InterfaceOperationTestUtils.createMockInterfaceDefinitionMap(interfaceType, operationId, operationType);
+        ComponentInstanceInterface componentInstanceInterface = new ComponentInstanceInterface(interfaceType, newInterfaceDefinition.get(interfaceType));
+
+        Map<String, List<ComponentInstanceInterface>> componentInstanceInterfaces = new HashMap<>();
+        componentInstanceInterfaces.put("Test", Arrays.asList(componentInstanceInterface));
+
+        Service parentService = new Service();
+        parentService.setComponentInstancesInterfaces(componentInstanceInterfaces);
+        Service childService = new Service();
+        childService.setUniqueId(serviceId);
+
+        PropertyDefinition propDef1 = new PropertyDefinition();
+        propDef1.setUniqueId("ComponentInput1_uniqueId");
+        Mockito.when(toscaOperationFacade.getParentComponents(serviceId)).thenReturn(Either.left(Arrays.asList(parentService)));
+        assertTrue(bl.isPropertyUsedByOperation(childService, propDef1));
+
+        PropertyDefinition propDef2 = new PropertyDefinition();
+        propDef1.setUniqueId("inputId2");
+        Mockito.when(toscaOperationFacade.getParentComponents(serviceId)).thenReturn(Either.left(new ArrayList<>()));
+        assertFalse(bl.isPropertyUsedByOperation(childService, propDef2));
+    }
+
+
     private PropertyDefinition createPropertyObject(String propertyName, String resourceId) {
         PropertyDefinition pd = new PropertyDefinition();
         pd.setConstraints(null);
@@ -193,7 +276,8 @@ public class PropertyBusinessLogicTest {
     public void deleteProperty_CONNECTION_FAILURE() {
         StorageOperationStatus lockResult = StorageOperationStatus.CONNECTION_FAILURE;
         when(graphLockOperation.lockComponent(any(), any())).thenReturn(lockResult);
-        assertTrue(bl.deleteProperty("resourceforproperty.0.1", "someProperty","i726").isRight());
+        when(toscaOperationFacade.getToscaElement(anyString())).thenReturn(Either.left(new Resource()));
+        assertTrue(bl.deletePropertyFromComponent("resourceforproperty.0.1", "someProperty","i726").isRight());
     }
 
     @Test
@@ -229,7 +313,7 @@ public class PropertyBusinessLogicTest {
         when(toscaOperationFacade.getToscaElement("RES01")).thenReturn(toscastatus);
 
 
-        assertTrue(bl.deleteProperty("RES01", "someProperty","i726").isRight());
+        assertTrue(bl.deletePropertyFromComponent("RES01", "someProperty","i726").isRight());
     }
 
     @Test
@@ -265,7 +349,7 @@ public class PropertyBusinessLogicTest {
         when(toscaOperationFacade.getToscaElement("RES01")).thenReturn(toscastatus);
 
 
-        assertTrue(bl.deleteProperty("RES01", "someProperty","i726").isRight());
+        assertTrue(bl.deletePropertyFromComponent("RES01", "someProperty","i726").isRight());
     }
 
     @Test
@@ -299,8 +383,9 @@ public class PropertyBusinessLogicTest {
 
         Either<Component, StorageOperationStatus> toscastatus=Either.left(resource);
         when(toscaOperationFacade.getToscaElement("RES01")).thenReturn(toscastatus);
-        when(toscaOperationFacade.deletePropertyOfResource(anyObject(),anyString())).thenReturn(StorageOperationStatus.OK);
+        when(toscaOperationFacade.deletePropertyOfComponent(anyObject(),anyString())).thenReturn(StorageOperationStatus.OK);
+        when(toscaOperationFacade.getParentComponents(anyString())).thenReturn(Either.left(new ArrayList<>()));
 
-        assertTrue(bl.deleteProperty("RES01", "PROP","USR01").isRight());
+        assertTrue(bl.deletePropertyFromComponent("RES01", "PROP","USR01").isRight());
     }
 }
index e2d83ae..fe1e384 100644 (file)
@@ -337,7 +337,7 @@ public class InterfaceOperationValidationTest {
                 .validateInterfaceOperations(inputInterfaceDefinition, component,
                         component.getInterfaces().get(interfaceType1),
                         InterfaceOperationTestUtils.createMockInterfaceTypeMap(
-                                interfaceType1, operationType1), false).isRight());
+                                interfaceType1, operationType1 ), false).isRight());
     }
 
     @Test
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/PropertyServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/PropertyServletTest.java
deleted file mode 100644 (file)
index fe147b1..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.openecomp.sdc.be.servlets;
-
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.core.Response;
-
-import org.codehaus.jettison.json.JSONObject;
-import org.junit.Test;
-import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
-import org.openecomp.sdc.be.dao.api.ActionStatus;
-import org.openecomp.sdc.be.model.PropertyDefinition;
-
-import fj.data.Either;
-
-public class PropertyServletTest {
-
-       private PropertyServlet createTestSubject() {
-               return new PropertyServlet();
-       }
-
-       
-       @Test
-       public void testCreateProperty() throws Exception {
-               PropertyServlet testSubject;
-               String resourceId = "";
-               String data = "";
-               HttpServletRequest request = null;
-               String userId = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testGetProperty() throws Exception {
-               PropertyServlet testSubject;
-               String resourceId = "";
-               String propertyId = "";
-               HttpServletRequest request = null;
-               String userId = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testDeleteProperty() throws Exception {
-               PropertyServlet testSubject;
-               String resourceId = "";
-               String propertyId = "";
-               HttpServletRequest request = null;
-               String userId = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testUpdateProperty() throws Exception {
-               PropertyServlet testSubject;
-               String resourceId = "";
-               String propertyId = "";
-               String data = "";
-               HttpServletRequest request = null;
-               String userId = "";
-               Response result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testGetPropertyModel() throws Exception {
-               PropertyServlet testSubject;
-               String resourceId = "";
-               String data = "";
-               Either<Map<String, PropertyDefinition>, ActionStatus> result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-
-
-       
-       @Test
-       public void testGetPropertyDefinitionJSONObject() throws Exception {
-               PropertyServlet testSubject;
-               PropertyDefinition propertyDefinition = null;
-               JSONObject result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-
-       
-       @Test
-       public void testGetPropertyBL() throws Exception {
-               PropertyServlet testSubject;
-               ServletContext context = null;
-               PropertyBusinessLogic result;
-
-               // default test
-               testSubject = createTestSubject();
-       }
-}
\ No newline at end of file
index a06ba84..35b8ed0 100644 (file)
@@ -37,12 +37,12 @@ public class PropertyConvertorTest {
        
        property.setSchema(schema);
        
-       PropertyConvertor.getInstance().convertProperty(dataTypes, property, true);
+       PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY);
     }
 
     @Test
     public void convertPropertyWhenValueAndDefaultNull() {
-        ToscaProperty prop = PropertyConvertor.getInstance().convertProperty(dataTypes, property, false);
+        ToscaProperty prop = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY);
         assertNotNull(prop);
         assertNull(prop.getDefaultp());
     }
@@ -51,7 +51,7 @@ public class PropertyConvertorTest {
     public void convertPropertyWhenValueNullAndDefaultNotEmpty() {
         final String def = "1";
         property.setDefaultValue(def);
-        ToscaProperty result = PropertyConvertor.getInstance().convertProperty(dataTypes, property, false);
+        ToscaProperty result = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.PROPERTY);
         assertNotNull(result);
         assertEquals(Integer.valueOf(def), result.getDefaultp());
     }
@@ -129,7 +129,7 @@ public class PropertyConvertorTest {
                 .setDefaultValue("::")
                 .setType(ToscaPropertyType.STRING.getType())
                 .build();
-        ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(Collections.emptyMap(), property1, false);
+        ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(Collections.emptyMap(), property1, PropertyConvertor.PropertyType.PROPERTY);
         assertThat(toscaProperty.getDefaultp()).isEqualTo("::");
     }
 
@@ -139,7 +139,7 @@ public class PropertyConvertorTest {
                 .setDefaultValue("/")
                 .setType(ToscaPropertyType.STRING.getType())
                 .build();
-        ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(Collections.emptyMap(), property1, false);
+        ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(Collections.emptyMap(), property1, PropertyConvertor.PropertyType.PROPERTY);
         assertThat(toscaProperty.getDefaultp()).isEqualTo("/");
     }
     
index 592d27e..a61ea04 100644 (file)
@@ -498,6 +498,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
                Component component = getNewService();
                List<ComponentInstance> componentInstances = new ArrayList<>();
                Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = new HashMap<>();
+               Map<String, List<ComponentInstanceProperty>> componentInstancesInterfaces = new HashMap<>();
                Map<String, Component> componentCache = new HashMap<>();
                Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
                ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
@@ -542,6 +543,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
                componentCache.put("uid", component);
 
                componentInstancesProperties.put("id", new ArrayList<>());
+               componentInstancesInterfaces.put("id", new ArrayList<>());
                componentInstancesInputs.put("id", new ArrayList<>());
 
                Mockito.when(capabiltyRequirementConvertor.getOriginComponent(Mockito.any(Map.class),
@@ -553,7 +555,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
 
                // default test
                result = Deencapsulation.invoke(testSubject, "convertNodeTemplates", component, componentInstances,
-                               componentInstancesProperties, componentCache, dataTypes, topologyTemplate);
+                               componentInstancesProperties, componentInstancesInterfaces, componentCache, dataTypes, topologyTemplate);
        }
 
        @Test
@@ -561,6 +563,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
                Component component = getNewResource();
                List<ComponentInstance> componentInstances = new ArrayList<>();
                Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = new HashMap<>();
+               Map<String, List<ComponentInstanceProperty>> componentInstancesInterfaces = new HashMap<>();
                Map<String, Component> componentCache = new HashMap<>();
                Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
                ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
@@ -597,7 +600,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
 
                // default test
                result = Deencapsulation.invoke(testSubject, "convertNodeTemplates", component, componentInstances,
-                               componentInstancesProperties, componentCache, dataTypes, topologyTemplate);
+                               componentInstancesProperties, componentInstancesInterfaces, componentCache, dataTypes, topologyTemplate);
        }
 
        @Test
@@ -605,6 +608,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
                Component component = getNewResource();
                List<ComponentInstance> componentInstances = new ArrayList<>();
                Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = new HashMap<>();
+               Map<String, List<ComponentInstanceProperty>> componentInstancesInterfaces = new HashMap<>();
                Map<String, Component> componentCache = new HashMap<>();
                Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
                ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
@@ -637,7 +641,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
 
                // default test
                result = Deencapsulation.invoke(testSubject, "convertNodeTemplates", component, componentInstances,
-                               componentInstancesProperties, componentCache, dataTypes, topologyTemplate);
+                               componentInstancesProperties, componentInstancesInterfaces, componentCache, dataTypes, topologyTemplate);
        }
 
        @Test
@@ -645,6 +649,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
                Component component = new Resource();
                List<ComponentInstance> componentInstances = new ArrayList<>();
                Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = new HashMap<>();
+               Map<String, List<ComponentInstanceProperty>> componentInstancesInterfaces = new HashMap<>();
                Map<String, Component> componentCache = new HashMap<>();
                Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
                ToscaTopolgyTemplate topologyTemplate = new ToscaTopolgyTemplate();
@@ -677,7 +682,7 @@ public class ToscaExportHandlerTest extends BeConfDependentTest {
 
                // default test
                result = Deencapsulation.invoke(testSubject, "convertNodeTemplates", component, componentInstances,
-                               componentInstancesProperties, componentCache, dataTypes, topologyTemplate);
+                               componentInstancesProperties, componentInstancesInterfaces, componentCache, dataTypes, topologyTemplate);
        }
 
        @Test
index 156d280..fc017c8 100644 (file)
@@ -122,7 +122,7 @@ public class InterfacesOperationsToscaUtilTest {
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
         ToscaNodeType nodeType = new ToscaNodeType();
-        addInterfaceDefinitionElement(component, nodeType, false);
+        addInterfaceDefinitionElement(component, nodeType, null, false);
 
         ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null);
         ToscaTemplate template = new ToscaTemplate(NODE_TYPE_NAME);
@@ -153,7 +153,7 @@ public class InterfacesOperationsToscaUtilTest {
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
         ToscaNodeType nodeType = new ToscaNodeType();
-        addInterfaceDefinitionElement(component, nodeType, false);
+        addInterfaceDefinitionElement(component, nodeType, null, false);
 
         ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null);
         ToscaTemplate template = new ToscaTemplate("testService");
@@ -183,7 +183,7 @@ public class InterfacesOperationsToscaUtilTest {
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(interfaceType, addedInterface);
         ToscaNodeType nodeType = new ToscaNodeType();
-        addInterfaceDefinitionElement(component, nodeType, false);
+        addInterfaceDefinitionElement(component, nodeType, null, false);
 
         ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null);
         ToscaTemplate template = new ToscaTemplate("test");
@@ -218,7 +218,7 @@ public class InterfacesOperationsToscaUtilTest {
         component.setInterfaces(new HashMap<>());
         component.getInterfaces().put(addedInterfaceType, addedInterface);
         ToscaNodeType nodeType = new ToscaNodeType();
-        addInterfaceDefinitionElement(component, nodeType, false);
+        addInterfaceDefinitionElement(component, nodeType, null, false);
 
         ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null);
         ToscaTemplate template = new ToscaTemplate("test");
@@ -266,7 +266,7 @@ public class InterfacesOperationsToscaUtilTest {
         component.getInterfaces().put(secondInterfaceType, secondInterface);
 
         ToscaNodeType nodeType = new ToscaNodeType();
-        addInterfaceDefinitionElement(component, nodeType, false);
+        addInterfaceDefinitionElement(component, nodeType, null,false);
 
         ToscaExportHandler handler = new ToscaExportHandler(null,null,null,null,null,null, null);
         ToscaTemplate template = new ToscaTemplate("test");
index 1cc5b56..25c0d65 100644 (file)
@@ -103,7 +103,7 @@ public class InterfaceOperationTestUtils {
     }
 
     public static Map<String, InterfaceDefinition> createMockInterfaceTypeMap(String interfaceType,
-            String operationType) {
+                                                                              String operationType) {
         Map<String, Operation> operationMap = createMockOperationTypeMap(operationType);
         Map<String, InterfaceDefinition> interfaceDefinitionMap = new HashMap<>();
         interfaceDefinitionMap.put(interfaceType,
@@ -118,5 +118,4 @@ public class InterfaceOperationTestUtils {
         operationMap.put(operationType, operation);
         return operationMap;
     }
-
 }
index 33515c3..6acdb32 100644 (file)
@@ -122,12 +122,13 @@ public enum ActionStatus {
 
     //InterfaceOperation
     INTERFACE_OPERATION_NOT_FOUND, INTERFACE_OPERATION_NAME_ALREADY_IN_USE, INTERFACE_OPERATION_NAME_MANDATORY,
-    INTERFACE_OPERATION_NAME_INVALID, INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
+    INTERFACE_OPERATION_NAME_INVALID, INTERFACE_OPERATION_DESCRIPTION_MAX_LENGTH, INTERFACE_OPERATION_INPUT_NAME_ALREADY_IN_USE,
     INTERFACE_OPERATION_OUTPUT_NAME_ALREADY_IN_USE, INTERFACE_OPERATION_NOT_DELETED,
     INTERFACE_OPERATION_MAPPED_OUTPUT_MODIFIED,
     INTERFACE_OPERATION_INPUT_NAME_MANDATORY, INTERFACE_OPERATION_OUTPUT_NAME_MANDATORY,
     INTERFACE_OPERATION_INPUT_PROPERTY_NOT_FOUND_IN_COMPONENT, INTERFACE_OPERATION_INVALID_FOR_LOCAL_TYPE,
     INTERFACE_OPERATION_INVALID_FOR_GLOBAL_TYPE,
+    PROPERTY_USED_BY_OPERATION, DECLARED_INPUT_USED_BY_OPERATION,
 
     //NodeFilter
     NODE_FILTER_NOT_FOUND,
index 91c1d96..994b2f7 100644 (file)
                        <groupId>io.netty</groupId>
                        <artifactId>netty-all</artifactId>
                </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-collections4</artifactId>
+            <version>${commons.collections.version}</version>
+        </dependency>
 
                <dependency>
                        <groupId>io.netty</groupId>
                        <artifactId>netty-handler</artifactId>
                </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-collections4</artifactId>
+            <version>4.1</version>
+        </dependency>
 
        </dependencies>
        <build>
index 7c53688..24386bc 100644 (file)
@@ -25,17 +25,19 @@ import com.google.common.collect.Maps;
 import org.apache.commons.collections.MapUtils;
 import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.dao.utils.MapUtil;
+import org.openecomp.sdc.be.datatypes.elements.*;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.model.category.CategoryDefinition;
 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.Collections.emptyList;
-import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.PolicyDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType;
-import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
-import java.util.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
@@ -45,37 +47,38 @@ import static java.util.stream.Collectors.toMap;
 import static org.apache.commons.collections.CollectionUtils.isEmpty;
 import static org.apache.commons.collections.MapUtils.isEmpty;
 
-public abstract class Component {
-
-    private ComponentMetadataDefinition componentMetadataDefinition;
-    private Map<String, ArtifactDefinition> artifacts;
-    private Map<String, ArtifactDefinition> deploymentArtifacts;
-    private Map<String, ArtifactDefinition> toscaArtifacts;
-    private List<CategoryDefinition> categories;
-    private List<ComponentInstance> componentInstances;
-    private List<RequirementCapabilityRelDef> componentInstancesRelations;
-    private Map<String, List<ComponentInstanceInput>> componentInstancesInputs;
-    private Map<String, List<ComponentInstanceProperty>> componentInstancesProperties;
-    private Map<String, List<ComponentInstanceProperty>> componentInstancesAttributes;
-    private Map<String, List<CapabilityDefinition>> capabilities;
-    private Map<String, List<RequirementDefinition>> requirements;
-    private List<InputDefinition> inputs;
-    private List<GroupDefinition> groups;
-    private Map<String, PolicyDefinition> policies;
-    private String derivedFromGenericType;
-    private String derivedFromGenericVersion;
-    private String toscaType;
-    protected List<AdditionalInformationDefinition> additionalInformation;
-    protected List<PropertyDefinition> properties;
-    private Map<String, InterfaceDefinition> interfaces;
-
-    public Map<String, InterfaceDefinition> getInterfaces() {
-        return interfaces;
-    }
-
-    public void setInterfaces(Map<String, InterfaceDefinition> interfaces) {
-        this.interfaces = interfaces;
-    }
+public abstract class Component implements PropertiesOwner {
+
+       private ComponentMetadataDefinition componentMetadataDefinition;
+       private Map<String, ArtifactDefinition> artifacts;
+       private Map<String, ArtifactDefinition> deploymentArtifacts;
+       private Map<String, ArtifactDefinition> toscaArtifacts;
+       private List<CategoryDefinition> categories;
+       private List<ComponentInstance> componentInstances;
+       private List<RequirementCapabilityRelDef> componentInstancesRelations;
+       private Map<String, List<ComponentInstanceInput>> componentInstancesInputs;
+       private Map<String, List<ComponentInstanceProperty>> componentInstancesProperties;
+       private Map<String, List<ComponentInstanceProperty>> componentInstancesAttributes;
+       private Map<String, List<CapabilityDefinition>> capabilities;
+       private Map<String, List<RequirementDefinition>> requirements;
+       private Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces;
+       private List<InputDefinition> inputs;
+       private List<GroupDefinition> groups;
+       private Map<String, PolicyDefinition> policies;
+       private String derivedFromGenericType;
+       private String derivedFromGenericVersion;
+       private String toscaType;
+       protected List<AdditionalInformationDefinition> additionalInformation;
+       protected List<PropertyDefinition> properties;
+       private Map<String, InterfaceDefinition> interfaces;
+
+       public Map<String, InterfaceDefinition> getInterfaces() {
+               return interfaces;
+       }
+
+       public void setInterfaces(Map<String, InterfaceDefinition> interfaces) {
+               this.interfaces = interfaces;
+       }
 
     public Component(ComponentMetadataDefinition componentMetadataDefinition) {
         this.componentMetadataDefinition = componentMetadataDefinition;
@@ -119,9 +122,10 @@ public abstract class Component {
         this.toscaArtifacts = toscaArtifacts;
     }
 
-    public String getUniqueId() {
-        return componentMetadataDefinition.getMetadataDataDefinition().getUniqueId();
-    }
+       @Override
+       public String getUniqueId() {
+               return componentMetadataDefinition.getMetadataDataDefinition().getUniqueId();
+       }
 
     public void setUniqueId(String uniqueId) {
         componentMetadataDefinition.getMetadataDataDefinition().setUniqueId(uniqueId);
@@ -203,9 +207,10 @@ public abstract class Component {
         this.componentMetadataDefinition.getMetadataDataDefinition().setLastUpdaterFullName(lastUpdaterFullName);
     }
 
-    public String getName() {
-        return componentMetadataDefinition.getMetadataDataDefinition().getName();
-    }
+       @Override
+       public String getName() {
+               return componentMetadataDefinition.getMetadataDataDefinition().getName();
+       }
 
     public String getVersion() {
         return componentMetadataDefinition.getMetadataDataDefinition().getVersion();
@@ -317,9 +322,10 @@ public abstract class Component {
         this.categories = categories;
     }
 
-    public String getNormalizedName() {
-        return componentMetadataDefinition.getMetadataDataDefinition().getNormalizedName();
-    }
+       @Override
+       public String getNormalizedName() {
+               return componentMetadataDefinition.getMetadataDataDefinition().getNormalizedName();
+       }
 
     public void setNormalizedName(String normalizedName) {
         componentMetadataDefinition.getMetadataDataDefinition().setNormalizedName(normalizedName);
@@ -355,7 +361,7 @@ public abstract class Component {
     public List<ComponentInstance> getComponentInstances() {
         return componentInstances;
     }
-    
+
     public List<ComponentInstance> safeGetComponentInstances() {
        if(componentInstances != null) {
                return componentInstances;
@@ -418,10 +424,14 @@ public abstract class Component {
         return this.safeGetComponentInstanceEntity(comptInstanceId, this.componentInstancesInputs);
     }
 
-    public void setComponentInstancesProperties(
-            Map<String, List<ComponentInstanceProperty>> resourceInstancesProperties) {
-        this.componentInstancesProperties = resourceInstancesProperties;
-    }
+       public List<ComponentInstanceInterface> safeGetComponentInstanceInterfaces(String cmptInstacneId) {
+               return this.safeGetComponentInstanceEntity(cmptInstacneId, this.componentInstancesInterfaces);
+       }
+
+       public void setComponentInstancesProperties(
+                       Map<String, List<ComponentInstanceProperty>> resourceInstancesProperties) {
+               this.componentInstancesProperties = resourceInstancesProperties;
+       }
 
     public Boolean getIsDeleted() {
         return componentMetadataDefinition.getMetadataDataDefinition().isDeleted();
@@ -515,58 +525,69 @@ public abstract class Component {
                      .findAny();
     }
 
-    public void setGroups(List<GroupDefinition> groups) {
-        this.groups = groups;
-    }
+       public Map<String, List<ComponentInstanceInterface>> getComponentInstancesInterfaces() {
+               return componentInstancesInterfaces;
+       }
 
-    public void addGroups(List<GroupDefinition> groupsToAdd) {
-        if (groups == null) {
-            groups = new ArrayList<>();
-        }
-        groups.addAll(groupsToAdd);
-    }
+       public void setComponentInstancesInterfaces(Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces) {
+               this.componentInstancesInterfaces = componentInstancesInterfaces;
+       }
 
-    public Map<String, PolicyDefinition> getPolicies() {
-        return policies;
-    }
+       public void setGroups(List<GroupDefinition> groups) {
+               this.groups = groups;
+       }
 
-    public void setPolicies(Map<String, PolicyDefinition> policies) {
-        this.policies = policies;
+  public void addGroups(List<GroupDefinition> groupsToAdd) {
+    if (groups == null) {
+      groups = new ArrayList<>();
     }
+    groups.addAll(groupsToAdd);
+  }
 
-    public List<PropertyDefinition> getProperties() {
-        return properties;
-    }
+       public Map<String, PolicyDefinition> getPolicies() {
+               return policies;
+       }
 
-    public void setProperties(List<PropertyDefinition> properties) {
-        this.properties = properties;
+    public void setPolicies(Map<String, PolicyDefinition> policies) {
+        this.policies = policies;
     }
 
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((artifacts == null) ? 0 : artifacts.hashCode());
-        result = prime * result + ((categories == null) ? 0 : categories.hashCode());
-        result = prime * result + ((componentMetadataDefinition == null) ? 0 : componentMetadataDefinition.hashCode());
-        result = prime * result + ((deploymentArtifacts == null) ? 0 : deploymentArtifacts.hashCode());
-        result = prime * result + ((capabilities == null) ? 0 : capabilities.hashCode());
-        result = prime * result + ((requirements == null) ? 0 : requirements.hashCode());
-        result = prime * result + ((componentInstances == null) ? 0 : componentInstances.hashCode());
-        result = prime * result
-                + ((componentInstancesProperties == null) ? 0 : componentInstancesProperties.hashCode());
-        result = prime * result
-                + ((componentInstancesAttributes == null) ? 0 : componentInstancesAttributes.hashCode());
-        result = prime * result + ((componentInstancesInputs == null) ? 0 : componentInstancesInputs.hashCode());
-        result = prime * result + ((componentInstancesRelations == null) ? 0 : componentInstancesRelations.hashCode());
-        result = prime * result + ((groups == null) ? 0 : groups.hashCode());
-        result = prime * result + ((policies == null) ? 0 : policies.hashCode());
-        result = prime * result + ((derivedFromGenericType == null) ? 0 : derivedFromGenericType.hashCode());
-        result = prime * result + ((derivedFromGenericVersion == null) ? 0 : derivedFromGenericVersion.hashCode());
-        result = prime * result + ((interfaces == null) ? 0 : interfaces.hashCode());
-        result = prime * result + ((properties == null) ? 0 : properties.hashCode());
-        return result;
-    }
+       public List<PropertyDefinition> getProperties() {
+               return properties;
+       }
+
+       public void setProperties(List<PropertyDefinition> properties) {
+               this.properties = properties;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((artifacts == null) ? 0 : artifacts.hashCode());
+               result = prime * result + ((categories == null) ? 0 : categories.hashCode());
+               result = prime * result + ((componentMetadataDefinition == null) ? 0 : componentMetadataDefinition.hashCode());
+//             result = prime * result + ((creatorUserId == null) ? 0 : creatorUserId.hashCode());
+//             result = prime * result + ((creatorFullName == null) ? 0 : creatorFullName.hashCode());
+               result = prime * result + ((deploymentArtifacts == null) ? 0 : deploymentArtifacts.hashCode());
+//             result = prime * result + ((lastUpdaterUserId == null) ? 0 : lastUpdaterUserId.hashCode());
+//             result = prime * result + ((lastUpdaterFullName == null) ? 0 : lastUpdaterFullName.hashCode());
+               result = prime * result + ((capabilities == null) ? 0 : capabilities.hashCode());
+               result = prime * result + ((requirements == null) ? 0 : requirements.hashCode());
+               result = prime * result + ((componentInstances == null) ? 0 : componentInstances.hashCode());
+               result = prime * result
+                               + ((componentInstancesProperties == null) ? 0 : componentInstancesProperties.hashCode());
+               result = prime * result
+                               + ((componentInstancesAttributes == null) ? 0 : componentInstancesAttributes.hashCode());
+               result = prime * result + ((componentInstancesInputs == null) ? 0 : componentInstancesInputs.hashCode());
+               result = prime * result + ((componentInstancesRelations == null) ? 0 : componentInstancesRelations.hashCode());
+               result = prime * result + ((groups == null) ? 0 : groups.hashCode());
+               result = prime * result + ((policies == null) ? 0 : policies.hashCode());
+               result = prime * result + ((derivedFromGenericType == null) ? 0 : derivedFromGenericType.hashCode());
+               result = prime * result + ((derivedFromGenericVersion == null) ? 0 : derivedFromGenericVersion.hashCode());
+               result = prime * result + ((interfaces == null) ? 0 : interfaces.hashCode());
+               return result;
+       }
 
     @Override
     public boolean equals(Object obj) {
index 306992d..9d0877d 100644 (file)
@@ -31,6 +31,7 @@ public class ComponentInstInputsMap {
 
     private Map<String, List<ComponentInstancePropInput>> componentInstanceInputsMap;
     private Map<String, List<ComponentInstancePropInput>> componentInstanceProperties;
+    private Map<String, List<ComponentInstancePropInput>> serviceProperties;
     private Map<String, List<ComponentInstancePropInput>> policyProperties;
     private Map<String, List<ComponentInstancePropInput>> groupProperties;
 
@@ -44,6 +45,9 @@ public class ComponentInstInputsMap {
         if (isNotEmpty(policyProperties)) {
             return singleMapEntry(policyProperties);
         }
+        if(isNotEmpty(serviceProperties)) {
+            return singleMapEntry(serviceProperties);
+        }
         if (isNotEmpty(groupProperties)) {
             return singleMapEntry(groupProperties);
         }
@@ -79,6 +83,15 @@ public class ComponentInstInputsMap {
         this.policyProperties = policyProperties;
     }
 
+    public Map<String, List<ComponentInstancePropInput>> getServiceProperties() {
+        return serviceProperties;
+    }
+
+    public void setServiceProperties(
+        Map<String, List<ComponentInstancePropInput>> serviceProperties) {
+        this.serviceProperties = serviceProperties;
+    }
+
     public Map<String, List<ComponentInstancePropInput>> getGroupProperties() {
         return groupProperties;
     }
index ef9b409..0d18676 100644 (file)
 
 package org.openecomp.sdc.be.model;
 
+import org.apache.commons.collections.MapUtils;
 import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PropertiesOwner;
 import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
 
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -36,6 +38,8 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement
     private Map<String, ArtifactDefinition> deploymentArtifacts;
     private Map<String, ArtifactDefinition> artifacts;
     private List<GroupInstance> groupInstances;
+    private Map<String, Object> interfaces;
+    private List<PropertyDefinition> properties;
     private CINodeFilterDataDefinition nodeFilter;
 
     public ComponentInstance() {
@@ -109,6 +113,30 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement
         return safeGetInformationalArtifacts().get(artifactLabel) != null;
     }
 
+    public Map<String, Object> getInterfaces() {
+        return interfaces;
+    }
+
+    public void setInterfaces(Map<String, Object> interfaces) {
+        this.interfaces = interfaces;
+    }
+
+    public void addInterface(String interfaceName, Object interfaceDefinition) {
+        if(MapUtils.isEmpty(this.interfaces)) {
+            this.interfaces = new HashMap<>();
+        }
+
+        this.interfaces.put(interfaceName, interfaceDefinition);
+    }
+
+    public List<PropertyDefinition> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(List<PropertyDefinition> properties) {
+        this.properties = properties;
+    }
+
     public CINodeFilterDataDefinition getNodeFilter() {
         return nodeFilter;
     }
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceInterface.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstanceInterface.java
new file mode 100644 (file)
index 0000000..5482a51
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.be.model;
+
+import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.InterfaceInstanceDataDefinition;
+
+public class ComponentInstanceInterface extends InterfaceDefinition {
+  private String interfaceId;
+  private InterfaceInstanceDataDefinition interfaceInstanceDataDefinition;
+
+  public ComponentInstanceInterface(String interfaceId,
+                                    InterfaceInstanceDataDefinition interfaceInstanceDataDefinition) {
+    this.interfaceId = interfaceId;
+    this.interfaceInstanceDataDefinition = interfaceInstanceDataDefinition;
+  }
+
+  public ComponentInstanceInterface(String interfaceId, InterfaceDataDefinition interfaceDataDefinition) {
+    super(interfaceDataDefinition);
+    this.interfaceId = interfaceId;
+  }
+
+  public String getInterfaceId() {
+    return interfaceId;
+  }
+
+  public void setInterfaceId(String interfaceId) {
+    this.interfaceId = interfaceId;
+  }
+
+  public InterfaceInstanceDataDefinition getInterfaceInstanceDataDefinition() {
+    return interfaceInstanceDataDefinition;
+  }
+
+  public void setInterfaceInstanceDataDefinition(
+      InterfaceInstanceDataDefinition interfaceInstanceDataDefinition) {
+    this.interfaceInstanceDataDefinition = interfaceInstanceDataDefinition;
+  }
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/InterfaceInstanceDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/InterfaceInstanceDefinition.java
new file mode 100644 (file)
index 0000000..d16370d
--- /dev/null
@@ -0,0 +1,39 @@
+package org.openecomp.sdc.be.model;
+
+import org.apache.commons.collections.MapUtils;
+import org.openecomp.sdc.be.datatypes.elements.InterfaceInstanceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationInstance;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+public class InterfaceInstanceDefinition extends InterfaceInstanceDataDefinition {
+
+  public InterfaceInstanceDefinition(InterfaceInstanceDataDefinition inter) {
+    super(inter);
+  }
+
+  public InterfaceInstanceDefinition(){}
+
+  public Map<String, Object> getInputs() {
+    return this.inputs;
+  }
+
+  public void setInputs(
+      Map<String, Object> inputs) {
+    this.inputs = inputs;
+  }
+
+  public Map<String, OperationInstance> getOperations() {
+    return operations;
+  }
+
+  public void addInstanceOperation(String operationName, OperationInstance operation) {
+    if(MapUtils.isEmpty(this.operations)) {
+      this.operations = new HashMap<>();
+    }
+
+    this.operations.put(operationName, operation);
+  }
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceDataDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceDataDefinition.java
new file mode 100644 (file)
index 0000000..c58131f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.be.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapDataDefinition;
+
+import java.util.Map;
+
+public class MapInterfaceDataDefinition extends MapDataDefinition<InterfaceDataDefinition> {
+
+  public MapInterfaceDataDefinition() {
+
+  }
+
+  @JsonCreator
+  public MapInterfaceDataDefinition(Map<String, InterfaceDataDefinition > mapToscaDataDefinition) {
+    super(mapToscaDataDefinition);
+  }
+
+  @JsonValue
+  @Override
+  public Map<String, InterfaceDataDefinition> getMapToscaDataDefinition() {
+    return mapToscaDataDefinition;
+  }
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceInstanceDataDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/MapInterfaceInstanceDataDefinition.java
new file mode 100644 (file)
index 0000000..6efa0ed
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.be.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import org.openecomp.sdc.be.datatypes.elements.InterfaceInstanceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapDataDefinition;
+
+import java.util.Map;
+
+public class MapInterfaceInstanceDataDefinition extends
+        MapDataDefinition<InterfaceInstanceDataDefinition> {
+
+  public MapInterfaceInstanceDataDefinition() {
+
+  }
+
+  @JsonCreator
+  public MapInterfaceInstanceDataDefinition(Map<String, InterfaceInstanceDataDefinition> mapToscaDataDefinition) {
+    super(mapToscaDataDefinition);
+  }
+
+  @JsonValue
+  @Override
+  public Map<String, InterfaceInstanceDataDefinition> getMapToscaDataDefinition() {
+    return mapToscaDataDefinition;
+  }
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/OperationInstance.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/OperationInstance.java
new file mode 100644 (file)
index 0000000..fb958eb
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.be.model;
+
+import org.openecomp.sdc.be.datatypes.elements.OperationImplementation;
+
+import java.util.Map;
+import java.util.Objects;
+
+public class OperationInstance/* extends Operation*/ {
+  private OperationImplementation implementation;
+  private Map<String, Object> inputs;
+
+
+  public OperationImplementation getImplementation() {
+    return implementation;
+  }
+
+  public void setImplementation(OperationImplementation implementation) {
+    this.implementation = implementation;
+  }
+
+  public Map<String, Object> getInputs() {
+    return inputs;
+  }
+
+  public void setInputs(Map<String, Object> inputs) {
+    this.inputs = inputs;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof OperationInstance)) {
+      return false;
+    }
+    OperationInstance that = (OperationInstance) o;
+    return Objects.equals(implementation, that.implementation) &&
+        Objects.equals(inputs, that.inputs);
+  }
+
+  @Override
+  public int hashCode() {
+
+    return Objects.hash(implementation, inputs);
+  }
+}
index f3996ed..0603538 100644 (file)
@@ -42,12 +42,15 @@ public class Resource extends Component {
 
     private List<PropertyDefinition> attributes;
 
-    private List<String> defaultCapabilities;
-    
-    public Resource() {
-        super(new ResourceMetadataDefinition());
-        this.getComponentMetadataDefinition().getMetadataDataDefinition().setComponentType(ComponentTypeEnum.RESOURCE);
-    }
+  private Map<String, InterfaceInstanceDefinition> instInterfaces;
+
+  private List<String> defaultCapabilities;
+
+  public Resource() {
+    super(new ResourceMetadataDefinition());
+    this.getComponentMetadataDefinition().getMetadataDataDefinition()
+        .setComponentType(ComponentTypeEnum.RESOURCE);
+  }
 
     public Resource(ComponentMetadataDefinition componentMetadataDefinition) {
         super(componentMetadataDefinition);
@@ -101,10 +104,20 @@ public class Resource extends Component {
         this.attributes = attributes;
     }
 
-    public Boolean isAbstract() {
-        return ((ResourceMetadataDataDefinition) getComponentMetadataDefinition().getMetadataDataDefinition())
-                .isAbstract();
-    }
+  public Map<String, InterfaceInstanceDefinition> getInstInterfaces() {
+    return instInterfaces;
+  }
+
+  public void setInstInterfaces(
+      Map<String, InterfaceInstanceDefinition> instInterfaces) {
+    this.instInterfaces = instInterfaces;
+  }
+
+  public Boolean isAbstract() {
+    return ((ResourceMetadataDataDefinition) getComponentMetadataDefinition()
+        .getMetadataDataDefinition())
+        .isAbstract();
+  }
 
     public void setAbstract(Boolean isAbstract) {
         ((ResourceMetadataDataDefinition) getComponentMetadataDefinition().getMetadataDataDefinition())
index 823abab..3c1ca26 100644 (file)
@@ -22,6 +22,10 @@ package org.openecomp.sdc.be.model;
 
 import org.apache.commons.lang.StringUtils;
 import org.openecomp.sdc.be.datatypes.components.ComponentMetadataDataDefinition;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import org.openecomp.sdc.be.datatypes.components.ServiceMetadataDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
@@ -51,7 +55,6 @@ public class Service extends Component {
        private Map<String, ArtifactDefinition> serviceApiArtifacts;
        private Map<String, ForwardingPathDataDefinition> forwardingPaths;
 
-
        public Map<String, ArtifactDefinition> getServiceApiArtifacts() {
                return serviceApiArtifacts;
        }
index 0d7b14a..ac9f196 100644 (file)
@@ -25,6 +25,8 @@ 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.MapInterfaceDataDefinition;
+import org.openecomp.sdc.be.model.MapInterfaceInstanceDataDefinition;
 import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum;
 
 import java.util.HashMap;
@@ -54,6 +56,8 @@ public class TopologyTemplate extends ToscaElement{
     private Map<String, MapArtifactDataDefinition> instDeploymentArtifacts;
     private Map<String, MapArtifactDataDefinition> instanceArtifacts;
     private Map<String, InterfaceDataDefinition> interfaces;
+    private Map<String, MapInterfaceInstanceDataDefinition> instInterfaces;
+    private Map<String, MapInterfaceDataDefinition> componentInstInterfaces;
     
     //Component Instances External References (instanceId -> ExternalRefsMap)
     //-----------------------------------------------------------------------
@@ -76,6 +80,43 @@ public class TopologyTemplate extends ToscaElement{
       this.interfaces = interfaces;
     }
 
+    public Map<String, MapInterfaceInstanceDataDefinition> getInstInterfaces() {
+        return instInterfaces;
+    }
+
+    public void setInstInterfaces(
+            Map<String, MapInterfaceInstanceDataDefinition> instInterfaces) {
+        this.instInterfaces = instInterfaces;
+    }
+
+    public void addInstInterface(String compId, MapInterfaceInstanceDataDefinition
+            mapInterfaceInstanceDataDefinition) {
+        if(MapUtils.isEmpty(this.instInterfaces)) {
+            this.instInterfaces = new HashMap<>();
+        }
+
+        this.instInterfaces.put(compId, mapInterfaceInstanceDataDefinition);
+    }
+
+    public Map<String, MapInterfaceDataDefinition> getComponentInstInterfaces() {
+        return componentInstInterfaces;
+    }
+
+    public void setComponentInstInterfaces(
+            Map<String, MapInterfaceDataDefinition> componentInstInterfaces) {
+        this.componentInstInterfaces = componentInstInterfaces;
+    }
+
+    public void addComponentInstanceInterfaceMap(String componentInstanceId, MapInterfaceDataDefinition
+            mapInterfaceDataDefinition) {
+        if(MapUtils.isEmpty(this.componentInstInterfaces)) {
+            this.componentInstInterfaces = new HashMap<>();
+        }
+
+        this.componentInstInterfaces.put(componentInstanceId, mapInterfaceDataDefinition);
+    }
+
+
     public Map<String, PropertyDataDefinition> getInputs() {
         return inputs;
     }
index 5c06e97..d8a4fc4 100644 (file)
@@ -25,6 +25,7 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
 import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
@@ -35,8 +36,6 @@ import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
 import org.openecomp.sdc.be.datatypes.elements.*;
 import org.openecomp.sdc.be.datatypes.enums.*;
 import org.openecomp.sdc.be.model.*;
-import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
-import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
@@ -971,7 +970,35 @@ public class ToscaOperationFacade {
 
     }
 
-    public Either<List<InputDefinition>, StorageOperationStatus> updateInputsToComponent(List<InputDefinition> inputs, String componentId) {
+       public Either<List<InputDefinition>, StorageOperationStatus> getComponentInputs(String componentId) {
+
+               Either<GraphVertex, TitanOperationStatus> getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse);
+               if (getVertexEither.isRight()) {
+                       log.debug("Couldn't fetch component with and unique id {}, error: {}", componentId, getVertexEither.right().value());
+                       return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(getVertexEither.right().value()));
+
+               }
+
+               Either<ToscaElement, StorageOperationStatus> toscaElement =
+                               topologyTemplateOperation.getToscaElement(componentId);
+               if(toscaElement.isRight()) {
+                       return Either.right(toscaElement.right().value());
+               }
+
+               TopologyTemplate topologyTemplate = (TopologyTemplate) toscaElement.left().value();
+
+               Map<String, PropertyDataDefinition> inputsMap = topologyTemplate.getInputs();
+
+               List<InputDefinition> inputs = new ArrayList<>();
+               if(MapUtils.isNotEmpty(inputsMap)) {
+                       inputs =
+                                       inputsMap.values().stream().map(p -> new InputDefinition(p)).collect(Collectors.toList());
+               }
+
+               return Either.left(inputs);
+       }
+
+       public Either<List<InputDefinition>, StorageOperationStatus> updateInputsToComponent(List<InputDefinition> inputs, String componentId) {
 
         Either<GraphVertex, TitanOperationStatus> getVertexEither = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse);
         if (getVertexEither.isRight()) {
@@ -1135,7 +1162,7 @@ public class ToscaOperationFacade {
         }
         return Either.left(instProperties);
     }
-    
+
     public Either<Map<String, List<ComponentInstanceProperty>>, StorageOperationStatus> addComponentInstancePropertiesToComponent(Component containerComponent, Map<String, List<ComponentInstanceProperty>> instProperties) {
         requireNonNull(instProperties);
         StorageOperationStatus status;
@@ -1984,91 +2011,97 @@ public class ToscaOperationFacade {
         return nodeTemplateOperation.generateCustomizationUUIDOnInstanceGroup(componentId, instanceId, groupInstances);
     }
 
-    /*
-     * adds property to a resource
-     * @warn this method has SIDE EFFECT on ownerId ,use it with caution
-     * */
-    public Either<PropertyDefinition, StorageOperationStatus> addPropertyToResource(String propertyName, PropertyDefinition newPropertyDefinition, Resource resource) {
-
-        Either<PropertyDefinition, StorageOperationStatus> result = null;
-        Either<Component, StorageOperationStatus> getUpdatedComponentRes = null;
-        newPropertyDefinition.setName(propertyName);
-        StorageOperationStatus status = getToscaElementOperation(resource).addToscaDataToToscaElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME);
-        if (status != StorageOperationStatus.OK) {
-            CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_ADD_THE_PROPERTY_TO_THE_RESOURCE_STATUS_IS, propertyName, resource.getName(), status);
-            result = Either.right(status);
-        }
-        if (result == null) {
-            ComponentParametersView filter = new ComponentParametersView(true);
-            filter.setIgnoreProperties(false);
-            getUpdatedComponentRes = getToscaElement(resource.getUniqueId(), filter);
-            if (getUpdatedComponentRes.isRight()) {
-                CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_UPDATED_RESOURCE_STATUS_IS, resource.getUniqueId(), getUpdatedComponentRes.right().value());
-                result = Either.right(status);
-            }
-        }
-        if (result == null) {
-            PropertyDefinition newProperty = null;
-            List<PropertyDefinition> properties = ((Resource) getUpdatedComponentRes.left().value()).getProperties();
-            if (CollectionUtils.isNotEmpty(properties)) {
-                Optional<PropertyDefinition> newPropertyOptional = properties.stream().filter(p -> p.getName().equals(propertyName)).findAny();
-                if (newPropertyOptional.isPresent()) {
-                    newProperty = newPropertyOptional.get();
-                }
-            }
-            if (newProperty == null) {
-                CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_FIND_RECENTLY_ADDED_PROPERTY_ON_THE_RESOURCE_STATUS_IS, propertyName, resource.getUniqueId(), StorageOperationStatus.NOT_FOUND);
-                result = Either.right(StorageOperationStatus.NOT_FOUND);
-            } else {
-                result = Either.left(newProperty);
-            }
-        }
-        return result;
-    }
-
-    public StorageOperationStatus deletePropertyOfResource(Resource resource, String propertyName) {
-        return getToscaElementOperation(resource).deleteToscaDataElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, propertyName, JsonPresentationFields.NAME);
-    }
-
-    public StorageOperationStatus deleteAttributeOfResource(Component component, String attributeName) {
-        return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.ATTRIBUTES, VertexTypeEnum.ATTRIBUTES, attributeName, JsonPresentationFields.NAME);
-    }
+               public Either<PropertyDefinition, StorageOperationStatus> addPropertyToComponent(String propertyName,
+                                                                                                                                                                        PropertyDefinition newPropertyDefinition,
+                                                                                                                                                                        Component component) {
+
+               Either<PropertyDefinition, StorageOperationStatus> result = null;
+               Either<Component, StorageOperationStatus> getUpdatedComponentRes = null;
+               newPropertyDefinition.setName(propertyName);
+
+               StorageOperationStatus status = getToscaElementOperation(component)
+                               .addToscaDataToToscaElement(component.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME);
+               if (status != StorageOperationStatus.OK) {
+                       CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the component {}. Status is {}. ", propertyName, component.getName(), status);
+                       result = Either.right(status);
+               }
+               if (result == null) {
+                       ComponentParametersView filter = new ComponentParametersView(true);
+                       filter.setIgnoreProperties(false);
+                       filter.setIgnoreInputs(false);
+                       getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter);
+                       if (getUpdatedComponentRes.isRight()) {
+                               CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated component {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value());
+                               result = Either.right(status);
+                       }
+               }
+               if (result == null) {
+                       PropertyDefinition newProperty = null;
+                       List<PropertyDefinition> properties =
+                                       (getUpdatedComponentRes.left().value()).getProperties();
+                       if (CollectionUtils.isNotEmpty(properties)) {
+                               Optional<PropertyDefinition> propertyOptional = properties.stream().filter(
+                                               propertyEntry -> propertyEntry.getName().equals(propertyName)).findAny();
+                               if (propertyOptional.isPresent()) {
+                                       newProperty = propertyOptional.get();
+                               }
+                       }
+                       if (newProperty == null) {
+                               CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the component {}. Status is {}. ", propertyName, component.getUniqueId(), StorageOperationStatus.NOT_FOUND);
+                               result = Either.right(StorageOperationStatus.NOT_FOUND);
+                       } else {
+                               result = Either.left(newProperty);
+                       }
+               }
+               return result;
+       }
+       public StorageOperationStatus deletePropertyOfComponent(Component component, String propertyName) {
+               return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, propertyName, JsonPresentationFields.NAME);
+       }
+
+       public StorageOperationStatus deleteAttributeOfResource(Component component, String attributeName) {
+               return getToscaElementOperation(component).deleteToscaDataElement(component.getUniqueId(), EdgeLabelEnum.ATTRIBUTES, VertexTypeEnum.ATTRIBUTES, attributeName, JsonPresentationFields.NAME);
+       }
 
     public StorageOperationStatus deleteInputOfResource(Component resource, String inputName) {
         return getToscaElementOperation(resource).deleteToscaDataElement(resource.getUniqueId(), EdgeLabelEnum.INPUTS, VertexTypeEnum.INPUTS, inputName, JsonPresentationFields.NAME);
     }
 
-    public Either<PropertyDefinition, StorageOperationStatus> updatePropertyOfResource(Resource resource, PropertyDefinition newPropertyDefinition) {
-
-        Either<Component, StorageOperationStatus> getUpdatedComponentRes = null;
-        Either<PropertyDefinition, StorageOperationStatus> result = null;
-        StorageOperationStatus status = getToscaElementOperation(resource).updateToscaDataOfToscaElement(resource.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME);
-        if (status != StorageOperationStatus.OK) {
-            CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_ADD_THE_PROPERTY_TO_THE_RESOURCE_STATUS_IS, newPropertyDefinition.getName(), resource.getName(), status);
-            result = Either.right(status);
-        }
-        if (result == null) {
-            ComponentParametersView filter = new ComponentParametersView(true);
-            filter.setIgnoreProperties(false);
-            getUpdatedComponentRes = getToscaElement(resource.getUniqueId(), filter);
-            if (getUpdatedComponentRes.isRight()) {
-                CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_UPDATED_RESOURCE_STATUS_IS, resource.getUniqueId(), getUpdatedComponentRes.right().value());
-                result = Either.right(status);
-            }
-        }
-        if (result == null) {
-            Optional<PropertyDefinition> newProperty = ((Resource) getUpdatedComponentRes.left().value()).getProperties().stream().filter(p -> p.getName().equals(newPropertyDefinition.getName())).findAny();
-            if (newProperty.isPresent()) {
-                result = Either.left(newProperty.get());
-            } else {
-                CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_FIND_RECENTLY_ADDED_PROPERTY_ON_THE_RESOURCE_STATUS_IS, newPropertyDefinition.getName(), resource.getUniqueId(), StorageOperationStatus.NOT_FOUND);
-                result = Either.right(StorageOperationStatus.NOT_FOUND);
-            }
-        }
-        return result;
-    }
-
-    public Either<PropertyDefinition, StorageOperationStatus> addAttributeOfResource(Component component, PropertyDefinition newAttributeDef) {
+       public Either<PropertyDefinition, StorageOperationStatus> updatePropertyOfComponent(Component component,
+                                                                                                                                                                               PropertyDefinition newPropertyDefinition) {
+
+               Either<Component, StorageOperationStatus> getUpdatedComponentRes = null;
+               Either<PropertyDefinition, StorageOperationStatus> result = null;
+               StorageOperationStatus status = getToscaElementOperation(component).updateToscaDataOfToscaElement(component.getUniqueId(), EdgeLabelEnum.PROPERTIES, VertexTypeEnum.PROPERTIES, newPropertyDefinition, JsonPresentationFields.NAME);
+               if (status != StorageOperationStatus.OK) {
+                       CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add the property {} to the resource {}. Status is {}. ", newPropertyDefinition.getName(), component.getName(), status);
+                       result = Either.right(status);
+               }
+               if (result == null) {
+                       ComponentParametersView filter = new ComponentParametersView(true);
+                       filter.setIgnoreProperties(false);
+                       getUpdatedComponentRes = getToscaElement(component.getUniqueId(), filter);
+                       if (getUpdatedComponentRes.isRight()) {
+                               CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to get updated resource {}. Status is {}. ", component.getUniqueId(), getUpdatedComponentRes.right().value());
+                               result = Either.right(status);
+                       }
+               }
+               if (result == null) {
+                       Optional<PropertyDefinition> newProperty = (getUpdatedComponentRes.left().value())
+                                       .getProperties().stream().filter(p -> p.getName().equals(newPropertyDefinition.getName())).findAny();
+                       if (newProperty.isPresent()) {
+                               result = Either.left(newProperty.get());
+                       } else {
+                               CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to find recently added property {} on the resource {}. Status is {}. ", newPropertyDefinition.getName(), component.getUniqueId(), StorageOperationStatus.NOT_FOUND);
+                               result = Either.right(StorageOperationStatus.NOT_FOUND);
+                       }
+               }
+               return result;
+       }
+
+
+
+       public Either<PropertyDefinition, StorageOperationStatus> addAttributeOfResource(Component component, PropertyDefinition newAttributeDef) {
 
         Either<Component, StorageOperationStatus> getUpdatedComponentRes = null;
         Either<PropertyDefinition, StorageOperationStatus> result = null;
@@ -2263,10 +2296,11 @@ public class ToscaOperationFacade {
                 .orElse(StorageOperationStatus.NOT_FOUND);
     }
 
-    public StorageOperationStatus updateComponentCalculatedCapabilitiesProperties(Component containerComponent) {
-        Map<String, MapCapabilityProperty> MapCapabilityPropertyMap = convertComponentCapabilitiesProperties(containerComponent);
-        return nodeTemplateOperation.overrideComponentCapabilitiesProperties(containerComponent, MapCapabilityPropertyMap);
-    }
+       public StorageOperationStatus updateComponentCalculatedCapabilitiesProperties(Component containerComponent) {
+               Map<String, MapCapabilityProperty> mapCapabiltyPropertyMap =
+        convertComponentCapabilitiesProperties(containerComponent);
+               return nodeTemplateOperation.overrideComponentCapabilitiesProperties(containerComponent, mapCapabiltyPropertyMap);
+       }
 
     public StorageOperationStatus deleteAllCalculatedCapabilitiesRequirements(String topologyTemplateId) {
         StorageOperationStatus status = topologyTemplateOperation.removeToscaData(topologyTemplateId, EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES);
@@ -2309,11 +2343,24 @@ public class ToscaOperationFacade {
         return topologyTemplateOperation.getComponentInstanceCapabilityProperties(componentId, instanceId, capabilityName, capabilityType, ownerId);
     }
 
-    private Map<String, MapCapabilityProperty> convertComponentCapabilitiesProperties(Component currComponent) {
-        Map<String, MapCapabilityProperty> map = ModelConverter.extractCapabilityPropertiesFromGroups(currComponent.getGroups(), true);
-        map.putAll(ModelConverter.extractCapabilityProperteisFromInstances(currComponent.getComponentInstances(), true));
-        return map;
-    }
+       private MapInterfaceDataDefinition convertComponentInstanceInterfaces(Component currComponent,
+                                                                                                                                                                                                                                                                                               String componentInstanceId) {
+               MapInterfaceDataDefinition mapInterfaceDataDefinition = new MapInterfaceDataDefinition();
+               List<ComponentInstanceInterface> componentInterface = currComponent.getComponentInstancesInterfaces().get(componentInstanceId);
+
+               if(CollectionUtils.isNotEmpty(componentInterface)) {
+                       componentInterface.stream().forEach(interfaceDef -> mapInterfaceDataDefinition.put
+                                       (interfaceDef.getUniqueId(), interfaceDef));
+               }
+
+               return mapInterfaceDataDefinition;
+       }
+
+  private Map<String, MapCapabilityProperty> convertComponentCapabilitiesProperties(Component currComponent) {
+    Map<String, MapCapabilityProperty> map = ModelConverter.extractCapabilityPropertiesFromGroups(currComponent.getGroups(), true);
+    map.putAll(ModelConverter.extractCapabilityProperteisFromInstances(currComponent.getComponentInstances(), true));
+    return map;
+  }
 
     private Optional<MapCapabilityProperty> convertComponentInstanceProperties(Component component, String instanceId) {
         return component.fetchInstanceById(instanceId)
@@ -2433,4 +2480,71 @@ public class ToscaOperationFacade {
         throw new StorageException(status);
     }
 
+    public Either<Boolean, StorageOperationStatus> isComponentInUse(String componentId) {
+        final List<EdgeLabelEnum> forbiddenEdgeLabelEnums = Arrays.asList(EdgeLabelEnum.INSTANCE_OF, EdgeLabelEnum.PROXY_OF, EdgeLabelEnum.ALLOTTED_OF);
+        Either<GraphVertex, TitanOperationStatus> vertexById = titanDao.getVertexById(componentId);
+        if (vertexById.isLeft()) {
+            for (EdgeLabelEnum edgeLabelEnum : forbiddenEdgeLabelEnums) {
+                Iterator<Edge> edgeItr = vertexById.left().value().getVertex().edges(Direction.IN, edgeLabelEnum.name());
+                if(edgeItr != null && edgeItr.hasNext()){
+                    return Either.left(true);
+                }
+            }
+        }
+        return Either.left(false);
+    }
+
+       public Either<List<Component>, StorageOperationStatus> getComponentListByInvariantUuid
+                       (String componentInvariantUuid, Map<GraphPropertyEnum, Object> additionalPropertiesToMatch) {
+
+               Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
+               if (MapUtils.isNotEmpty(additionalPropertiesToMatch)) {
+                       propertiesToMatch.putAll(additionalPropertiesToMatch);
+               }
+               propertiesToMatch.put(GraphPropertyEnum.INVARIANT_UUID, componentInvariantUuid);
+
+               Either<List<GraphVertex>, TitanOperationStatus> vertexEither = titanDao.getByCriteria(null, propertiesToMatch, JsonParseFlagEnum.ParseMetadata);
+
+               if (vertexEither.isRight()) {
+                       log.debug("Couldn't fetch metadata for component with type {} and invariantUUId {}, error: {}", componentInvariantUuid, vertexEither.right().value());
+                       return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(vertexEither.right().value()));
+               }
+               List<GraphVertex> vertexList = vertexEither.isLeft() ? vertexEither.left().value() : null;
+
+               if (vertexList == null || vertexList.isEmpty()) {
+                       log.debug("Component with invariantUUId {} was not found", componentInvariantUuid);
+                       return Either.right(StorageOperationStatus.NOT_FOUND);
+               }
+
+               ArrayList<Component> components = new ArrayList<>();
+               for (GraphVertex vertex : vertexList) {
+                       Either<Component, StorageOperationStatus> toscaElementByOperation = getToscaElementByOperation(vertex);
+                       if (toscaElementByOperation.isRight()) {
+                               log.debug("Could not fetch the following Component by Invariant UUID {}", vertex.getUniqueId());
+                               return Either.right(toscaElementByOperation.right().value());
+                       }
+                       components.add(toscaElementByOperation.left().value());
+               }
+
+               return Either.left(components);
+       }
+
+    public Either<List<Component>, StorageOperationStatus> getParentComponents(String componentId) {
+        List<Component> parentComponents = new ArrayList<>();
+        final List<EdgeLabelEnum> relationEdgeLabelEnums = Arrays.asList(EdgeLabelEnum.INSTANCE_OF, EdgeLabelEnum.PROXY_OF);
+        Either<GraphVertex, TitanOperationStatus> vertexById = titanDao.getVertexById(componentId);
+        if (vertexById.isLeft()) {
+            for (EdgeLabelEnum edgeLabelEnum : relationEdgeLabelEnums) {
+                Either<GraphVertex, TitanOperationStatus> parentVertexEither = titanDao.getParentVertex(vertexById.left().value(), edgeLabelEnum, JsonParseFlagEnum.ParseJson);
+                if(parentVertexEither.isLeft()){
+                    Either<Component, StorageOperationStatus> componentEither = getToscaElement(parentVertexEither.left().value().getUniqueId());
+                    if(componentEither.isLeft()){
+                        parentComponents.add(componentEither.left().value());
+                    }
+                }
+            }
+        }
+        return Either.left(parentComponents);
+    }
+
 }
index 569491c..6a49509 100644 (file)
@@ -22,68 +22,17 @@ package org.openecomp.sdc.be.model.jsontitan.utils;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
 import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
-import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.CompositionDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.GroupInstanceDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.MapArtifactDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
-import org.openecomp.sdc.be.datatypes.elements.MapGroupsDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.MapListRequirementDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.PolicyDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.RelationshipInstDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.*;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
-import org.openecomp.sdc.be.model.AdditionalInformationDefinition;
-import org.openecomp.sdc.be.model.ArtifactDefinition;
-import org.openecomp.sdc.be.model.CapabilityDefinition;
-import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
-import org.openecomp.sdc.be.model.Component;
-import org.openecomp.sdc.be.model.ComponentInstance;
-import org.openecomp.sdc.be.model.ComponentInstanceInput;
-import org.openecomp.sdc.be.model.ComponentInstanceProperty;
-import org.openecomp.sdc.be.model.DistributionStatusEnum;
-import org.openecomp.sdc.be.model.GroupDefinition;
-import org.openecomp.sdc.be.model.GroupInstance;
-import org.openecomp.sdc.be.model.InputDefinition;
-import org.openecomp.sdc.be.model.InterfaceDefinition;
-import org.openecomp.sdc.be.model.PolicyDefinition;
-import org.openecomp.sdc.be.model.PropertyDefinition;
-import org.openecomp.sdc.be.model.RelationshipImpl;
-import org.openecomp.sdc.be.model.RelationshipInfo;
-import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
-import org.openecomp.sdc.be.model.RequirementDefinition;
-import org.openecomp.sdc.be.model.Resource;
-import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.*;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.NodeType;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate;
 import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement;
@@ -95,6 +44,11 @@ import org.openecomp.sdc.be.resources.data.ResourceMetadataData;
 import org.openecomp.sdc.be.resources.data.ServiceMetadataData;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
 public class ModelConverter {
     public static final String CAP_PROP_DELIM = "#";
     private static final Logger log = Logger.getLogger(ModelConverter.class);
@@ -171,7 +125,11 @@ public class ModelConverter {
 
         convertComponentInstances(topologyTemplate, service);
 
-        convertInputs(topologyTemplate, service);
+               convertInputs(topologyTemplate, service);
+
+               convertProperties(topologyTemplate, service);
+
+               convertPolicies(topologyTemplate, service);
 
         convertGroups(topologyTemplate, service);
 
@@ -591,8 +549,14 @@ public class ModelConverter {
         component.setDerivedFromGenericType(toscaElement.getDerivedFromGenericType());
         component.setDerivedFromGenericVersion(toscaElement.getDerivedFromGenericVersion());
 
-        //archive
-        component.setArchived(toscaElement.isArchived() == null ? false : toscaElement.isArchived());
+               Map<String, PropertyDataDefinition> properties = toscaElement.getProperties();
+               if(MapUtils.isNotEmpty(properties)) {
+                       List<PropertyDefinition> propertiesMap = properties.values().stream().map(x -> new PropertyDefinition(x)).collect(Collectors.toList());
+                       component.setProperties(propertiesMap);
+               }
+
+               //archive
+    component.setArchived(toscaElement.isArchived() == null ? false : toscaElement.isArchived());
 
 
         //component.setArchiveTime(toscaElement.getArchiveTime() == null ? 0L : toscaElement.getArchiveTime());
@@ -632,14 +596,6 @@ public class ModelConverter {
         component.setContactId((String) toscaElement.getMetadataValue(JsonPresentationFields.CONTACT_ID));
         component.setUUID((String) toscaElement.getMetadataValue(JsonPresentationFields.UUID));
         component.setIsDeleted((Boolean) toscaElement.getMetadataValue(JsonPresentationFields.IS_DELETED));
-
-
-        Map<String, PropertyDataDefinition> properties = toscaElement.getProperties();
-        if (properties != null && !properties.isEmpty()) {
-                       List<PropertyDefinition> propertiesMap = properties.values().stream().map(PropertyDefinition::new).collect(Collectors.toList());
-            ((Resource) component).setProperties(propertiesMap);
-        }
-
         component.setToscaType(toscaElement.getToscaType().getValue());
     }
 
@@ -944,34 +900,35 @@ public class ModelConverter {
         ComponentTypeEnum componentType = component.getComponentType();
         topologyTemplate = new TopologyTemplate();
 
-        if (componentType == ComponentTypeEnum.RESOURCE) {
-            Resource resource = (Resource) component;
-            topologyTemplate.setResourceType(resource.getResourceType());
-            topologyTemplate.setMetadataValue(JsonPresentationFields.CSAR_UUID, resource.getCsarUUID());
-            topologyTemplate.setMetadataValue(JsonPresentationFields.CSAR_VERSION, resource.getCsarVersion());
-            topologyTemplate.setMetadataValue(JsonPresentationFields.IMPORTED_TOSCA_CHECKSUM, resource.getImportedToscaChecksum());
-                       convertInterfaces(resource, topologyTemplate);
-        }
-        if (componentType == ComponentTypeEnum.SERVICE) {
-            convertServiceSpecificEntities((Service) component, topologyTemplate);
-        }
-        convertCommonToscaData(component, topologyTemplate);
-        convertArtifacts(component, topologyTemplate);
+               if (componentType == ComponentTypeEnum.RESOURCE) {
+                       Resource resource = (Resource) component;
+                       topologyTemplate.setResourceType(resource.getResourceType());
+                       topologyTemplate.setMetadataValue(JsonPresentationFields.CSAR_UUID, resource.getCsarUUID());
+                       topologyTemplate.setMetadataValue(JsonPresentationFields.CSAR_VERSION, resource.getCsarVersion());
+                       topologyTemplate.setMetadataValue(JsonPresentationFields.IMPORTED_TOSCA_CHECKSUM, resource.getImportedToscaChecksum());
+                       convertTopologyTemplateInterfaces(resource, topologyTemplate);
+               }
+               if (componentType == ComponentTypeEnum.SERVICE) {
+                       convertServiceSpecificEntities((Service) component, topologyTemplate);
+               }
+               convertCommonToscaData(component, topologyTemplate);
+               convertArtifacts(component, topologyTemplate);
 
         convertAdditionalInformation(component, topologyTemplate);
         convertComponentInstances(component, topologyTemplate);
 
-        convertInputs(component, topologyTemplate);
-        convertCapabilities(component, topologyTemplate);
-        convertGroups(component, topologyTemplate);
-        convertPolicies(component, topologyTemplate);
-        convertRequirements(component, topologyTemplate);
-        convertRelationsToComposition(component, topologyTemplate);
+               convertInputs(component, topologyTemplate);
+               convertProperties(component, topologyTemplate);
+               convertCapabilities(component, topologyTemplate);
+               convertGroups(component, topologyTemplate);
+               convertPolicies(component, topologyTemplate);
+               convertRequirements(component, topologyTemplate);
+               convertRelationsToComposition(component, topologyTemplate);
 
         return topologyTemplate;
     }
 
-       private static void convertInterfaces(Resource resource, TopologyTemplate topologyTemplate) {
+       private static void convertTopologyTemplateInterfaces(Resource resource, TopologyTemplate topologyTemplate) {
                Map<String, InterfaceDefinition> interfaces = resource.getInterfaces();
                if (interfaces != null && !interfaces.isEmpty()) {
                        Map<String, InterfaceDataDefinition> copy = interfaces.entrySet().stream()
@@ -1047,17 +1004,36 @@ public class ModelConverter {
 
     }
 
-    private static void convertInputs(TopologyTemplate topologyTemplate, Component component) {
-        Map<String, PropertyDataDefinition> inputsMap = topologyTemplate.getInputs();
-        if (inputsMap != null && !inputsMap.isEmpty()) {
-                       List<InputDefinition> inputsList = inputsMap.values()
-                    .stream()
-                    .map(InputDefinition::new)
-                    .collect(Collectors.toList());
-            component.setInputs(inputsList);
-        }
+       private static void convertInputs(TopologyTemplate topologyTemplate, Component component) {
+               Map<String, PropertyDataDefinition> inputsMap = topologyTemplate.getInputs();
+               if (inputsMap != null && !inputsMap.isEmpty()) {
+      List<InputDefinition> inputsList = inputsMap.values()
+          .stream()
+          .map(InputDefinition::new)
+          .collect(Collectors.toList());
+                       component.setInputs(inputsList);
+               }
+       }
+
+       private static void convertProperties(Component component, TopologyTemplate topologyTemplate) {
+               List<PropertyDefinition> propertiesList = component.getProperties();
+               if (propertiesList != null && !propertiesList.isEmpty()) {
+                       Map<String, PropertyDataDefinition> propertiesMap = propertiesList.stream().map(i -> new PropertyDataDefinition(i)).collect(Collectors.toMap(i -> i.getName(), i -> i));
+                       topologyTemplate.setProperties(propertiesMap);
+               }
+
+       }
+
+       private static void convertProperties(TopologyTemplate topologyTemplate, Component component) {
+               Map<String, PropertyDataDefinition> proeprtiesMap = topologyTemplate.getProperties();
+               if (proeprtiesMap != null && !proeprtiesMap.isEmpty()) {
+                       Map<String, PropertyDefinition> copy = proeprtiesMap.entrySet().stream()
+                                       .collect(Collectors.toMap(entry -> entry.getKey(), entry -> new PropertyDefinition
+                                                       (entry.getValue())));
+                       component.setProperties(new ArrayList<>(copy.values()));
+               }
+       }
 
-    }
 
     private static void convertCommonToscaData(Component component, ToscaElement toscaElement) {
         toscaElement.setUUID(component.getUUID());
@@ -1131,6 +1107,14 @@ public class ModelConverter {
                 List<GroupInstance> groupInstances = topologyTemplate.getInstGroups().get(key).getMapToscaDataDefinition().entrySet().stream().map(e -> new GroupInstance(e.getValue())).collect(Collectors.toList());
                 currComponentInstance.setGroupInstances(groupInstances);
             }
+            if(topologyTemplate.getInstProperties() != null && topologyTemplate.getInstProperties().containsKey(key) && topologyTemplate.getInstProperties().get(key) != null ){
+                List<PropertyDefinition> instanceProps = topologyTemplate.getInstProperties().get(key).getMapToscaDataDefinition().entrySet().stream().map(e -> new PropertyDefinition(e.getValue())).collect(Collectors.toList());
+                currComponentInstance.setProperties(instanceProps);
+            }
+            if(topologyTemplate.getComponentInstInterfaces() != null && topologyTemplate.getComponentInstInterfaces().containsKey(key) && topologyTemplate.getComponentInstInterfaces().get(key) != null ){
+                Map<String, Object> interfacesMap = topologyTemplate.getComponentInstInterfaces().get(key).getMapToscaDataDefinition().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+                currComponentInstance.setInterfaces(interfacesMap);
+            }
             componentInstances.add(currComponentInstance);
         }
         component.setComponentInstances(componentInstances);
@@ -1165,20 +1149,52 @@ public class ModelConverter {
         }
     }
 
-    private static void setComponentInstancesAttributesToComponent(TopologyTemplate topologyTemplate, Component component) {
-        if (topologyTemplate.getInstAttributes() != null) {
-            Map<String, List<ComponentInstanceProperty>> attributes = new HashMap<>();
-            for (Map.Entry<String, MapPropertiesDataDefinition> entry : topologyTemplate.getInstAttributes().entrySet()) {
-                if (entry.getValue() != null && entry.getValue().getMapToscaDataDefinition() != null) {
-                    String key = entry.getKey();
-                    List<ComponentInstanceProperty> componentInstanceAttributes = entry.getValue().getMapToscaDataDefinition().entrySet().stream().map(e -> new ComponentInstanceProperty(new ComponentInstanceProperty(e.getValue())))
-                            .collect(Collectors.toList());
-                    attributes.put(key, componentInstanceAttributes);
-                }
-            }
-            component.setComponentInstancesAttributes(attributes);
-        }
-    }
+       private static void setComponentInstancesInterfacesToComponent(TopologyTemplate topologyTemplate, Component component) {
+               if (topologyTemplate.getInstInterfaces() != null) {
+                       Map<String, List<ComponentInstanceInterface>> interfaces = new HashMap<>();
+                       for (Entry<String, MapInterfaceInstanceDataDefinition> entry : topologyTemplate.getInstInterfaces().entrySet()) {
+                               if (entry.getValue() != null && entry.getValue().getMapToscaDataDefinition() != null) {
+                                       String key = entry.getKey();
+                                       List<ComponentInstanceInterface> componentInstanceInterfaces = entry.getValue()
+                                                       .getMapToscaDataDefinition().entrySet().stream().map(e -> new
+                                                                       ComponentInstanceInterface(e.getKey(), e.getValue()))
+                                                       .collect(Collectors.toList());
+                                       interfaces.put(key, componentInstanceInterfaces);
+                               }
+                       }
+                       component.setComponentInstancesInterfaces(interfaces);
+               }
+               else if (topologyTemplate.getComponentInstInterfaces() != null) {
+                       Map<String, List<ComponentInstanceInterface>> interfaces = new HashMap<>();
+                       for (Entry<String, MapInterfaceDataDefinition> entry : topologyTemplate.getComponentInstInterfaces().entrySet()) {
+                               if (entry.getValue() != null && entry.getValue().getMapToscaDataDefinition() != null) {
+                                       String key = entry.getKey();
+                                       List<ComponentInstanceInterface> componentInstanceInterfaces = entry.getValue()
+                                                       .getMapToscaDataDefinition().entrySet().stream().map(e -> new
+                                                                       ComponentInstanceInterface(e.getKey(), e.getValue()))
+                                                       .collect(Collectors.toList());
+                                       interfaces.put(key, componentInstanceInterfaces);
+                               }
+                       }
+                       component.setComponentInstancesInterfaces(interfaces);
+               }
+
+       }
+
+       private static void setComponentInstancesAttributesToComponent(TopologyTemplate topologyTemplate, Component component) {
+               if (topologyTemplate.getInstAttributes() != null) {
+                       Map<String, List<ComponentInstanceProperty>> attributes = new HashMap<>();
+                       for (Map.Entry<String, MapPropertiesDataDefinition> entry : topologyTemplate.getInstAttributes().entrySet()) {
+                               if (entry.getValue() != null && entry.getValue().getMapToscaDataDefinition() != null) {
+                                       String key = entry.getKey();
+                                       List<ComponentInstanceProperty> componentInstanceAttributes = entry.getValue().getMapToscaDataDefinition().entrySet().stream().map(e -> new ComponentInstanceProperty(new ComponentInstanceProperty(e.getValue())))
+                                                       .collect(Collectors.toList());
+                                       attributes.put(key, componentInstanceAttributes);
+                               }
+                       }
+                       component.setComponentInstancesAttributes(attributes);
+               }
+       }
 
     private static void setComponentInstancesRequirementsToComponent(TopologyTemplate topologyTemplate, Component component) {
 
index ca700b0..bb1096a 100644 (file)
@@ -62,6 +62,7 @@ public enum StorageOperationStatus {
     CANNOT_UPDATE_EXISTING_ENTITY, 
     PROPERTY_NAME_ALREADY_EXISTS, 
     INVALID_PROPERTY,
-    COMPONENT_IS_ARCHIVED;
+    COMPONENT_IS_ARCHIVED,
+    DECLARED_INPUT_USED_BY_OPERATION;
 
 }
index 7a845ef..750563b 100644 (file)
@@ -27,6 +27,7 @@ import { UpgradeAdapter } from '@angular/upgrade';
 import { UpgradeModule } from '@angular/upgrade/static';
 import { SdcUiComponentsModule, SdcUiComponents } from "sdc-ui/lib/angular";
 import { PropertiesAssignmentModule } from './pages/properties-assignment/properties-assignment.module';
+import { PropertyCreatorModule } from './pages/properties-assignment/property-creator/property-creator.module';
 import {
     DataTypesServiceProvider, SharingServiceProvider, CookieServiceProvider, StateServiceFactory,
     StateParamsServiceFactory, CacheServiceProvider, EventListenerServiceProvider, ScopeServiceFactory,
@@ -102,6 +103,7 @@ export function configServiceFactory(config: ConfigService) {
         //We need to import them here since we use them in angular1
         ConnectionWizardModule,
         PropertiesAssignmentModule,
+        PropertyCreatorModule,
         PluginFrameModule,
         InterfaceOperationModule,
         OperationCreatorModule,
index 65072f8..2068b17 100644 (file)
@@ -58,6 +58,9 @@
                     </div>
                     <span *ngIf="property.description" class="property-description-icon sprite-new show-desc" tooltip="{{property.description}}"
                         tooltipDelay="0"></span>
+                    <div class="delete-button-container">
+                        <span *ngIf="showDelete" class="sprite-new delete-btn" [ngClass]="{'disabled' : property.isDisabled || property.isDeclared}" (click)="openDeleteModal(property)" data-tests-id="delete-input-button"></span>
+                    </div>
                 </div>
                 <div class="table-cell col2" *ngIf="!hidePropertyType">
                     <div class="inner-cell-div" tooltip="{{property.type | contentAfterLastDot}}">
index 0f6dd51..86832e5 100644 (file)
         }
     }
 
+    .delete-button-container {
+        max-height: 24px;
+        cursor: pointer;
+    }
+
     .filtered {
         /deep/ .checkbox-label-content{
             background-color: yellow;
index b11bc02..167509b 100644 (file)
@@ -22,6 +22,7 @@
 import { Component, Input, Output, EventEmitter} from "@angular/core";
 import {PropertyFEModel, DerivedFEProperty, InstanceFePropertiesMap} from "app/models";
 import {PropertiesService} from "../../../services/properties.service";
+import {ModalService} from "../../../services/modal.service";
 import { InstanceFeDetails } from "../../../../models/instance-fe-details";
 
 @Component({
@@ -40,10 +41,13 @@ export class PropertiesTableComponent {
     @Input() isLoading:boolean;
     @Input() hasDeclareOption:boolean;
     @Input() hidePropertyType:boolean;
+    @Input() showDelete:boolean;
     
     @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() deleteProperty: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>();
+    private selectedPropertyToDelete: PropertyFEModel;
 
     sortBy: String;
     reverse: boolean;
@@ -57,7 +61,7 @@ export class PropertiesTableComponent {
         this.path = sortBy.split('.');
     }
 
-    constructor (private propertiesService:PropertiesService ){
+    constructor (private propertiesService:PropertiesService, private modalService: ModalService){
     }
     
     ngOnInit() {
@@ -92,6 +96,17 @@ export class PropertiesTableComponent {
         this.updateCheckedPropertyCount.emit(isChecked);
     }
 
+    onDeleteProperty = () => {
+        this.deleteProperty.emit(this.selectedPropertyToDelete);
+        this.modalService.closeCurrentModal();
+    };
+
+    openDeleteModal = (property:PropertyFEModel) => {
+        this.selectedPropertyToDelete = property;
+        this.modalService.createActionModal("Delete Property", "Are you sure you want to delete this property?",
+            "Delete", this.onDeleteProperty, "Close").instance.open();
+    }
+
 }
 
 export class PropertyRowSelectedEvent {
index ca3e90f..8a3e8d2 100644 (file)
                             [readonly]="isReadonly || resourceIsReadonly"
                             [isLoading]="loadingProperties || savingChangedData"
                             [hasDeclareOption]="true"
+                            [showDelete]="!isReadOnly && isSelf()"
                             (propertyChanged)="dataChanged($event)"
                             (propertySelected)="propertySelected($event)"
                             (selectPropertyRow)="selectPropertyRow($event)"
                             (selectChildProperty)="selectChildProperty($event)"
                             (updateCheckedPropertyCount)="updateCheckedPropertyCount($event)"
-                            (selectInstanceRow)="selectInstanceRow($event)">
+                            (selectInstanceRow)="selectInstanceRow($event)"
+                            (deleteProperty)="deleteProperty($event)">
                         </properties-table>
                     </tab>
                     <tab tabTitle="Inputs">
                 <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="declareProperties()" data-tests-id="declare-button">Declare</button>
             </div>
         </div>
-        <div class="right-column gray-border">
-            <tabs #hierarchyNavTabs tabStyle="simple-tabs">
+        <div class="right-column">
+            <div *ngIf="!isReadonly" class="add-btn"
+                 (click)="addProperty()" [ngClass]="{'disabled': !isSelf()}">Add Property</div>
+            <tabs #hierarchyNavTabs tabStyle="simple-tabs" class="gray-border">
                 <tab tabTitle="Composition">
                     <div class="hierarchy-nav-container">
                         <loader [display]="loadingInstances" [size]="'medium'" [relative]="true" [loaderDelay]="500"></loader>
index 6de6dda..95ff943 100644 (file)
         display:flex;
         flex:0 0 350px;
         flex-direction:column;
-        margin: 45px 0 0 1em;
+        margin: 0px 0 0 1em;
         overflow-x:auto;
+         .add-btn{
+
+            align-self: flex-end;
+            margin-top: 10px;
+            margin-bottom: 19px;
+        }
 
         /deep/ .tabs {
             border-bottom: solid 1px #d0d0d0;
index 5a21e86..953c973 100644 (file)
@@ -38,12 +38,14 @@ import {ComponentModeService} from "../../services/component-services/component-
 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 { 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";
 
+const SERVICE_SELF_TITLE = "SELF";
 @Component({
     templateUrl: './properties-assignment.page.component.html',
     styleUrls: ['./properties-assignment.page.component.less']
@@ -84,6 +86,7 @@ export class PropertiesAssignmentComponent {
     isValidChangedData:boolean;
     savingChangedData:boolean;
     stateChangeStartUnregister:Function;
+    serviceBePropertiesMap: InstanceBePropertiesMap;
 
     @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs;
     @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
@@ -132,7 +135,7 @@ export class PropertiesAssignmentComponent {
                 });
                 this.loadingInputs = false;
 
-            }, error => {}); //ignore error
+            });
         this.componentServiceNg2
             .getComponentResourcePropertiesData(this.component)
             .subscribe(response => {
@@ -141,6 +144,12 @@ export class PropertiesAssignmentComponent {
                 this.instances.push(...response.groupInstances);
                 this.instances.push(...response.policies);
 
+                // add the service self instance to the top of the list.
+                const serviceInstance = new ComponentInstance();
+                serviceInstance.name = SERVICE_SELF_TITLE;
+                serviceInstance.uniqueId = this.component.uniqueId;
+                this.instances.unshift(serviceInstance);
+
                 _.forEach(this.instances, (instance) => {
                     this.instancesNavigationData.push(instance);
                     this.componentInstanceNamesMap[instance.uniqueId] = <InstanceFeDetails>{name: instance.name, iconClass:instance.iconClass, originArchived:instance.originArchived};
@@ -150,7 +159,7 @@ export class PropertiesAssignmentComponent {
                     this.loadingProperties = false;
                 }
                 this.selectFirstInstanceByDefault();
-            }, error => {}); //ignore error
+            });
 
         this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => {
             // stop if has changed properties
@@ -183,6 +192,23 @@ export class PropertiesAssignmentComponent {
         this.updateViewMode();
     }
 
+    isSelf = ():boolean => {
+        return this.selectedInstanceData && this.selectedInstanceData.uniqueId == this.component.uniqueId;
+    }
+
+    getServiceProperties(){
+        this.loadingProperties = false;
+        this.componentServiceNg2
+            .getServiceProperties(this.component)
+            .subscribe(response => {
+                this.serviceBePropertiesMap = new InstanceBePropertiesMap();
+                this.serviceBePropertiesMap[this.component.uniqueId] = response;
+                this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false);
+                this.loadingProperties = false;
+            }, error => {
+                this.loadingProperties = false;
+            });
+    }
 
     onInstanceSelectedUpdate = (instance: ComponentInstance|GroupInstance|PolicyInstance) => {
         // stop if has changed properties
@@ -210,6 +236,8 @@ export class PropertiesAssignmentComponent {
                         this.loadingProperties = false;
                     }, error => {
                     }); //ignore error
+            } else if (this.isSelf()) {
+                this.getServiceProperties();
             } else {
                 this.componentInstanceServiceNg2
                     .getComponentInstanceProperties(this.component, instance.uniqueId)
@@ -391,7 +419,7 @@ export class PropertiesAssignmentComponent {
         let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
 
         this.componentServiceNg2
-            .createInput(this.component, inputsToCreate)
+            .createInput(this.component, inputsToCreate, this.isSelf())
             .subscribe(response => {
                 this.setInputTabIndication(response.length);
                 this.checkedPropertiesCount = 0;
@@ -439,8 +467,12 @@ export class PropertiesAssignmentComponent {
                             console.log('updated instance inputs:', response);
                         };
                     } else {
-                        request = this.componentInstanceServiceNg2
-                            .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedProperties)
+                        if (this.isSelf()) {
+                            request = this.componentServiceNg2.updateServiceProperties(this.component, changedProperties);
+                        } else {
+                            request = this.componentInstanceServiceNg2
+                                .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedProperties);
+                        }
                         handleSuccess = (response) => {
                             // reset each changed property with new value and remove it from changed properties list
                             response.forEach((resProp) => {
@@ -650,7 +682,57 @@ export class PropertiesAssignmentComponent {
             }, error => {}); //ignore error
     };
 
+    deleteProperty = (property: PropertyFEModel) => {
+        let propertyToDelete = new PropertyFEModel(property);
+        this.loadingProperties = true;
+        let feMap = this.instanceFePropertiesMap;
+        this.componentServiceNg2
+            .deleteServiceProperty(this.component, propertyToDelete)
+            .subscribe(response => {
+                const props = feMap[this.component.uniqueId];
+                props.splice(props.findIndex(p => p.uniqueId === response),1);
+                this.loadingProperties = false;
+            }, error => {
+                this.loadingProperties = false;
+                console.error(error);
+            });
+    };
+
+    /*** addProperty ***/
+    addProperty = () => {
+        let modalTitle = 'Add Property';
+        const modal = this.ModalService.createCustomModal(new ModalModel(
+            'sm',
+            modalTitle,
+            null,
+            [
+                new ButtonModel('Save', 'blue', () => {
+                    modal.instance.dynamicContent.instance.isLoading = true;
+                    const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel;
+                    this.componentServiceNg2.createServiceProperty(this.component, newProperty)
+                        .subscribe(response => {
+                            modal.instance.dynamicContent.instance.isLoading = false;
+                            let newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
+                            this.instanceFePropertiesMap[this.component.uniqueId].push(newProp);
+                            modal.instance.close();
+                        }, (error) => {
+                            modal.instance.dynamicContent.instance.isLoading = false;
+                            this.Notification.error({
+                                message: 'Failed to add property:' + error,
+                                title: 'Failure'
+                            });
+                        });
 
+                }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
+                new ButtonModel('Cancel', 'outline grey', () => {
+                    modal.instance.close();
+                }),
+            ],
+            null
+        ));
+        this.ModalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
+        modal.instance.open();
+    };
 
     /*** SEARCH RELATED FUNCTIONS ***/
     searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.html
new file mode 100644 (file)
index 0000000..e97ec79
--- /dev/null
@@ -0,0 +1,46 @@
+<div class="property-creator">
+    <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 required">Type</label>
+                <ui-element-dropdown [testId]="'property-type'"
+                                     class="cell link-selector"
+                                     [values]="typesProperties"
+                                     [(value)]="propertyModel.type"></ui-element-dropdown>
+            </div>
+            <div class="i-sdc-form-item propertySchemaType" *ngIf="showSchema()">
+                <label class="i-sdc-form-label required">Schema Type</label>
+                <ui-element-dropdown [testId]="'property-type'"
+                                     class="cell link-selector"
+                                     [values]="typesSchemaProperties"
+                                     [(value)]="propertyModel.schema.property.type"></ui-element-dropdown>
+            </div>
+        </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/property-creator/property-creator.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.less
new file mode 100644 (file)
index 0000000..d17a45e
--- /dev/null
@@ -0,0 +1,35 @@
+@import '../../../../../assets/styles/variables.less';
+
+.property-creator {
+    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/property-creator/property-creator.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts
new file mode 100644 (file)
index 0000000..d5946d2
--- /dev/null
@@ -0,0 +1,78 @@
+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";
+
+
+
+@Component({
+    selector: 'property-creator',
+    templateUrl: './property-creator.component.html',
+    styleUrls:['./property-creator.component.less'],
+})
+
+export class PropertyCreatorComponent {
+
+    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;
+
+    constructor(protected dataTypeService:DataTypeService) {}
+
+    ngOnInit() {
+        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...'));
+
+    }
+
+    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/property-creator/property-creator.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts
new file mode 100644 (file)
index 0000000..92accb2
--- /dev/null
@@ -0,0 +1,27 @@
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {PropertyCreatorComponent} from "./property-creator.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: [
+        PropertyCreatorComponent,
+    ],
+    imports: [
+        CommonModule,
+        FormsModule,
+        FormElementsModule,
+        UiElementsModule,
+        TranslateModule
+    ],
+    exports: [],
+    entryComponents: [
+        PropertyCreatorComponent
+    ],
+    providers: []
+})
+
+export class PropertyCreatorModule {}
index e7b59b9..3ed535d 100644 (file)
@@ -75,6 +75,14 @@ export class PropertiesUtils {
         return instanceFePropertiesMap;
     }
 
+    public convertAddPropertyBAToPropertyFE = (property: PropertyBEModel):PropertyFEModel => {
+        let newFEProp: PropertyFEModel = new PropertyFEModel(property); //Convert property to FE
+        this.initValueObjectRef(newFEProp);
+        newFEProp.updateExpandedChildPropertyId(newFEProp.name); //display only the first level of children
+        this.dataTypeService.checkForCustomBehavior(newFEProp);
+        return newFEProp;
+    }
+
     public createListOrMapChildren = (property:PropertyFEModel | DerivedFEProperty, key: string, valueObj: any): Array<DerivedFEProperty> => {
         let newProps: Array<DerivedFEProperty> = [];
         let parentProp = new DerivedFEProperty(property, property.propertiesName, true, key, valueObj);
index 97e62da..69871ab 100644 (file)
@@ -24,7 +24,7 @@ import {Observable} from 'rxjs/Observable';
 import 'rxjs/add/operator/map';
 import 'rxjs/add/operator/toPromise';
 import {Response, URLSearchParams} from '@angular/http';
-import { Component, InputBEModel, InstancePropertiesAPIMap, FilterPropertiesAssignmentData, OperationModel, BEOperationModel, CreateOperationResponse} from "app/models";
+import { Component, InputBEModel, InstancePropertiesAPIMap, FilterPropertiesAssignmentData, PropertyBEModel, OperationModel, BEOperationModel, CreateOperationResponse} from "app/models";
 import {downgradeInjectable} from '@angular/upgrade/static';
 import {COMPONENT_FIELDS, CommonUtils} from "app/utils";
 import {ComponentGenericResponse} from "../responses/component-generic-response";
@@ -205,8 +205,9 @@ export class ComponentServiceNg2 {
         return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [COMPONENT_FIELDS.COMPONENT_INSTANCES_RELATION, COMPONENT_FIELDS.COMPONENT_INSTANCES, COMPONENT_FIELDS.COMPONENT_GROUPS]);
     }
 
-    createInput(component:Component, inputsToCreate:InstancePropertiesAPIMap):Observable<any> {
-        return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/inputs', inputsToCreate)
+    createInput(component:Component, inputsToCreate:InstancePropertiesAPIMap, isSelf:boolean):Observable<any> {
+        let inputs = isSelf ? { serviceProperties: inputsToCreate.componentInstanceProperties } : inputsToCreate;
+        return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/inputs', inputs)
             .map(res => {
                 return res.json();
             })
@@ -247,6 +248,42 @@ export class ComponentServiceNg2 {
             });
     }
 
+    createServiceProperty(component: Component, propertyModel:PropertyBEModel): Observable<PropertyBEModel> {
+        let serverObject = {};
+        serverObject[propertyModel.name] = propertyModel;
+        return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties', serverObject)
+            .map(res => {
+                let property:PropertyBEModel = new PropertyBEModel(res.json());
+                return property;
+            })
+    }
+
+    getServiceProperties(component: Component): Observable<Array<PropertyBEModel>> {
+        return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties')
+            .map((res: Response) => {
+                if (!res.text()){
+                    return new Array<PropertyBEModel>();
+                }
+                return CommonUtils.initBeProperties(res.json());
+            });
+    }
+
+    updateServiceProperties(component: Component, properties: PropertyBEModel[]) {
+        return this.http.put( this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties', properties)
+            .map((res: Response) => {
+                const resJson = res.json();
+                return _.map(resJson,
+                    (resValue:PropertyBEModel) => new PropertyBEModel(resValue));
+            });
+    }
+
+    deleteServiceProperty(component:Component, property:PropertyBEModel):Observable<string> {
+        return this.http.delete(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/properties/' + property.uniqueId )
+            .map((res:Response) => {
+                return property.uniqueId;
+            })
+    }
+
     getDependencies(componentType:string, componentId: string):Observable<Array<IDependenciesServerResponse>> {
         return this.http.get(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/dependencies')
             .map((res:Response) => {
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/InterfaceInstanceDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/InterfaceInstanceDataDefinition.java
new file mode 100644 (file)
index 0000000..29859cb
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.be.datatypes.elements;
+
+import org.apache.commons.collections.MapUtils;
+import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+public class InterfaceInstanceDataDefinition extends ToscaDataDefinition implements Serializable {
+  protected Map<String, Object> inputs;
+  protected Map<String, OperationInstance> operations;
+
+  public InterfaceInstanceDataDefinition(
+      InterfaceInstanceDataDefinition inter) {
+    this.toscaPresentation = null;
+    this.inputs = inter.inputs == null? new HashMap():new HashMap<>(inter.inputs);
+    this.operations = new HashMap<>(inter.operations);
+  }
+
+  public InterfaceInstanceDataDefinition(){
+    this.toscaPresentation = null;
+  }
+
+  public Map<String, Object> getInputs() {
+    return this.inputs;
+  }
+
+  public void setInputs(
+      Map<String, Object> inputs) {
+    this.inputs = inputs;
+  }
+
+  public Map<String, OperationInstance> getOperations() {
+    return operations;
+  }
+
+  public void addInstanceOperation(String operationName, OperationInstance operation) {
+    if(MapUtils.isEmpty(this.operations)) {
+      this.operations = new HashMap<>();
+    }
+
+    this.operations.put(operationName, operation);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof InterfaceInstanceDataDefinition)) {
+      return false;
+    }
+    InterfaceInstanceDataDefinition that = (InterfaceInstanceDataDefinition) o;
+    return Objects.equals(inputs, that.inputs);
+  }
+
+  @Override
+  public int hashCode() {
+
+    return Objects.hash(inputs);
+  }
+
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationImplementation.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationImplementation.java
new file mode 100644 (file)
index 0000000..7d6ebdd
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.be.datatypes.elements;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+
+public class OperationImplementation {
+
+  private String primary;
+  private List<String> dependencies;
+
+  public String getPrimary() {
+    return primary;
+  }
+
+  public void setPrimary(String primary) {
+    this.primary = primary;
+  }
+
+  public List<String> getDependencies() {
+    return dependencies;
+  }
+
+  public void setDependencies(List<String> dependencies) {
+    this.dependencies = dependencies;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof OperationImplementation)) {
+      return false;
+    }
+    OperationImplementation that = (OperationImplementation) o;
+    return Objects.equals(primary, that.primary) &&
+        Objects.equals(new HashSet<>(dependencies), new HashSet<>(that.dependencies));
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(primary, dependencies);
+  }
+}
diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInstance.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/OperationInstance.java
new file mode 100644 (file)
index 0000000..59a235b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.be.datatypes.elements;
+
+import java.util.Map;
+import java.util.Objects;
+
+public class OperationInstance/* extends Operation*/ {
+  private OperationImplementation implementation;
+  private Map<String, Object> inputs;
+
+
+  public OperationImplementation getImplementation() {
+    return implementation;
+  }
+
+  public void setImplementation(OperationImplementation implementation) {
+    this.implementation = implementation;
+  }
+
+  public Map<String, Object> getInputs() {
+    return inputs;
+  }
+
+  public void setInputs(Map<String, Object> inputs) {
+    this.inputs = inputs;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof OperationInstance)) {
+      return false;
+    }
+    OperationInstance that = (OperationInstance) o;
+    return Objects.equals(implementation, that.implementation) &&
+        Objects.equals(inputs, that.inputs);
+  }
+
+  @Override
+  public int hashCode() {
+
+    return Objects.hash(implementation, inputs);
+  }
+}