Requirement and capabilities feature 46/79446/3
authormojahidi <mojahidul.islam@amdocs.com>
Fri, 1 Mar 2019 12:20:15 +0000 (17:50 +0530)
committerOren Kleks <orenkle@amdocs.com>
Mon, 4 Mar 2019 10:57:03 +0000 (10:57 +0000)
1. Enhance Service/VF/PNF to support Req & Cap
2. Added Type fetch APIs to fetch types from global types

Change-Id: I2b749ec9da34e488421b8ebe311ccf03c4b7c0fd
Issue-ID: SDC-2142
Signed-off-by: mojahidi <mojahidul.islam@amdocs.com>
66 files changed:
asdctool/src/main/resources/config/error-configuration.yaml
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogic.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeBusinessLogic.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeImportManager.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogic.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CertificationChangeTransition.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/lifecycle/CheckoutTransition.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/utils/MergeInstanceUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidation.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/RequirementValidation.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/BeGenericServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/CapabilityServlet.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/RequirementServlet.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesFetchServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java
catalog-be/src/main/resources/import/tosca/relationship-types/relationshipTypes.yml
catalog-be/src/main/resources/scripts/import/tosca/importNormativeAll.py
catalog-be/src/main/resources/scripts/import/tosca/importNormativeRelationships.py [new file with mode: 0644]
catalog-be/src/main/resources/scripts/import/tosca/importONAPNormativeAll.py
catalog-be/src/main/resources/scripts/import/tosca/upgradeNormative.py
catalog-be/src/main/resources/scripts/import/tosca/upgradeONAPNormative.py
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogicTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogicTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidationTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/RequirementValidationTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/servlets/TypesUploadServletTest.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/graph/GraphElementFactory.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/types/VertexTypeEnum.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/neo4j/GraphPropertiesDictionary.java
catalog-dao/src/main/java/org/openecomp/sdc/be/resources/data/RelationshipTypeData.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/RelationshipTypeDefinition.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeType.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/ToscaElement.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperation.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/RequirementOperation.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/ICapabilityTypeOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OperationUtils.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperation.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/UniqueIdBuilder.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/utils/TypeCompareUtils.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeTypeTest.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperationTest.java [new file with mode: 0644]
catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ToscaElementLifecycleOperationTest.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CapabilityDataDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RelationshipInstDataDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java
test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/api/Urls.java
test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/capability/CapabilitiesTest.java [new file with mode: 0644]
test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/CapabilityDetails.java [new file with mode: 0644]
test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/RequirementDetails.java [new file with mode: 0644]
test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/requirements/RequirementsTest.java [new file with mode: 0644]
test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CapabilityRestUtils.java [new file with mode: 0644]
test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/RequirementsUtils.java [new file with mode: 0644]
test-apis-ci/src/main/resources/ci/testSuites/cap_req.xml [new file with mode: 0644]

index 92ba061..01f8ea4 100644 (file)
@@ -1689,4 +1689,117 @@ errors:
         message: "Error: The server was acting as a gateway or proxy and received an invalid response from the upstream server",
         messageId: "SVC4674"
     }
+#---------SVC4675------------------------------
+# %1 - resource Id
+    CAPABILITY_NOT_FOUND: {
+        code: 400,
+        message: "Error: Capability not found in the resource '%1'.",
+        messageId: "SVC4675"
+    }
 
+#---------SVC4676------------------------------
+# %1 - resource Id
+    REQUIREMENT_NOT_FOUND: {
+        code: 400,
+        message: "Error: Requirement not found in the resource '%1'.",
+        messageId: "SVC4676"
+    }
+#---------SVC4677-----------------------------
+    CAPABILITY_NAME_MANDATORY: {
+      code: 404,
+      message: "Error: Capability name is mandatory, Capability name can't be empty.",
+      messageId: "SVC4677"
+    }
+#---------SVC4678-----------------------------
+    CAPABILITY_TYPE_MANDATORY: {
+      code: 404,
+      message: "Error: Capability type is mandatory, Capability type can't be empty.",
+      messageId: "SVC4678"
+    }
+#---------SVC4679-----------------------------
+# %1 - Capability Name
+    CAPABILITY_NAME_ALREADY_IN_USE: {
+      code: 400,
+      message: "Error: Capability name '%1' already in use, Your current changes will not be saved.",
+      messageId: "SVC4679"
+    }
+
+#---------SVC4680-----------------------------
+    REQUIREMENT_NAME_MANDATORY: {
+      code: 404,
+      message: "Error: Requirement name is mandatory, Requirement name can't be empty.",
+      messageId: "SVC4680"
+    }
+#---------SVC4681-----------------------------
+    REQUIREMENT_CAPABILITY_MANDATORY: {
+      code: 404,
+      message: "Error: Requirement capability is mandatory, Requirement capability can't be empty.",
+      messageId: "SVC4681"
+    }
+#---------SVC4682-----------------------------
+# %1 - Requirement Name
+    REQUIREMENT_NAME_ALREADY_IN_USE: {
+      code: 400,
+      message: "Error: Requirement name '%1' already in use, Your current changes will not be saved.",
+      messageId: "SVC4682"
+    }
+#---------SVC4683-----------------------------
+    MAX_OCCURRENCES_SHOULD_BE_GREATER_THAN_MIN_OCCURRENCES: {
+      code: 400,
+      message: "Error: maxOccurrences should be greater than minOccurrences",
+      messageId: "SVC4683"
+    }
+#---------SVC4684-----------------------------
+# %1 - Capability name
+    CAPABILITY_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION: {
+        code: 409,
+        message: "Error: Capability '%1' can't be deleted,  since it is used in service composition",
+        messageId: "SVC4684"
+    }
+#---------SVC4685-----------------------------
+# %1 - Requirement name
+    REQUIREMENT_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION: {
+        code: 409,
+        message: "Error: Requirement '%1' can't be deleted,  since it is used in service composition",
+        messageId: "SVC4685"
+    }
+#---------SVC4686-----------------------------
+    CAPABILITY_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION: {
+        code: 409,
+        message: "Error: Capability can't be updated,  since it is used in service composition",
+        messageId: "SVC4686"
+    }
+
+#---------SVC4687-----------------------------
+    REQUIREMENT_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION: {
+        code: 409,
+        message: "Error: Requirement can't be updated,  since it is used in service composition",
+        messageId: "SVC4687"
+    }
+#---------SVC4688-----------------------------
+    CAPABILITY_TYPE_CANNOT_BE_EMPTY: {
+      code: 500,
+      message: "Error: Capability types are empty. Please import the capability types.",
+      messageId: "SVC4688"
+    }
+#---------SVC4689-----------------------------
+    RELATIONSHIP_TYPE_ALREADY_EXIST: {
+      code: 409,
+      message: "Error: Relationship Type with name '%1' already exists.",
+      messageId: "SVC4689"
+    }
+#---------SVC4690-----------------------------
+# %1 - Requirement name
+    INVALID_REQUIREMENT_NAME: {
+        code: 400,
+        message: "Requirement name '%1' is invalid, Only alphanumeric chars, underscore and dot allowed",
+        messageId: "SVC4690"
+    }
+
+#---------SVC4691-----------------------------
+# %1 - Capability name
+    INVALID_CAPABILITY_NAME: {
+        code: 400,
+        message: "Capability name '%1' is invalid, Only alphanumeric chars, underscore and dot allowed",
+        messageId: "SVC4691"
+    }
\ No newline at end of file
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogic.java
new file mode 100644 (file)
index 0000000..75d5836
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * 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.impl;
+
+import fj.data.Either;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.openecomp.sdc.be.components.validation.CapabilitiesValidation;
+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.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
+import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.jsontitan.operations.CapabilitiesOperation;
+import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+@Component("capabilitiesBusinessLogic")
+public class CapabilitiesBusinessLogic extends BaseBusinessLogic {
+    private static final Logger LOGGER = LoggerFactory.getLogger(CapabilitiesBusinessLogic.class);
+    private static final String FAILED_TO_LOCK_COMPONENT_RESPONSE_IS
+            = "Failed to lock component {}. Response is {}";
+    private static final String DELETE_CAPABILITIES = "deleteCapability";
+    private static final String GET_CAPABILITIES = "getCapabilities";
+    private static final String EXCEPTION_OCCURRED_DURING_CAPABILITIES
+            = "Exception occurred during {}. Response is {}";
+
+    @Autowired
+    private CapabilitiesOperation capabilitiesOperation;
+    @Autowired
+    private CapabilitiesValidation capabilitiesValidation;
+    @Autowired
+    private ICapabilityTypeOperation capabilityTypeOperation;
+
+
+    public void setCapabilitiesValidation(CapabilitiesValidation capabilitiesValidation) {
+        this.capabilitiesValidation = capabilitiesValidation;
+    }
+
+    public void setCapabilitiesOperation(CapabilitiesOperation capabilitiesOperation) {
+        this.capabilitiesOperation = capabilitiesOperation;
+    }
+
+    public Either<List<CapabilityDefinition>, ResponseFormat> createCapabilities(
+            String componentId, List<CapabilityDefinition> capabilityDefinitions,
+            User user, String errorContext, boolean lock) {
+        validateUserExists(user.getUserId(), errorContext, true);
+        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither
+                = getComponentDetails(componentId);
+        if (componentEither.isRight()) {
+            return Either.right(componentEither.right().value());
+        }
+        org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
+        Either<Boolean, ResponseFormat> capabilitiesValidationEither = capabilitiesValidation
+                .validateCapabilities(capabilityDefinitions, storedComponent, false);
+        if (capabilitiesValidationEither.isRight()) {
+            return Either.right(capabilitiesValidationEither.right().value());
+        }
+
+        Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock,
+                storedComponent, errorContext);
+        if (lockResult.isRight()) {
+            return Either.right(lockResult.right().value());
+        }
+        try {
+            Either<List<CapabilityDefinition>, StorageOperationStatus> result;
+            List<CapabilityDefinition> capabilitiesListStoredInComponent = null;
+            Map<String, List<CapabilityDefinition>> storedComponentCapabilities
+                    = storedComponent.getCapabilities();
+            if (org.apache.commons.collections.MapUtils.isNotEmpty(storedComponentCapabilities)) {
+                CapabilityDefinition capabilityDefinitionToGetType = capabilityDefinitions.get(0);
+                if(Objects.isNull(capabilityDefinitionToGetType)) {
+                    return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
+                }
+                capabilitiesListStoredInComponent
+                        = getCapabilityStoredInComponentByType(capabilityDefinitionToGetType
+                        .getType(), storedComponentCapabilities);
+            }
+            List<CapabilityDefinition> capabilitiesDefListToCreate;
+            List<CapabilityDefinition> capabilitiesToReturn;
+            if (CollectionUtils.isNotEmpty(capabilitiesListStoredInComponent)) {
+                capabilitiesDefListToCreate = capabilityDefinitions.stream()
+                        .map(capabilityDefinition ->
+                                initiateNewCapability(storedComponent, capabilityDefinition))
+                        .collect(Collectors.toList());
+                capabilitiesToReturn = capabilitiesDefListToCreate;
+                capabilitiesDefListToCreate.addAll(capabilitiesListStoredInComponent);
+                result = capabilitiesOperation.updateCapabilities(componentId,
+                        capabilitiesDefListToCreate);
+            } else {
+                capabilitiesToReturn = capabilityDefinitions.stream()
+                        .map(capabilityDefinition -> initiateNewCapability(
+                                storedComponent, capabilityDefinition))
+                        .collect(Collectors.toList());
+                result = capabilitiesOperation.addCapabilities(componentId, capabilitiesToReturn);
+            }
+            if (result.isRight()) {
+                titanDao.rollback();
+                return Either.right(componentsUtils.getResponseFormat(
+                        componentsUtils.convertFromStorageResponse(result.right().value(),
+                                storedComponent.getComponentType()), ""));
+            }
+            titanDao.commit();
+            return Either.left(capabilitiesToReturn);
+        } catch (Exception e) {
+            titanDao.rollback();
+            LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "addOrUpdate", e);
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+        } finally {
+            if (lockResult.isLeft() && lockResult.left().value()) {
+                graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
+                        NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
+            }
+        }
+    }
+
+    public Either<List<CapabilityDefinition>, ResponseFormat> updateCapabilities(
+            String componentId, List<CapabilityDefinition> capabilityDefinitions,
+            User user, String errorContext, boolean lock) {
+        validateUserExists(user.getUserId(), errorContext, true);
+        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither
+                = getComponentDetails(componentId);
+        if (componentEither.isRight()) {
+            return Either.right(componentEither.right().value());
+        }
+        org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
+        Either<Boolean, ResponseFormat> capabilitiesValidationEither = capabilitiesValidation
+                .validateCapabilities(capabilityDefinitions, storedComponent, true);
+        if (capabilitiesValidationEither.isRight()) {
+            return Either.right(capabilitiesValidationEither.right().value());
+        }
+
+        Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock,
+                storedComponent, errorContext);
+        if (lockResult.isRight()) {
+            return Either.right(lockResult.right().value());
+        }
+        try {
+            Either<List<CapabilityDefinition>, StorageOperationStatus> result;
+            List<CapabilityDefinition> capabilitiesListStoredInComponent = null;
+            Map<String, List<CapabilityDefinition>> storedComponentCapabilities
+                    = storedComponent.getCapabilities();
+            if (org.apache.commons.collections.MapUtils.isNotEmpty(storedComponentCapabilities)) {
+                CapabilityDefinition capabilityDefinitionToGetType = capabilityDefinitions.get(0);
+                if(Objects.isNull(capabilityDefinitionToGetType)) {
+                    return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
+                }
+                capabilitiesListStoredInComponent
+                        = getCapabilityStoredInComponentByType(capabilityDefinitionToGetType
+                        .getType(), storedComponentCapabilities);
+            }
+            List<CapabilityDefinition> capabilitiesDefListToUpdate = new ArrayList<>();
+            List<CapabilityDefinition> capabilitiesToReturn = null;
+            if (CollectionUtils.isNotEmpty(capabilitiesListStoredInComponent)) {
+                if (capabilityDefinitions.stream().anyMatch(capabilityDefinition ->
+                        isCapabilityUsedInServiceComposition(capabilityDefinition, storedComponent))) {
+                    LOGGER.error("Capability can't be edited, since it is"
+                            + " used in service composition");
+                    return Either.right(componentsUtils.getResponseFormat(
+                            ActionStatus.CAPABILITY_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION));
+                }
+                for (CapabilityDefinition capabilityDefinitionToUpdate : capabilityDefinitions) {
+                    capabilitiesToReturn = capabilitiesListStoredInComponent.stream()
+                            .filter(capToUpdate -> capToUpdate.getUniqueId()
+                                    .equals(capabilityDefinitionToUpdate.getUniqueId()))
+                            .map(capabilityDefinition -> updateCapability(capabilityDefinition,
+                                    capabilityDefinitionToUpdate)).collect(Collectors.toList());
+                    capabilitiesListStoredInComponent.removeIf(capToUpdate ->
+                            capToUpdate.getUniqueId().equals(capabilityDefinitionToUpdate.getUniqueId()));
+                    if (CollectionUtils.isNotEmpty(capabilitiesToReturn)) {
+                        capabilitiesListStoredInComponent.addAll(capabilitiesToReturn);
+                        capabilitiesDefListToUpdate.addAll(capabilitiesListStoredInComponent);
+                    } else {
+                        Either<List<CapabilityDefinition>, ResponseFormat> capTypeUpdateEither
+                                = handleCapabilityTypeUpdateWhenNewTypeExist(storedComponent,
+                                storedComponent.getCapabilities(), capabilitiesToReturn, capabilityDefinitionToUpdate);
+                        if (capTypeUpdateEither.isRight()) {
+                            return Either.right(capTypeUpdateEither.right().value());
+                        }
+                        capabilitiesDefListToUpdate = capTypeUpdateEither.left().value();
+                    }
+                }
+                result = capabilitiesOperation.updateCapabilities(componentId,
+                        capabilitiesDefListToUpdate);
+            } else {
+                Either<List<CapabilityDefinition>, ResponseFormat> capabilityDefinitionToDelete
+                        = handleCapabilityTypeUpdateWhenNewTypeNotExist(capabilityDefinitions,
+                        storedComponent, storedComponentCapabilities);
+                if (capabilityDefinitionToDelete != null) {
+                    return capabilityDefinitionToDelete;
+                }
+                capabilitiesToReturn = capabilityDefinitions.stream()
+                        .map(capabilityDefinition -> initiateNewCapability(
+                                storedComponent, capabilityDefinition))
+                        .collect(Collectors.toList());
+                result = capabilitiesOperation.addCapabilities(componentId, capabilitiesToReturn);
+            }
+            if (result.isRight()) {
+                titanDao.rollback();
+                return Either.right(componentsUtils.getResponseFormat(
+                        componentsUtils.convertFromStorageResponse(result.right().value(),
+                                storedComponent.getComponentType()), ""));
+            }
+
+            titanDao.commit();
+            return Either.left(capabilitiesToReturn);
+        } catch (Exception e) {
+            titanDao.rollback();
+            LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "addOrUpdate", e);
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+        } finally {
+            if (lockResult.isLeft() && lockResult.left().value()) {
+                graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
+                        NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
+            }
+        }
+    }
+
+    private Either<List<CapabilityDefinition>, ResponseFormat> handleCapabilityTypeUpdateWhenNewTypeExist(
+            org.openecomp.sdc.be.model.Component storedComponent, Map<String,
+            List<CapabilityDefinition>> storedComponentCapabilities,
+            List<CapabilityDefinition> capabilitiesToReturn,
+            CapabilityDefinition capabilityDefinitionToUpdate) {
+        List<CapabilityDefinition> capabilitiesListStoredInComponent;
+        List<CapabilityDefinition> capabilitiesDefsToCreateOrUpdate = new ArrayList<>();
+        Optional<CapabilityDefinition> definitionOptional = storedComponentCapabilities
+                .values().stream().flatMap(Collection::stream)
+                .filter(capabilityDefinition -> capabilityDefinition.getUniqueId()
+                        .equals(capabilityDefinitionToUpdate.getUniqueId())).findAny();
+        if (!definitionOptional.isPresent()) {
+            return Either.right(componentsUtils.getResponseFormat(
+                    ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId()));
+        }
+        CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get();
+
+        capabilitiesListStoredInComponent = getCapabilityStoredInComponentByType(
+                capabilityDefinitionToUpdate.getType(), storedComponentCapabilities);
+        Either<List<CapabilityDefinition>, StorageOperationStatus> deleteCapabilityEither
+                = deleteCapability(storedComponent, storedComponentCapabilities, capabilityDefinitionToDelete);
+        if (deleteCapabilityEither.isRight()) {
+            titanDao.rollback();
+            return Either.right(componentsUtils.getResponseFormat(deleteCapabilityEither.right().value()));
+        }
+        capabilitiesToReturn.add(initiateNewCapability(storedComponent, capabilityDefinitionToUpdate));
+
+        capabilitiesDefsToCreateOrUpdate.addAll(capabilitiesToReturn);
+        capabilitiesDefsToCreateOrUpdate.addAll(capabilitiesListStoredInComponent);
+        return Either.left(capabilitiesDefsToCreateOrUpdate);
+    }
+
+    private Either<List<CapabilityDefinition>, ResponseFormat> handleCapabilityTypeUpdateWhenNewTypeNotExist(
+            List<CapabilityDefinition> capabilityDefinitions,
+            org.openecomp.sdc.be.model.Component storedComponent,
+            Map<String, List<CapabilityDefinition>> storedComponentCapabilities) {
+        for (CapabilityDefinition capabilityDefinitionToUpdate : capabilityDefinitions) {
+
+            Optional<CapabilityDefinition> definitionOptional = storedComponentCapabilities.values()
+                    .stream().flatMap(Collection::stream)
+                    .filter(capabilityDefinition -> capabilityDefinition.getUniqueId()
+                            .equals(capabilityDefinitionToUpdate.getUniqueId())).findAny();
+            if (!definitionOptional.isPresent()) {
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.CAPABILITY_NOT_FOUND, storedComponent.getUniqueId()));
+            }
+            CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get();
+            Boolean isCapabilityUsedInServiceComposition = isCapabilityUsedInServiceComposition(
+                    capabilityDefinitionToDelete, storedComponent);
+            if (isCapabilityUsedInServiceComposition) {
+                LOGGER.error("Capability {} can't be edited, since it is used in service composition",
+                        capabilityDefinitionToDelete.getUniqueId());
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.CAPABILITY_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION,
+                        capabilityDefinitionToDelete.getName()));
+            }
+            Either<List<CapabilityDefinition>, StorageOperationStatus> deleteCapabilityEither
+                    = deleteCapability(storedComponent, storedComponentCapabilities,
+                    capabilityDefinitionToDelete);
+            if (deleteCapabilityEither.isRight()) {
+                titanDao.rollback();
+                return Either.right(componentsUtils.getResponseFormat(deleteCapabilityEither.right().value()));
+            }
+        }
+        return null;
+    }
+
+    public Either<CapabilityDefinition, ResponseFormat> getCapability(
+            String componentId,
+            String capabilityToGet, User user, boolean lock) {
+        validateUserExists(user.getUserId(), GET_CAPABILITIES, true);
+        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither
+                = getComponentDetails(componentId);
+        if (componentEither.isRight()) {
+            return Either.right(componentEither.right().value());
+        }
+        org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
+
+        Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock,
+                storedComponent, GET_CAPABILITIES);
+        if (lockResult.isRight()) {
+            return Either.right(lockResult.right().value());
+        }
+        try {
+            List<CapabilityDefinition> capabilityDefinitions = storedComponent.getCapabilities()
+                    .values().stream()
+                    .flatMap(Collection::stream).collect(Collectors.toList());
+            if (capabilityDefinitions.isEmpty()) {
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.CAPABILITY_NOT_FOUND, componentId));
+            }
+
+            CapabilityDefinition capabilityDefinitionToReturn;
+            Optional<CapabilityDefinition> capabilityDefinitionOptional
+                    = capabilityDefinitions.stream()
+                    .filter(capabilityDefinition -> capabilityDefinition.getUniqueId()
+                            .equals(capabilityToGet)).findAny();
+            if (capabilityDefinitionOptional.isPresent()) {
+                capabilityDefinitionToReturn = capabilityDefinitionOptional.get();
+            } else {
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.CAPABILITY_NOT_FOUND, componentId));
+            }
+
+            return Either.left(capabilityDefinitionToReturn);
+        } catch (Exception e) {
+            LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "get", e);
+            return Either.right(componentsUtils.getResponseFormat(
+                    ActionStatus.CAPABILITY_NOT_FOUND, componentId));
+        } finally {
+            if (lockResult.isLeft() && lockResult.left().value()) {
+                graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
+                        NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType()
+                                .getValue()));
+            }
+        }
+    }
+
+    public Either<CapabilityDefinition, ResponseFormat> deleteCapability(
+            String componentId, String capabilityIdToDelete, User user,
+            boolean lock) {
+        validateUserExists(user.getUserId(), DELETE_CAPABILITIES, true);
+        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither
+                = getComponentDetails(componentId);
+        if (componentEither.isRight()) {
+            return Either.right(componentEither.right().value());
+        }
+        org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
+
+        Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock,
+                storedComponent, DELETE_CAPABILITIES);
+        if (lockResult.isRight()) {
+            return Either.right(lockResult.right().value());
+        }
+
+        try {
+            Map<String, List<CapabilityDefinition>> storedComponentCapabilities
+                    = storedComponent.getCapabilities();
+            if (storedComponentCapabilities.isEmpty()) {
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.CAPABILITY_NOT_FOUND, componentId));
+            }
+
+            Optional<CapabilityDefinition> definitionOptional = storedComponentCapabilities
+                    .values().stream().flatMap(Collection::stream)
+                    .filter(capabilityDefinition -> capabilityDefinition.getUniqueId()
+                            .equals(capabilityIdToDelete)).findAny();
+            if (!definitionOptional.isPresent()) {
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.CAPABILITY_NOT_FOUND, componentId));
+            }
+            CapabilityDefinition capabilityDefinitionToDelete = definitionOptional.get();
+            Boolean isCapabilityUsedInServiceComposition
+                    = isCapabilityUsedInServiceComposition(capabilityDefinitionToDelete, storedComponent);
+            if (isCapabilityUsedInServiceComposition) {
+                LOGGER.error("Capability {} can't be deleted, since it is used in service composition",
+                        capabilityDefinitionToDelete.getUniqueId());
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.CAPABILITY_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION,
+                        capabilityDefinitionToDelete.getName()));
+            }
+
+            Either<List<CapabilityDefinition>, StorageOperationStatus> result
+                    = deleteCapability(storedComponent, storedComponentCapabilities,
+                    capabilityDefinitionToDelete);
+            if (result.isRight()) {
+                titanDao.rollback();
+                LOGGER.error("Failed to delete capability  from component {}. Response is {}",
+                        storedComponent.getName(), result.right().value());
+                return Either.right(componentsUtils.getResponseFormat(
+                        componentsUtils.convertFromStorageResponse(result.right().value(),
+                                storedComponent.getComponentType())));
+            }
+
+            titanDao.commit();
+            return Either.left(capabilityDefinitionToDelete);
+        } catch (Exception e) {
+            LOGGER.error(EXCEPTION_OCCURRED_DURING_CAPABILITIES, "delete", e);
+            titanDao.rollback();
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.CAPABILITY_NOT_FOUND));
+        } finally {
+            if (lockResult.isLeft() && lockResult.left().value()) {
+                graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
+                        NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
+            }
+        }
+    }
+
+    private Either<List<CapabilityDefinition>, StorageOperationStatus> deleteCapability(
+            org.openecomp.sdc.be.model.Component storedComponent,
+            Map<String, List<CapabilityDefinition>> storedComponentCapabilities,
+            CapabilityDefinition capabilityDefinitionToDelete) {
+        List<CapabilityDefinition> capabilitiesListStoredInComponent =
+                getCapabilityStoredInComponentByType(capabilityDefinitionToDelete.getType(),
+                        storedComponentCapabilities);
+        if(capabilitiesListStoredInComponent == null) {
+           return Either.right(StorageOperationStatus.BAD_REQUEST);
+        }
+        capabilitiesListStoredInComponent.removeIf(capabilityDefinition ->
+                capabilityDefinition.getUniqueId().equals(capabilityDefinitionToDelete.getUniqueId()));
+        Either<List<CapabilityDefinition>, StorageOperationStatus> result;
+        if (capabilitiesListStoredInComponent.isEmpty()) {
+            StorageOperationStatus operationStatus = capabilitiesOperation.deleteCapabilities(storedComponent,
+                    capabilityDefinitionToDelete.getType());
+            if (StorageOperationStatus.OK.equals(operationStatus)) {
+                result = Either.left(Collections.singletonList(capabilityDefinitionToDelete));
+            } else {
+                result = Either.right(operationStatus);
+            }
+        } else {
+            result = capabilitiesOperation.updateCapabilities(storedComponent.getUniqueId(),
+                    capabilitiesListStoredInComponent);
+        }
+        return result;
+    }
+
+
+    private Either<org.openecomp.sdc.be.model.Component, ResponseFormat> getComponentDetails(
+            String componentId) {
+        ComponentParametersView filter = new ComponentParametersView(true);
+        filter.setIgnoreCapabilities(false);
+        filter.setIgnoreCapabiltyProperties(false);
+        Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus>
+                componentStorageOperationStatusEither = toscaOperationFacade
+                .getToscaElement(componentId, filter);
+        if (componentStorageOperationStatusEither.isRight()) {
+            StorageOperationStatus errorStatus = componentStorageOperationStatusEither.right().value();
+            LOGGER.error("Failed to fetch component information by component id {}, Response is {}",
+                    componentId, errorStatus);
+            return Either.right(componentsUtils.getResponseFormat(componentsUtils
+                    .convertFromStorageResponse(errorStatus)));
+        }
+        return Either.left(componentStorageOperationStatusEither.left().value());
+    }
+
+    private Either<Boolean, ResponseFormat> lockComponentResult(
+            boolean lock, org.openecomp.sdc.be.model.Component component,
+            String action) {
+        if (lock) {
+            Either<Boolean, ResponseFormat> lockResult = lockComponent(component.getUniqueId(),
+                    component, action);
+            if (lockResult.isRight()) {
+                LOGGER.debug(FAILED_TO_LOCK_COMPONENT_RESPONSE_IS, component.getName(),
+                        lockResult.right().value().getFormattedMessage());
+                titanDao.rollback();
+                return Either.right(lockResult.right().value());
+            }
+        }
+        return Either.left(true);
+    }
+
+    private List<CapabilityDefinition> getCapabilityStoredInComponentByType(
+            String capabilityType, Map<String,
+            List<CapabilityDefinition>> capabilities) {
+        Optional<Map.Entry<String, List<CapabilityDefinition>>> entryOptional
+                = capabilities.entrySet().stream().
+                filter(map -> map.getKey().equals(capabilityType)).findFirst();
+        return entryOptional.map(Map.Entry::getValue).orElse(null);
+
+    }
+
+    private CapabilityDefinition initiateNewCapability(
+            org.openecomp.sdc.be.model.Component component,
+            CapabilityDefinition capabilityDefinition) {
+        if (StringUtils.isEmpty(capabilityDefinition.getUniqueId()))
+            capabilityDefinition.setUniqueId(UUID.randomUUID().toString());
+        if (StringUtils.isEmpty(capabilityDefinition.getOwnerId()))
+            capabilityDefinition.setOwnerId(component.getUniqueId());
+        if (StringUtils.isEmpty(capabilityDefinition.getOwnerName()))
+            capabilityDefinition.setOwnerName(component.getName());
+        capabilityDefinition.setLeftOccurrences(capabilityDefinition.getMaxOccurrences());
+        return capabilityDefinition;
+    }
+
+    private CapabilityDefinition updateCapability(CapabilityDefinition storedCapability,
+                                                  CapabilityDefinition capabilityToUpdate) {
+        storedCapability.setName(capabilityToUpdate.getName());
+        storedCapability.setDescription(capabilityToUpdate.getDescription());
+        storedCapability.setType(capabilityToUpdate.getType());
+        storedCapability.setValidSourceTypes(capabilityToUpdate.getValidSourceTypes());
+        storedCapability.setMinOccurrences(capabilityToUpdate.getMinOccurrences());
+        storedCapability.setMaxOccurrences(capabilityToUpdate.getMaxOccurrences());
+
+        return storedCapability;
+    }
+
+
+    private Boolean isCapabilityUsedInServiceComposition(
+            CapabilityDefinition capabilityDefinition,
+            org.openecomp.sdc.be.model.Component component) {
+        Either<List<org.openecomp.sdc.be.model.Component>, StorageOperationStatus>
+                componentList = toscaOperationFacade
+                .getParentComponents(component.getUniqueId());
+        if (componentList.isRight()) {
+            return Boolean.FALSE;
+        }
+        return componentList.left().value().stream().flatMap(parentComponent -> parentComponent
+                .getComponentInstancesRelations().stream())
+                .flatMap(requirementCapabilityRelDef -> requirementCapabilityRelDef.getRelationships().stream())
+                .anyMatch(capabilityRequirementRelationship -> capabilityRequirementRelationship
+                        .getRelation().getCapabilityUid().equals(capabilityDefinition.getUniqueId()));
+    }
+
+    public Either<Map<String, CapabilityTypeDefinition>, ResponseFormat> getAllCapabilityTypes() {
+        Either<Map<String, CapabilityTypeDefinition>, TitanOperationStatus> capabilityTypeCacheAll =
+                capabilityTypeOperation.getAllCapabilityTypes();
+        if (capabilityTypeCacheAll.isRight()) {
+            TitanOperationStatus operationStatus = capabilityTypeCacheAll.right().value();
+            if (TitanOperationStatus.NOT_FOUND == operationStatus) {
+                BeEcompErrorManager.getInstance().logInternalDataError("FetchCapabilityTypes", "Capability types are "
+                                + "not loaded",
+                        BeEcompErrorManager.ErrorSeverity.ERROR);
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPE_CANNOT_BE_EMPTY));
+            } else {
+                BeEcompErrorManager.getInstance().logInternalFlowError("FetchCapabilityTypes", "Failed to fetch capability "
+                                + "types",
+                        BeEcompErrorManager.ErrorSeverity.ERROR);
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+            }
+        }
+        return Either.left(capabilityTypeCacheAll.left().value());
+    }
+}
index b60b5c7..773dc63 100644 (file)
@@ -173,7 +173,7 @@ public class CommonImportManager {
     }
 
     public enum ElementTypeEnum {
-        POLICY_TYPE, GROUP_TYPE, DATA_TYPE, CAPABILITY_TYPE, INTERFACE_LIFECYCLE_TYPE
+        POLICY_TYPE, GROUP_TYPE, DATA_TYPE, CAPABILITY_TYPE, INTERFACE_LIFECYCLE_TYPE, RELATIONSHIP_TYPE
     }
 
     private ActionStatus convertFromStorageResponseForElementType(StorageOperationStatus status, ElementTypeEnum elementTypeEnum) {
@@ -191,6 +191,9 @@ public class CommonImportManager {
         case INTERFACE_LIFECYCLE_TYPE:
             ret = componentsUtils.convertFromStorageResponseForLifecycleType(status);
             break;
+        case RELATIONSHIP_TYPE:
+            ret = componentsUtils.convertFromStorageResponseForRelationshipType(status);
+            break;
         default:
             ret = componentsUtils.convertFromStorageResponse(status);
             break;
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeBusinessLogic.java
new file mode 100644 (file)
index 0000000..4a90978
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.impl;
+
+import java.util.Map;
+
+import fj.data.Either;
+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.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
+import org.openecomp.sdc.be.model.operations.impl.RelationshipTypeOperation;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("relationshipTypeBusinessLogic")
+public class RelationshipTypeBusinessLogic {
+
+    @Autowired
+    private RelationshipTypeOperation relationshipTypeOperation;
+
+    @Autowired
+    protected ComponentsUtils componentsUtils;
+
+    public Either<Map<String, RelationshipTypeDefinition>, ResponseFormat> getAllRelationshipTypes() {
+        Either<Map<String, RelationshipTypeDefinition>, TitanOperationStatus> allRelationshipTypes =
+                relationshipTypeOperation.getAllRelationshipTypes();
+        if (allRelationshipTypes.isRight()) {
+            TitanOperationStatus operationStatus = allRelationshipTypes.right().value();
+            if (TitanOperationStatus.NOT_FOUND == operationStatus) {
+                BeEcompErrorManager.getInstance().logInternalDataError("FetchRelationshipTypes", "Relationship types "
+                                + "are "
+                                + "not loaded",
+                        BeEcompErrorManager.ErrorSeverity.ERROR);
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.DATA_TYPE_CANNOT_BE_EMPTY));
+            } else {
+                BeEcompErrorManager.getInstance().logInternalFlowError("FetchRelationshipTypes", "Failed to fetch "
+                                + "relationship types",
+                        BeEcompErrorManager.ErrorSeverity.ERROR);
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+            }
+        }
+        return Either.left(allRelationshipTypes.left().value());
+    }
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RelationshipTypeImportManager.java
new file mode 100644 (file)
index 0000000..18671f8
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import fj.data.Either;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openecomp.sdc.be.components.impl.CommonImportManager.ElementTypeEnum;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
+import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
+import org.openecomp.sdc.be.model.operations.impl.RelationshipTypeOperation;
+import org.openecomp.sdc.be.utils.TypeUtils;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.springframework.stereotype.Component;
+
+@Component("relationshipTypeImportManager")
+public class RelationshipTypeImportManager {
+
+    private final RelationshipTypeOperation relationshipTypeOperation;
+    private final CommonImportManager commonImportManager;
+    private ComponentsUtils componentsUtils;
+
+    public RelationshipTypeImportManager(RelationshipTypeOperation relationshipTypeOperation,
+                                         CommonImportManager commonImportManager) {
+        this.relationshipTypeOperation = relationshipTypeOperation;
+        this.commonImportManager = commonImportManager;
+    }
+
+    public Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat> createRelationshipTypes(
+            String relationshipYml) {
+        return createRelationshipTypes(relationshipYml, false);
+    }
+
+    private Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat> createRelationshipTypes(
+            String relationshipTypeYml, boolean inTransaction) {
+        return commonImportManager.createElementTypes(relationshipTypeYml,
+                relationshipTypesFromYml -> createRelationshipTypesFromYml(relationshipTypeYml),
+                relationshipTypesToCreate -> createRelationshipTypesByDao(relationshipTypesToCreate,
+                        inTransaction), ElementTypeEnum.RELATIONSHIP_TYPE);
+    }
+
+    private Either<List<RelationshipTypeDefinition>, ActionStatus> createRelationshipTypesFromYml(
+            String relationshipTypeYml) {
+        return commonImportManager.createElementTypesFromYml(relationshipTypeYml,
+                this::createRelationshipType);
+    }
+
+    private Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat> createRelationshipTypesByDao(
+            List<RelationshipTypeDefinition> relationshipTypesToCreate, boolean inTransaction) {
+        return commonImportManager.createElementTypesByDao(relationshipTypesToCreate, this::validateRelationshipType,
+                relationshipType -> new ImmutablePair<>(ElementTypeEnum.RELATIONSHIP_TYPE, relationshipType.getType()),
+                relationshipTypeName -> relationshipTypeOperation.getRelationshipTypeByName(relationshipTypeName)
+                        .right().map(DaoStatusConverter::convertTitanStatusToStorageStatus),
+                relationshipType -> relationshipTypeOperation.addRelationshipType(relationshipType, inTransaction),
+                (newRelationshipType, oldRelationshipType) -> relationshipTypeOperation
+                        .updateRelationshipType(newRelationshipType, oldRelationshipType, inTransaction));
+    }
+
+
+    private Either<ActionStatus, ResponseFormat> validateRelationshipType(RelationshipTypeDefinition relationshipType) {
+        Either<ActionStatus, ResponseFormat> result = Either.left(ActionStatus.OK);
+        if (relationshipType.getType() == null) {
+            ResponseFormat responseFormat =
+                    componentsUtils.getResponseFormat(ActionStatus.MISSING_RELATIONSHIP_TYPE, relationshipType.getType());
+            result = Either.right(responseFormat);
+        }
+        return result;
+    }
+
+    private RelationshipTypeDefinition createRelationshipType(String relationshipTypeName,
+                                                              Map<String, Object> toscaJson) {
+        RelationshipTypeDefinition relationshipType = new RelationshipTypeDefinition();
+
+        relationshipType.setType(relationshipTypeName);
+
+        // Description
+        commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DESCRIPTION.getElementName(),
+                relationshipType::setDescription);
+        // Derived From
+        commonImportManager.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName(),
+                relationshipType::setDerivedFrom);
+        // Properties
+        commonImportManager.setPropertiesMap(toscaJson, relationshipType::setProperties);
+        //valid-target-types
+        if(toscaJson.get("valid_target_types") instanceof List)
+            relationshipType.setValidTargetTypes((List<String>) toscaJson.get("valid_target_types"));
+
+        return relationshipType;
+    }
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogic.java
new file mode 100644 (file)
index 0000000..c07a9fc
--- /dev/null
@@ -0,0 +1,518 @@
+/*
+ * 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.impl;
+
+import fj.data.Either;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.openecomp.sdc.be.components.validation.RequirementValidation;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.RequirementDefinition;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.jsontitan.operations.RequirementOperation;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+@Component("requirementBusinessLogic")
+public class RequirementBusinessLogic extends BaseBusinessLogic {
+    private static final Logger LOGGER = LoggerFactory.getLogger(RequirementBusinessLogic.class);
+    private static final String FAILED_TO_LOCK_COMPONENT_RESPONSE_IS
+            = "Failed to lock component {}. Response is {}";
+    private static final String DELETE_REQUIREMENTS = "deleteRequirement";
+    private static final String GET_REQUIREMENTS = "getRequirements";
+    private static final String EXCEPTION_OCCURRED_DURING_REQUIREMENTS
+            = "Exception occurred during {}. Response is {}";
+
+    @Autowired
+    private RequirementOperation requirementOperation;
+    @Autowired
+    private RequirementValidation requirementValidation;
+
+
+    public void setRequirementOperation(RequirementOperation requirementOperation) {
+        this.requirementOperation = requirementOperation;
+    }
+
+    public void setRequirementValidation(RequirementValidation requirementValidation) {
+        this.requirementValidation = requirementValidation;
+    }
+
+    public Either<List<RequirementDefinition>, ResponseFormat> createRequirements(
+            String componentId, List<RequirementDefinition> requirementDefinitions,
+            User user, String errorContext, boolean lock) {
+        validateUserExists(user.getUserId(), errorContext, true);
+        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither
+                = getComponentDetails(componentId);
+        if (componentEither.isRight()) {
+            return Either.right(componentEither.right().value());
+        }
+        org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
+
+        Either<Boolean, ResponseFormat> requirementsValidationEither = requirementValidation
+                .validateRequirements(requirementDefinitions, storedComponent, false);
+        if (requirementsValidationEither.isRight()) {
+            return Either.right(requirementsValidationEither.right().value());
+        }
+
+        Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock,
+                storedComponent, errorContext);
+        if (lockResult.isRight()) {
+            return Either.right(lockResult.right().value());
+        }
+
+        try {
+            Either<List<RequirementDefinition>, StorageOperationStatus> result;
+            List<RequirementDefinition> requirementsListStoredInComponent = null;
+            Map<String, List<RequirementDefinition>> storedComponentRequirements
+                    = storedComponent.getRequirements();
+            if (org.apache.commons.collections.MapUtils.isNotEmpty(storedComponentRequirements)) {
+                RequirementDefinition requirementDefinitionToGetType = requirementDefinitions.get(0);
+                if(Objects.isNull(requirementDefinitionToGetType)) {
+                     return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
+                }
+                requirementsListStoredInComponent
+                        = getRequirementStoredInComponentByType(requirementDefinitionToGetType
+                        .getCapability(), storedComponentRequirements);
+            }
+            List<RequirementDefinition> requirementsToReturn;
+            if (org.apache.commons.collections.CollectionUtils
+                    .isNotEmpty(requirementsListStoredInComponent)) {
+                List<RequirementDefinition> requirementDefToCreate = requirementDefinitions.stream()
+                        .map(requirementDefinition -> initiateNewRequirement(storedComponent, requirementDefinition))
+                        .collect(Collectors.toList());
+                requirementsToReturn = requirementDefToCreate;
+                requirementDefToCreate.addAll(requirementsListStoredInComponent);
+                result = requirementOperation.updateRequirement(componentId, requirementDefToCreate);
+            } else {
+                requirementsToReturn = requirementDefinitions.stream().map(requirementDefinition ->
+                        initiateNewRequirement(storedComponent, requirementDefinition))
+                        .collect(Collectors.toList());
+                result = requirementOperation.addRequirement(componentId, requirementsToReturn);
+            }
+            if (result.isRight()) {
+                titanDao.rollback();
+                return Either.right(componentsUtils.getResponseFormat(
+                        componentsUtils.convertFromStorageResponse(result.right().value(),
+                                storedComponent.getComponentType()), ""));
+            }
+            titanDao.commit();
+            return Either.left(requirementsToReturn);
+        } catch (Exception e) {
+            titanDao.rollback();
+            LOGGER.error(EXCEPTION_OCCURRED_DURING_REQUIREMENTS, "addOrUpdate", e);
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+        } finally {
+            if (lockResult.isLeft() && lockResult.left().value()) {
+                graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
+                        NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
+            }
+        }
+    }
+
+    public Either<List<RequirementDefinition>, ResponseFormat> updateRequirements(
+            String componentId, List<RequirementDefinition> requirementDefinitions,
+            User user, String errorContext, boolean lock) {
+        validateUserExists(user.getUserId(), errorContext, true);
+        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither
+                = getComponentDetails(componentId);
+        if (componentEither.isRight()) {
+            return Either.right(componentEither.right().value());
+        }
+        org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
+
+        Either<Boolean, ResponseFormat> requirementsValidationEither = requirementValidation
+                .validateRequirements(requirementDefinitions, storedComponent, true);
+        if (requirementsValidationEither.isRight()) {
+            return Either.right(requirementsValidationEither.right().value());
+        }
+
+        Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock,
+                storedComponent, errorContext);
+        if (lockResult.isRight()) {
+            return Either.right(lockResult.right().value());
+        }
+        try {
+            Either<List<RequirementDefinition>, StorageOperationStatus> result;
+            List<RequirementDefinition> requirementsListStoredInComponent = null;
+            Map<String, List<RequirementDefinition>> storedComponentRequirements
+                    = storedComponent.getRequirements();
+            if (org.apache.commons.collections.MapUtils.isNotEmpty(storedComponentRequirements)) {
+                RequirementDefinition requirementDefinitionToGetType = requirementDefinitions.get(0);
+                if(Objects.isNull(requirementDefinitionToGetType)) {
+                    return Either.right(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT));
+                }
+                requirementsListStoredInComponent
+                        = getRequirementStoredInComponentByType(requirementDefinitionToGetType
+                        .getCapability(), storedComponentRequirements);
+            }
+            List<RequirementDefinition> requirementsToReturn = null;
+            if (org.apache.commons.collections.CollectionUtils
+                    .isNotEmpty(requirementsListStoredInComponent)) {
+                List<RequirementDefinition> requirementDefToUpdate = new ArrayList<>();
+                if (requirementDefinitions.stream().anyMatch(requirementDefinition ->
+                        isRequirementUsedInServiceComposition(requirementDefinition, storedComponent))) {
+                    LOGGER.error("Requirement can't be edited, since it is used in service composition");
+                    return Either.right(componentsUtils.getResponseFormat(ActionStatus
+                            .REQUIREMENT_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION));
+                }
+                for (RequirementDefinition requirementDefinitionToUpdate : requirementDefinitions) {
+                    requirementsToReturn = requirementsListStoredInComponent.stream()
+                            .filter(reqToUpdate -> reqToUpdate.getUniqueId()
+                                    .equals(requirementDefinitionToUpdate.getUniqueId()))
+                            .map(requirementDefinition -> updateRequirement(requirementDefinition,
+                                    requirementDefinitionToUpdate)).collect(Collectors.toList());
+                    requirementsListStoredInComponent.removeIf(reqToUpdate ->
+                            reqToUpdate.getUniqueId().equals(requirementDefinitionToUpdate.getUniqueId()));
+
+                    if (CollectionUtils.isNotEmpty(requirementsToReturn)) {
+                        requirementsListStoredInComponent.addAll(requirementsToReturn);
+                        requirementDefToUpdate.addAll(requirementsListStoredInComponent);
+                    } else {
+                        Either<List<RequirementDefinition>, ResponseFormat> updateCapTypeEither
+                                = handleUpdateRequirementCapabilityWhenNewCapabilityExist(storedComponent,
+                                storedComponentRequirements,
+                                requirementsToReturn, requirementDefinitionToUpdate);
+                        if (updateCapTypeEither.isRight()) {
+                            return Either.right(updateCapTypeEither.right().value());
+                        }
+                        requirementDefToUpdate = updateCapTypeEither.left().value();
+                    }
+                }
+                result = requirementOperation.updateRequirement(componentId, requirementDefToUpdate);
+            } else {
+                Either<List<RequirementDefinition>, ResponseFormat> requirementDefinitionToDelete
+                        = handleRequirementCapabilityUpdateWhenNewCapabilityNotExist(requirementDefinitions,
+                        storedComponent, storedComponentRequirements);
+                if (requirementDefinitionToDelete != null) {
+                    return requirementDefinitionToDelete;
+                }
+                requirementsToReturn = requirementDefinitions.stream().map(requirementDefinition ->
+                        initiateNewRequirement(storedComponent, requirementDefinition))
+                        .collect(Collectors.toList());
+                result = requirementOperation.addRequirement(componentId, requirementsToReturn);
+            }
+            if (result.isRight()) {
+                titanDao.rollback();
+                return Either.right(componentsUtils.getResponseFormat(
+                        componentsUtils.convertFromStorageResponse(result.right().value(),
+                                storedComponent.getComponentType()), ""));
+            }
+            titanDao.commit();
+            return Either.left(requirementsToReturn);
+        } catch (Exception e) {
+            titanDao.rollback();
+            LOGGER.error(EXCEPTION_OCCURRED_DURING_REQUIREMENTS, "addOrUpdate", e);
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+        } finally {
+            if (lockResult.isLeft() && lockResult.left().value()) {
+                graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
+                        NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
+            }
+        }
+    }
+
+    private Either<List<RequirementDefinition>, ResponseFormat> handleUpdateRequirementCapabilityWhenNewCapabilityExist(
+            org.openecomp.sdc.be.model.Component storedComponent,
+            Map<String, List<RequirementDefinition>> storedComponentRequirements,
+            List<RequirementDefinition> requirementsToReturn,
+            RequirementDefinition requirementDefinitionToUpdate) {
+        List<RequirementDefinition> requirementsListStoredInComponent;
+        List<RequirementDefinition> requirementDefsToCreateOrUpdate = new ArrayList<>();
+        Optional<RequirementDefinition> definitionOptional = storedComponentRequirements
+                .values().stream().flatMap(Collection::stream)
+                .filter(requirementDefinition -> requirementDefinition.getUniqueId()
+                        .equals(requirementDefinitionToUpdate.getUniqueId())).findAny();
+        if (!definitionOptional.isPresent()) {
+            return Either.right(componentsUtils.getResponseFormat(
+                    ActionStatus.REQUIREMENT_NOT_FOUND, storedComponent.getUniqueId()));
+        }
+        RequirementDefinition requirementDefinitionToDelete = definitionOptional.get();
+
+        requirementsListStoredInComponent = getRequirementStoredInComponentByType(
+                requirementDefinitionToUpdate.getCapability(), storedComponentRequirements);
+        Either<List<RequirementDefinition>, StorageOperationStatus> deleteRequirementEither
+                = deleteRequirement(storedComponent, storedComponentRequirements, requirementDefinitionToDelete);
+        if (deleteRequirementEither.isRight()) {
+            titanDao.rollback();
+            return Either.right(componentsUtils.getResponseFormat(deleteRequirementEither.right().value()));
+        }
+        requirementsToReturn.add(initiateNewRequirement(storedComponent, requirementDefinitionToUpdate));
+
+        requirementDefsToCreateOrUpdate.addAll(requirementsToReturn);
+        requirementDefsToCreateOrUpdate.addAll(requirementsListStoredInComponent);
+        return Either.left(requirementDefsToCreateOrUpdate);
+    }
+
+    private Either<List<RequirementDefinition>, ResponseFormat> handleRequirementCapabilityUpdateWhenNewCapabilityNotExist(
+            List<RequirementDefinition> requirementDefinitions,
+            org.openecomp.sdc.be.model.Component storedComponent,
+            Map<String, List<RequirementDefinition>> storedComponentRequirements) {
+        for (RequirementDefinition requirementDefinitionToUpdate : requirementDefinitions) {
+
+            Optional<RequirementDefinition> definitionOptional = storedComponentRequirements
+                    .values().stream().flatMap(Collection::stream)
+                    .filter(requirementDefinition -> requirementDefinition.getUniqueId()
+                            .equals(requirementDefinitionToUpdate.getUniqueId())).findAny();
+            if (!definitionOptional.isPresent()) {
+                return Either.right(componentsUtils.getResponseFormat(
+                        ActionStatus.REQUIREMENT_NOT_FOUND, storedComponent.getUniqueId()));
+            }
+            RequirementDefinition requirementDefinitionToDelete = definitionOptional.get();
+            Boolean isRequirementUsedInServiceComposition
+                    = isRequirementUsedInServiceComposition(requirementDefinitionToDelete, storedComponent);
+            if (isRequirementUsedInServiceComposition) {
+                LOGGER.error("Requirement {} can't be edited, since it is used in service composition",
+                        requirementDefinitionToDelete.getUniqueId());
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus
+                                .REQUIREMENT_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION,
+                        requirementDefinitionToDelete.getName()));
+            }
+            Either<List<RequirementDefinition>, StorageOperationStatus> deleteRequirementEither
+                    = deleteRequirement(storedComponent, storedComponentRequirements, requirementDefinitionToDelete);
+            if (deleteRequirementEither.isRight()) {
+                titanDao.rollback();
+                return Either.right(componentsUtils.getResponseFormat(deleteRequirementEither.right().value()));
+            }
+        }
+        return null;
+    }
+
+    public Either<RequirementDefinition, ResponseFormat> getRequirement(String componentId,
+                                                                        String requirementIdToGet, User user, boolean lock) {
+        validateUserExists(user.getUserId(), GET_REQUIREMENTS, true);
+        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither = getComponentDetails(componentId);
+        if (componentEither.isRight()) {
+            return Either.right(componentEither.right().value());
+        }
+        org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
+
+        Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock, storedComponent, GET_REQUIREMENTS);
+        if (lockResult.isRight()) {
+            return Either.right(lockResult.right().value());
+        }
+        try {
+
+            List<RequirementDefinition> requirementDefinitions = storedComponent.getRequirements().values().stream()
+                    .flatMap(Collection::stream).collect(Collectors.toList());
+            if (requirementDefinitions.isEmpty()) {
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND, componentId));
+            }
+
+            RequirementDefinition requirementDefinitionToReturn;
+            Optional<RequirementDefinition> requirementDefinitionOptional = requirementDefinitions.stream()
+                    .filter(requirementDefinition -> requirementDefinition.getUniqueId().equals(requirementIdToGet)).findAny();
+            if (requirementDefinitionOptional.isPresent()) {
+                requirementDefinitionToReturn = requirementDefinitionOptional.get();
+            } else {
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND, componentId));
+            }
+            return Either.left(requirementDefinitionToReturn);
+        } catch (Exception e) {
+            LOGGER.error(EXCEPTION_OCCURRED_DURING_REQUIREMENTS, "get", e);
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND, componentId));
+        } finally {
+            if (lockResult.isLeft() && lockResult.left().value()) {
+                graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
+                        NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
+            }
+        }
+    }
+
+    public Either<RequirementDefinition, ResponseFormat> deleteRequirement(String componentId,
+                                                                           String requirementIdToDelete,
+                                                                           User user, boolean lock) {
+        validateUserExists(user.getUserId(), DELETE_REQUIREMENTS, true);
+        Either<org.openecomp.sdc.be.model.Component, ResponseFormat> componentEither
+                = getComponentDetails(componentId);
+        if (componentEither.isRight()) {
+            return Either.right(componentEither.right().value());
+        }
+        org.openecomp.sdc.be.model.Component storedComponent = componentEither.left().value();
+
+        Either<Boolean, ResponseFormat> lockResult = lockComponentResult(lock, storedComponent, DELETE_REQUIREMENTS);
+        if (lockResult.isRight()) {
+            return Either.right(lockResult.right().value());
+        }
+
+        try {
+            Map<String, List<RequirementDefinition>> storedComponentRequirements = storedComponent.getRequirements();
+            if (storedComponentRequirements.isEmpty()) {
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND, componentId));
+            }
+
+            Optional<RequirementDefinition> definitionOptional = storedComponentRequirements
+                    .values().stream().flatMap(Collection::stream)
+                    .filter(requirementDefinition -> requirementDefinition.getUniqueId()
+                            .equals(requirementIdToDelete)).findAny();
+            if (!definitionOptional.isPresent()) {
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND, componentId));
+            }
+            RequirementDefinition requirementDefinitionToDelete = definitionOptional.get();
+
+            Boolean isRequirementUsedInServiceComposition
+                    = isRequirementUsedInServiceComposition(requirementDefinitionToDelete, storedComponent);
+            if (isRequirementUsedInServiceComposition) {
+                LOGGER.error("Requirement {} can't be deleted, since it is used in service composition",
+                        requirementDefinitionToDelete.getUniqueId());
+                return Either.right(componentsUtils.getResponseFormat(ActionStatus
+                                .CAPABILITY_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION,
+                        requirementDefinitionToDelete.getName()));
+            }
+
+            Either<List<RequirementDefinition>, StorageOperationStatus> result
+                    = deleteRequirement(storedComponent, storedComponentRequirements, requirementDefinitionToDelete);
+            if (result.isRight()) {
+                titanDao.rollback();
+                LOGGER.error("Failed to delete requirement  from component {}. Response is {}",
+                        storedComponent.getName(), result.right().value());
+                return Either.right(componentsUtils.getResponseFormat(componentsUtils
+                        .convertFromStorageResponse(result.right().value(), storedComponent.getComponentType())));
+            }
+            titanDao.commit();
+            return Either.left(requirementDefinitionToDelete);
+        } catch (Exception e) {
+            LOGGER.error(EXCEPTION_OCCURRED_DURING_REQUIREMENTS, "delete", e);
+            titanDao.rollback();
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.REQUIREMENT_NOT_FOUND));
+        } finally {
+            if (lockResult.isLeft() && lockResult.left().value()) {
+                graphLockOperation.unlockComponent(storedComponent.getUniqueId(),
+                        NodeTypeEnum.getByNameIgnoreCase(storedComponent.getComponentType().getValue()));
+            }
+        }
+    }
+
+    private Either<List<RequirementDefinition>, StorageOperationStatus> deleteRequirement(
+            org.openecomp.sdc.be.model.Component storedComponent, Map<String,
+            List<RequirementDefinition>> storedComponentRequirements,
+            RequirementDefinition requirementDefinitionToDelete) {
+        List<RequirementDefinition> requirementStoredInComponentByType =
+                getRequirementStoredInComponentByType(requirementDefinitionToDelete.getCapability(),
+                        storedComponentRequirements);
+        if(requirementStoredInComponentByType == null) {
+            return Either.right(StorageOperationStatus.BAD_REQUEST);
+        }
+        requirementStoredInComponentByType.removeIf(requirementDefinition ->
+                requirementDefinition.getUniqueId().equals(requirementDefinitionToDelete.getUniqueId()));
+        Either<List<RequirementDefinition>, StorageOperationStatus> result;
+        if (requirementStoredInComponentByType.isEmpty()) {
+
+            StorageOperationStatus operationStatus = requirementOperation.deleteRequirements(storedComponent,
+                    requirementDefinitionToDelete.getCapability());
+            if (operationStatus.equals(StorageOperationStatus.OK)) {
+                result = Either.left(Collections.singletonList(requirementDefinitionToDelete));
+            } else {
+                result = Either.right(operationStatus);
+            }
+        } else {
+            result = requirementOperation.updateRequirement(storedComponent.getUniqueId(),
+                    requirementStoredInComponentByType);
+        }
+        return result;
+    }
+
+    private Either<org.openecomp.sdc.be.model.Component, ResponseFormat> getComponentDetails(String componentId) {
+        ComponentParametersView filter = new ComponentParametersView(true);
+        filter.setIgnoreRequirements(false);
+        Either<org.openecomp.sdc.be.model.Component, StorageOperationStatus> componentStorageOperationStatusEither
+                = toscaOperationFacade.getToscaElement(componentId, filter);
+        if (componentStorageOperationStatusEither.isRight()) {
+            StorageOperationStatus errorStatus = componentStorageOperationStatusEither.right().value();
+            LOGGER.error("Failed to fetch component information by component id {}, Response is {}", componentId, errorStatus);
+            return Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(errorStatus)));
+        }
+        return Either.left(componentStorageOperationStatusEither.left().value());
+    }
+
+    private Either<Boolean, ResponseFormat> lockComponentResult(boolean lock,
+                                                                org.openecomp.sdc.be.model.Component component,
+                                                                String action) {
+        if (lock) {
+            Either<Boolean, ResponseFormat> lockResult = lockComponent(component.getUniqueId(), component, action);
+            if (lockResult.isRight()) {
+                LOGGER.debug(FAILED_TO_LOCK_COMPONENT_RESPONSE_IS, component.getName(),
+                        lockResult.right().value().getFormattedMessage());
+                titanDao.rollback();
+                return Either.right(lockResult.right().value());
+            }
+        }
+        return Either.left(true);
+    }
+
+    private List<RequirementDefinition> getRequirementStoredInComponentByType(
+            String capabilityType, Map<String,
+            List<RequirementDefinition>> requirements) {
+
+        Optional<Map.Entry<String, List<RequirementDefinition>>> entryOptional
+                = requirements.entrySet().stream().filter(map -> map.getKey().equals(capabilityType)).findFirst();
+        return entryOptional.map(Map.Entry::getValue).orElse(null);
+
+    }
+
+    private RequirementDefinition initiateNewRequirement(org.openecomp.sdc.be.model.Component component,
+                                                         RequirementDefinition requirementDefinition) {
+        if (StringUtils.isEmpty(requirementDefinition.getUniqueId()))
+            requirementDefinition.setUniqueId(UUID.randomUUID().toString());
+        if (StringUtils.isEmpty(requirementDefinition.getOwnerId()))
+            requirementDefinition.setOwnerId(component.getUniqueId());
+        if (StringUtils.isEmpty(requirementDefinition.getOwnerName()))
+            requirementDefinition.setOwnerName(component.getName());
+        requirementDefinition.setLeftOccurrences(requirementDefinition.getMaxOccurrences());
+        return requirementDefinition;
+    }
+
+    private RequirementDefinition updateRequirement(RequirementDefinition storedRequirement,
+                                                    RequirementDefinition requirementToUpdate) {
+        storedRequirement.setName(requirementToUpdate.getName());
+        storedRequirement.setCapability(requirementToUpdate.getCapability());
+        storedRequirement.setNode(requirementToUpdate.getNode());
+        storedRequirement.setRelationship(requirementToUpdate.getRelationship());
+        storedRequirement.setMinOccurrences(requirementToUpdate.getMinOccurrences());
+        storedRequirement.setMaxOccurrences(requirementToUpdate.getMaxOccurrences());
+        return storedRequirement;
+    }
+
+    private Boolean isRequirementUsedInServiceComposition(RequirementDefinition requirementDefinition,
+                                                          org.openecomp.sdc.be.model.Component component) {
+        Either<List<org.openecomp.sdc.be.model.Component>, StorageOperationStatus> componentList
+                = toscaOperationFacade.getParentComponents(component.getUniqueId());
+        if (componentList.isRight()) {
+            return Boolean.FALSE;
+        }
+        return componentList.left().value().stream()
+                .flatMap(parentComponent -> parentComponent.getComponentInstancesRelations()
+                        .stream()).flatMap(requirementCapabilityRelDef -> requirementCapabilityRelDef.getRelationships().stream())
+                .anyMatch(capabilityRequirementRelationship -> capabilityRequirementRelationship.getRelation()
+                        .getRequirementUid().equals(requirementDefinition.getUniqueId()));
+    }
+}
index e6a6491..2ca6ca4 100644 (file)
@@ -37,6 +37,7 @@ 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.StorageOperationStatus;
 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
+import org.openecomp.sdc.be.tosca.ToscaUtils;
 import org.openecomp.sdc.be.user.Role;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.exception.ResponseFormat;
@@ -193,6 +194,7 @@ public class CertificationChangeTransition extends LifeCycleTransition {
                 }
             }
             updateCalculatedCapabilitiesRequirements(componentAfterCertification);
+            updateCapReqOwnerId(componentAfterCertification);
             result = Either.left(componentAfterCertification);
             return result;
         } finally {
@@ -212,6 +214,12 @@ public class CertificationChangeTransition extends LifeCycleTransition {
 
     }
 
+    private void updateCapReqOwnerId(Component component) {
+        if(component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) {
+            toscaOperationFacade.updateCapReqOwnerId(component.getUniqueId());
+        }
+    }
+
     private void updateCalculatedCapabilitiesRequirements(Component certifiedComponent) {
         if(certifiedComponent.getComponentType() == ComponentTypeEnum.SERVICE){
             toscaOperationFacade.updateNamesOfCalculatedCapabilitiesRequirements(certifiedComponent.getUniqueId());
index 525df14..0c44642 100644 (file)
@@ -123,6 +123,7 @@ public class CheckoutTransition extends LifeCycleTransition {
                     }
                 }
                 handleCalculatedCapabilitiesRequirements(clonedComponent);
+               updateCapReqOwnerId(clonedComponent);
             }
 
         } finally {
@@ -148,6 +149,11 @@ public class CheckoutTransition extends LifeCycleTransition {
         }
     }
 
+    private void updateCapReqOwnerId(Component component) {
+        if(component.isTopologyTemplate() && ToscaUtils.isNotComplexVfc(component)) {
+            toscaOperationFacade.updateCapReqOwnerId(component.getUniqueId());
+        }
+    }
     private StorageOperationStatus upgradeToLatestGenericData(Component clonedComponent) {
 
         StorageOperationStatus updateStatus = StorageOperationStatus.OK;
index 06da9ec..55cf75b 100644 (file)
@@ -122,11 +122,17 @@ public class MergeInstanceUtils {
             else {
                 instanceBuildingBlocks = ComponentInstanceBuildingBlocks.of(new ArrayList<>(), singletonList(componentInstance));
             }
+            return instanceBuildingBlocks;
         }
         else {
             instanceBuildingBlocks = recursiveScanForAtomicBuildingBlocks(component);
+            if(org.apache.commons.collections.MapUtils.isNotEmpty(component.getCapabilities()) || org.apache.commons.collections.MapUtils.isNotEmpty(component.getRequirements())) {
+                ComponentInstanceBuildingBlocks nonAtomicBlocks = ComponentInstanceBuildingBlocks.of(new ArrayList<>(), singletonList(componentInstance));
+                return ComponentInstanceBuildingBlocks.merge(instanceBuildingBlocks, nonAtomicBlocks);
+            }
+            return instanceBuildingBlocks;
+        
         }
-        return instanceBuildingBlocks;
     }
 
     public RelationMergeInfo mapRelationCapability(RequirementCapabilityRelDef relDef, List<CapabilityOwner> capsOwners) {
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidation.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidation.java
new file mode 100644 (file)
index 0000000..9590ec9
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * 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.validation;
+
+import fj.data.Either;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+@Component("capabilitiesValidation")
+public class CapabilitiesValidation {
+    private static final Logger LOGGER = LoggerFactory.getLogger(CapabilitiesValidation.class);
+    private static final String CAPABILITY_NOT_FOUND_IN_COMPONENT = "Capability not found in component {} ";
+    private static final Pattern NAME_VALIDATION_REGEX_PATTERN = Pattern.compile("^[a-zA-Z0-9_.]*$");
+
+    public Either<Boolean, ResponseFormat> validateCapabilities(
+            Collection<CapabilityDefinition> capabilities,
+            org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
+
+        for(CapabilityDefinition capabilityDefinition : capabilities) {
+            Either<Boolean, ResponseFormat> validateCapabilityResponse = validateCapability(
+                    capabilityDefinition, component, isUpdate);
+            if (validateCapabilityResponse.isRight()) {
+                return validateCapabilityResponse;
+            }
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> validateCapability(CapabilityDefinition capabilityDefinition,
+                                                               org.openecomp.sdc.be.model.Component component,
+                                                               boolean isUpdate) {
+        ResponseFormatManager responseFormatManager = getResponseFormatManager();
+
+        if(isUpdate) {
+            Either<Boolean, ResponseFormat> capabilityExistValidationEither
+                    = isCapabilityExist(capabilityDefinition, responseFormatManager, component);
+            if (capabilityExistValidationEither.isRight()) {
+                return Either.right(capabilityExistValidationEither.right().value());
+            }
+        }
+        Either<Boolean, ResponseFormat> capabilityNameValidationResponse
+                = validateCapabilityName(capabilityDefinition, responseFormatManager, component, isUpdate);
+        if (capabilityNameValidationResponse.isRight()) {
+            return Either.right(capabilityNameValidationResponse.right().value());
+        }
+        Either<Boolean, ResponseFormat> capabilityTypeEmptyEither =
+                isCapabilityTypeEmpty(responseFormatManager, capabilityDefinition.getType());
+        if (capabilityTypeEmptyEither.isRight()) {
+            return Either.right(capabilityTypeEmptyEither.right().value());
+        }
+
+        Either<Boolean, ResponseFormat> capabilityOccurrencesValidationEither =
+                validateOccurrences(capabilityDefinition, responseFormatManager);
+        if (capabilityOccurrencesValidationEither.isRight()) {
+            return Either.right(capabilityOccurrencesValidationEither.right().value());
+        }
+
+        return Either.left(Boolean.FALSE);
+    }
+
+    private Either<Boolean, ResponseFormat> validateOccurrences(CapabilityDefinition capabilityDefinition,
+                                                                ResponseFormatManager responseFormatManager) {
+        String maxOccurrences = capabilityDefinition.getMaxOccurrences();
+        String minOccurrences = capabilityDefinition.getMinOccurrences();
+        if(StringUtils.isNotEmpty(maxOccurrences) && StringUtils.isNotEmpty(minOccurrences)) {
+            Either<Boolean, ResponseFormat> capabilityOccurrencesValidationEither =
+                    validateOccurrences(responseFormatManager, minOccurrences,
+                            maxOccurrences);
+            if (capabilityOccurrencesValidationEither.isRight()) {
+                return Either.right(capabilityOccurrencesValidationEither.right().value());
+            }
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> isCapabilityExist(CapabilityDefinition definition,
+                                                              ResponseFormatManager responseFormatManager,
+                                                              org.openecomp.sdc.be.model.Component component) {
+        Map<String, List<CapabilityDefinition>> componentCapabilities = component.getCapabilities();
+        if(MapUtils.isEmpty(componentCapabilities)){
+            LOGGER.error(CAPABILITY_NOT_FOUND_IN_COMPONENT, component.getUniqueId());
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .CAPABILITY_NOT_FOUND, component.getUniqueId());
+            return Either.right(errorResponse);
+        }
+
+        List<CapabilityDefinition> capabilityDefinitionList = componentCapabilities.values()
+                .stream().flatMap(Collection::stream).collect(Collectors.toList());
+        if(CollectionUtils.isEmpty(capabilityDefinitionList)){
+            LOGGER.error(CAPABILITY_NOT_FOUND_IN_COMPONENT, component.getUniqueId());
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .CAPABILITY_NOT_FOUND, component.getUniqueId());
+            return Either.right(errorResponse);
+        }
+        boolean isCapabilityExist = capabilityDefinitionList.stream().anyMatch(capabilityDefinition ->
+                capabilityDefinition.getUniqueId().equalsIgnoreCase(definition.getUniqueId()));
+
+        if(!isCapabilityExist) {
+            LOGGER.error(CAPABILITY_NOT_FOUND_IN_COMPONENT, component.getUniqueId());
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .CAPABILITY_NOT_FOUND, component.getUniqueId());
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> validateCapabilityName(CapabilityDefinition capabilityDefinition,
+                                                                   ResponseFormatManager responseFormatManager,
+                                                                   org.openecomp.sdc.be.model.Component component,
+                                                                   boolean isUpdate) {
+        Either<Boolean, ResponseFormat> capabilityNameEmptyEither =
+                isCapabilityNameEmpty(responseFormatManager, capabilityDefinition.getName());
+        if (capabilityNameEmptyEither.isRight()) {
+            return Either.right(capabilityNameEmptyEither.right().value());
+        }
+
+        Either<Boolean, ResponseFormat> capabilityNameRegexValidationResponse =
+                isCapabilityNameRegexValid(responseFormatManager, capabilityDefinition.getName());
+        if (capabilityNameRegexValidationResponse.isRight()) {
+            return Either.right(capabilityNameRegexValidationResponse.right().value());
+        }
+
+        Either<Boolean, ResponseFormat> operationTypeUniqueResponse
+                = validateCapabilityNameUnique(capabilityDefinition, component, isUpdate );
+        if(operationTypeUniqueResponse.isRight()) {
+            return Either.right(operationTypeUniqueResponse.right().value());
+        }
+        if (!operationTypeUniqueResponse.left().value()) {
+            LOGGER.error("Capability name  {} already in use ", capabilityDefinition.getName());
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .CAPABILITY_NAME_ALREADY_IN_USE, capabilityDefinition.getName());
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> isCapabilityNameEmpty(
+            ResponseFormatManager responseFormatManager, String capabilityName) {
+        if (StringUtils.isEmpty(capabilityName)) {
+            LOGGER.error("Capability Name is mandatory");
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .CAPABILITY_NAME_MANDATORY);
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> isCapabilityTypeEmpty(
+            ResponseFormatManager responseFormatManager, String capabilityType) {
+        if (StringUtils.isEmpty(capabilityType)) {
+            LOGGER.error("Capability type is mandatory");
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .CAPABILITY_TYPE_MANDATORY);
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+
+    private Either<Boolean, ResponseFormat> validateOccurrences        (
+            ResponseFormatManager responseFormatManager,
+            String minOccurrences, String maxOccurrences ) {
+        if(StringUtils.isNotEmpty(maxOccurrences)&& "UNBOUNDED".equalsIgnoreCase(maxOccurrences)
+                && Integer.parseInt(minOccurrences) >= 0) {
+            return Either.left(Boolean.TRUE);
+        } else if(Integer.parseInt(minOccurrences) < 0) {
+            LOGGER.debug("Invalid occurrences format.low_bound occurrence negative {}", minOccurrences);
+            ResponseFormat responseFormat = responseFormatManager.getResponseFormat(ActionStatus.INVALID_OCCURRENCES);
+            return Either.right(responseFormat);
+        } else if(Integer.parseInt(maxOccurrences) < Integer.parseInt(minOccurrences)){
+            LOGGER.error("Capability maxOccurrences should be greater than minOccurrences");
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .MAX_OCCURRENCES_SHOULD_BE_GREATER_THAN_MIN_OCCURRENCES);
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> validateCapabilityNameUnique(
+            CapabilityDefinition capabilityDefinition,
+            org.openecomp.sdc.be.model.Component component,
+            boolean isUpdate) {
+        boolean isCapabilityNameUnique = false;
+
+        Map<String, List<CapabilityDefinition>> componentCapabilities = component.getCapabilities();
+        if(MapUtils.isEmpty(componentCapabilities)){
+            return Either.left(true);
+        }
+
+        List<CapabilityDefinition> capabilityDefinitionList = componentCapabilities.values()
+                .stream().flatMap(Collection::stream).collect(Collectors.toList());
+
+        if(CollectionUtils.isEmpty(capabilityDefinitionList)){
+            return Either.left(true);
+        }
+
+        Map<String, String> capabilityNameMap = new HashMap<>();
+        capabilityDefinitionList.forEach(capability -> capabilityNameMap
+                .put(capability.getUniqueId(), capability.getName()));
+
+        if (!capabilityNameMap.values().contains(capabilityDefinition.getName())){
+            isCapabilityNameUnique = true;
+        }
+        if (!isCapabilityNameUnique && isUpdate){
+            List<Map.Entry<String, String>> capNamesEntries = capabilityNameMap.entrySet()
+                    .stream().filter(entry -> entry.getValue()
+                            .equalsIgnoreCase(capabilityDefinition.getName()))
+                    .collect(Collectors.toList());
+            if(capNamesEntries.size() == 1 && capNamesEntries.get(0).getKey()
+                    .equals(capabilityDefinition.getUniqueId())) {
+                isCapabilityNameUnique = true;
+            }
+        }
+        return Either.left(isCapabilityNameUnique);
+    }
+
+    private Either<Boolean, ResponseFormat> isCapabilityNameRegexValid(ResponseFormatManager responseFormatManager,
+                                                                       String capabilityName) {
+        if (!isValidCapabilityName(capabilityName)) {
+            LOGGER.error("Capability name {} is invalid, Only alphanumeric chars, underscore and dot allowed",
+                    capabilityName);
+            ResponseFormat errorResponse = responseFormatManager
+                    .getResponseFormat(ActionStatus.INVALID_CAPABILITY_NAME, capabilityName);
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private boolean isValidCapabilityName(String capabilityName) {
+        return NAME_VALIDATION_REGEX_PATTERN.matcher(capabilityName).matches();
+    }
+
+    protected ResponseFormatManager getResponseFormatManager() {
+        return ResponseFormatManager.getInstance();
+    }
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/RequirementValidation.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/RequirementValidation.java
new file mode 100644 (file)
index 0000000..0c6a294
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * 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.validation;
+
+import fj.data.Either;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.model.RequirementDefinition;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+@Component("requirementValidation")
+public class RequirementValidation {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(RequirementValidation.class);
+    private static final String REQUIREMENT_NOT_FOUND_IN_COMPONENT = "Requirement not found in component {} ";
+    private static final Pattern NAME_VALIDATION_REGEX_PATTERN = Pattern.compile("^[a-zA-Z0-9_.]*$");
+
+    public Either<Boolean, ResponseFormat> validateRequirements(
+            Collection<RequirementDefinition> requirements,
+            org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
+
+        for(RequirementDefinition requirementDefinition : requirements) {
+            Either<Boolean, ResponseFormat> requirementValidationResponse
+                    = validateRequirement(requirementDefinition, component, isUpdate);
+            if (requirementValidationResponse.isRight()) {
+                return requirementValidationResponse;
+            }
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> validateRequirement(
+            RequirementDefinition requirementDefinition,
+            org.openecomp.sdc.be.model.Component component,
+            boolean isUpdate) {
+        ResponseFormatManager responseFormatManager = getResponseFormatManager();
+        if(isUpdate) {
+            Either<Boolean, ResponseFormat> requirementExistValidationEither
+                    = isRequirementExist(requirementDefinition, responseFormatManager, component);
+            if (requirementExistValidationEither.isRight()) {
+                return Either.right(requirementExistValidationEither.right().value());
+            }
+        }
+
+        Either<Boolean, ResponseFormat> requirementNameValidationResponse
+                = isRequirementNameValid(requirementDefinition, responseFormatManager,
+                component, isUpdate);
+        if (requirementNameValidationResponse.isRight()) {
+            return Either.right(requirementNameValidationResponse.right().value());
+        }
+
+        Either<Boolean, ResponseFormat> requirementTypeEmptyEither =
+                isRequirementCapabilityEmpty(responseFormatManager,
+                        requirementDefinition.getCapability());
+        if (requirementTypeEmptyEither.isRight()) {
+            return Either.right(requirementTypeEmptyEither.right().value());
+        }
+        Either<Boolean, ResponseFormat> requirementOccurrencesValidationEither =
+                validateOccurrences(requirementDefinition, responseFormatManager);
+        if (requirementOccurrencesValidationEither.isRight()) {
+            return Either.right(requirementOccurrencesValidationEither.right().value());
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> validateOccurrences(RequirementDefinition requirementDefinition,
+                                                                ResponseFormatManager responseFormatManager) {
+        String maxOccurrences = requirementDefinition.getMaxOccurrences();
+        String minOccurrences = requirementDefinition.getMinOccurrences();
+        if(StringUtils.isNotEmpty(maxOccurrences) && StringUtils.isNotEmpty(minOccurrences)) {
+            Either<Boolean, ResponseFormat> requirementOccurrencesValidationEither =
+                    validateOccurrences(responseFormatManager, minOccurrences,
+                            maxOccurrences);
+            if (requirementOccurrencesValidationEither.isRight()) {
+                return Either.right(requirementOccurrencesValidationEither.right().value());
+            }
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> isRequirementNameValid(
+            RequirementDefinition requirementDefinition,
+            ResponseFormatManager responseFormatManager,
+            org.openecomp.sdc.be.model.Component component, boolean isUpdate) {
+        Either<Boolean, ResponseFormat> requirementNameEmptyEither =
+                isRequirementNameEmpty(responseFormatManager, requirementDefinition.getName());
+        if (requirementNameEmptyEither.isRight()) {
+            return Either.right(requirementNameEmptyEither.right().value());
+        }
+
+        Either<Boolean, ResponseFormat> requirementNameRegexValidationResponse =
+                isRequirementNameRegexValid(responseFormatManager, requirementDefinition.getName());
+        if (requirementNameRegexValidationResponse.isRight()) {
+            return Either.right(requirementNameRegexValidationResponse.right().value());
+        }
+
+        Either<Boolean, ResponseFormat> requirementNameUniqueResponse
+                = validateRequirementNameUnique(requirementDefinition,
+                component, isUpdate );
+        if(requirementNameUniqueResponse.isRight()) {
+            return Either.right(requirementNameUniqueResponse.right().value());
+        }
+        if (!requirementNameUniqueResponse.left().value()) {
+            LOGGER.error("Requirement name  {} already in use ", requirementDefinition.getName());
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .REQUIREMENT_NAME_ALREADY_IN_USE, requirementDefinition.getName());
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> isRequirementNameEmpty(
+            ResponseFormatManager responseFormatManager,
+            String requirementName) {
+        if (StringUtils.isEmpty(requirementName)) {
+            LOGGER.error("Requirement Name is mandatory");
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .REQUIREMENT_NAME_MANDATORY);
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> validateOccurrences        (
+            ResponseFormatManager responseFormatManager,
+            String minOccurrences, String maxOccurrences ) {
+        if(StringUtils.isNotEmpty(maxOccurrences)&& "UNBOUNDED".equalsIgnoreCase(maxOccurrences)
+                && Integer.parseInt(minOccurrences) >= 0) {
+            return Either.left(Boolean.TRUE);
+        } else if(Integer.parseInt(minOccurrences) < 0) {
+            LOGGER.debug("Invalid occurrences format.low_bound occurrence negative {}", minOccurrences);
+            ResponseFormat responseFormat = responseFormatManager.getResponseFormat(ActionStatus.INVALID_OCCURRENCES);
+            return Either.right(responseFormat);
+        }
+        else if(Integer.parseInt(maxOccurrences) < Integer.parseInt(minOccurrences)){
+            LOGGER.error("Requirement maxOccurrences should be greater than minOccurrences");
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .MAX_OCCURRENCES_SHOULD_BE_GREATER_THAN_MIN_OCCURRENCES);
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+    private Either<Boolean, ResponseFormat> isRequirementCapabilityEmpty(
+            ResponseFormatManager responseFormatManager,
+            String requirementCapability) {
+        if (StringUtils.isEmpty(requirementCapability)) {
+            LOGGER.error("Requirement capability is mandatory");
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .REQUIREMENT_CAPABILITY_MANDATORY);
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> validateRequirementNameUnique(
+            RequirementDefinition requirementDefinition,
+            org.openecomp.sdc.be.model.Component component,
+            boolean isUpdate) {
+        boolean isRequirementNameUnique = false;
+
+        Map<String, List<RequirementDefinition>> componentRequirements = component.getRequirements();
+        if(MapUtils.isEmpty(componentRequirements)){
+            return Either.left(true);
+        }
+        List<RequirementDefinition> requirementDefinitionList = componentRequirements.values()
+                .stream().flatMap(Collection::stream).collect(Collectors.toList());
+
+        if(CollectionUtils.isEmpty(requirementDefinitionList)){
+            return Either.left(true);
+        }
+
+        Map<String, String> requirementNameMap = new HashMap<>();
+        requirementDefinitionList.forEach(requirement -> requirementNameMap
+                .put(requirement.getUniqueId(), requirement.getName()));
+
+        if (!requirementNameMap.values().contains(requirementDefinition.getName())){
+            isRequirementNameUnique = true;
+        }
+        if (!isRequirementNameUnique && isUpdate){
+            List<Map.Entry<String, String>> reqNamesEntry = requirementNameMap.entrySet()
+                    .stream().filter(entry -> entry.getValue().equalsIgnoreCase(requirementDefinition.getName()))
+                    .collect(Collectors.toList());
+            if(reqNamesEntry.size() == 1 && reqNamesEntry.get(0).getKey()
+                    .equals(requirementDefinition.getUniqueId())) {
+                isRequirementNameUnique = true;
+            }
+        }
+        return Either.left(isRequirementNameUnique);
+    }
+
+    private Either<Boolean, ResponseFormat> isRequirementExist(
+            RequirementDefinition definition,
+            ResponseFormatManager responseFormatManager,
+            org.openecomp.sdc.be.model.Component component) {
+        Map<String, List<RequirementDefinition>> componentRequirements = component.getRequirements();
+        if(MapUtils.isEmpty(componentRequirements)){
+            LOGGER.error(REQUIREMENT_NOT_FOUND_IN_COMPONENT, component.getUniqueId());
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .REQUIREMENT_NOT_FOUND, component.getUniqueId());
+            return Either.right(errorResponse);
+        }
+
+        List<RequirementDefinition> requirementDefinitionList = componentRequirements.values()
+                .stream().flatMap(Collection::stream).collect(Collectors.toList());
+        if(CollectionUtils.isEmpty(requirementDefinitionList)){
+            LOGGER.error(REQUIREMENT_NOT_FOUND_IN_COMPONENT, component.getUniqueId());
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .REQUIREMENT_NOT_FOUND, component.getUniqueId());
+            return Either.right(errorResponse);
+        }
+        boolean isRequirementExist = requirementDefinitionList.stream()
+                .anyMatch(requirementDefinition -> requirementDefinition.getUniqueId()
+                        .equalsIgnoreCase(definition.getUniqueId()));
+
+        if(!isRequirementExist) {
+            LOGGER.error(REQUIREMENT_NOT_FOUND_IN_COMPONENT, component.getUniqueId());
+            ResponseFormat errorResponse = responseFormatManager.getResponseFormat(ActionStatus
+                    .REQUIREMENT_NOT_FOUND, component.getUniqueId());
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private Either<Boolean, ResponseFormat> isRequirementNameRegexValid(ResponseFormatManager responseFormatManager,
+                                                                        String requirementName) {
+        if (!isValidRequirementName(requirementName)) {
+            LOGGER.error("Requirement name {} is invalid, Only alphanumeric chars, underscore and dot allowed",
+                    requirementName);
+            ResponseFormat errorResponse = responseFormatManager
+                    .getResponseFormat(ActionStatus.INVALID_REQUIREMENT_NAME, requirementName);
+            return Either.right(errorResponse);
+        }
+        return Either.left(Boolean.TRUE);
+    }
+
+    private boolean isValidRequirementName(String requirementName) {
+        return NAME_VALIDATION_REGEX_PATTERN.matcher(requirementName).matches();
+    }
+
+    protected ResponseFormatManager getResponseFormatManager() {
+        return ResponseFormatManager.getInstance();
+    }
+
+}
+
index 909d4da..0930daa 100644 (file)
@@ -1522,5 +1522,32 @@ public class ComponentsUtils {
         }
         return getResponseFormat(exception.getActionStatus(), exception.getParams());
     }
+    public ActionStatus convertFromStorageResponseForRelationshipType(
+            StorageOperationStatus storageResponse) {
+        ActionStatus responseEnum;
 
+        switch (storageResponse) {
+            case OK:
+                responseEnum = ActionStatus.OK;
+                break;
+            case CONNECTION_FAILURE:
+            case GRAPH_IS_LOCK:
+                responseEnum = ActionStatus.GENERAL_ERROR;
+                break;
+            case BAD_REQUEST:
+                responseEnum = ActionStatus.INVALID_CONTENT;
+                break;
+            case ENTITY_ALREADY_EXISTS:
+                responseEnum = ActionStatus.RELATIONSHIP_TYPE_ALREADY_EXIST;
+                break;
+            case SCHEMA_VIOLATION:
+                responseEnum = ActionStatus.RELATIONSHIP_TYPE_ALREADY_EXIST;
+                break;
+            default:
+                responseEnum = ActionStatus.GENERAL_ERROR;
+                break;
+        }
+        log.debug(CONVERT_STORAGE_RESPONSE_TO_ACTION_RESPONSE, storageResponse, responseEnum);
+        return responseEnum;
+    }
 }
index c321df1..d27db55 100644 (file)
@@ -148,6 +148,16 @@ public class BeGenericServlet extends BasicServlet {
         return getClassFromWebAppContext(context, () -> InterfaceOperationBusinessLogic.class);
     }
 
+    protected CapabilitiesBusinessLogic getCapabilitiesBL(ServletContext context) {
+        return getClassFromWebAppContext(context, () -> CapabilitiesBusinessLogic.class);
+    }
+
+    protected RelationshipTypeBusinessLogic getRelationshipTypeBL(ServletContext context) {
+        return getClassFromWebAppContext(context, () -> RelationshipTypeBusinessLogic.class);
+    }
+    protected RequirementBusinessLogic getRequirementBL(ServletContext context) {
+        return getClassFromWebAppContext(context, () -> RequirementBusinessLogic.class);
+    }
     ComponentsCleanBusinessLogic getComponentCleanerBL(ServletContext context) {
         return getClassFromWebAppContext(context, () -> ComponentsCleanBusinessLogic.class);
     }
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/CapabilityServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/CapabilityServlet.java
new file mode 100644 (file)
index 0000000..a1456bb
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * 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.CapabilitiesBusinessLogic;
+import org.openecomp.sdc.be.config.BeEcompErrorManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
+import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
+import org.openecomp.sdc.common.api.Constants;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.openecomp.sdc.exception.ResponseFormat;
+
+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.Optional;
+
+@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
+@Path("/v1/catalog")
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+@Api(value = "Capability Servlet", description = "Capability Servlet")
+@Singleton
+public class CapabilityServlet extends AbstractValidationsServlet {
+    private static final Logger LOGGER = Logger.getLogger(CapabilityServlet.class);
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/resources/{resourceId}/capabilities")
+    @ApiOperation(value = "Create Capabilities on resource", httpMethod = "POST",
+            notes = "Create Capabilities on resource", response = Response.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Create Capabilities"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+            @ApiResponse(code = 409, message = "Capability already exist")})
+    public Response createCapabilitiesOnResource(
+            @ApiParam(value = "Capability to create", required = true) String data,
+            @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return createOrUpdate(data, "resources" , resourceId,
+                request, userId, false, "createCapabilities");
+    }
+
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/resources/{resourceId}/capabilities")
+    @ApiOperation(value = "Update Capabilities on resource", httpMethod = "PUT",
+            notes = "Update Capabilities on resource", response = CapabilityDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Update Capabilities"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response updateCapabilitiesOnResource(
+            @ApiParam(value = "Capabilities to update", required = true) String data,
+            @ApiParam(value = "Component Id") @PathParam("resourceId") String resourceId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return createOrUpdate(data, "resources", resourceId,
+                request, userId, true, "updateCapabilities");
+    }
+
+    @GET
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/resources/{resourceId}/capabilities/{capabilityId}")
+    @ApiOperation(value = "Get Capability from resource", httpMethod = "GET",
+            notes = "GET Capability from resource", response = CapabilityDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "GET Capability"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response getCapabilityOnResource(
+            @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId,
+            @ApiParam(value = "Capability Id") @PathParam("capabilityId") String capabilityId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+        return get(capabilityId, resourceId, request, userId);
+    }
+
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/resources/{resourceId}/capabilities/{capabilityId}")
+    @ApiOperation(value = "Delete capability from resource", httpMethod = "DELETE",
+            notes = "Delete capability from resource", response = CapabilityDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Delete capability"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response deleteCapabilityOnResource(
+            @ApiParam(value = "capability Id") @PathParam("capabilityId") String capabilityId,
+            @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return delete(capabilityId, resourceId, request, userId);
+    }
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/services/{serviceId}/capabilities")
+    @ApiOperation(value = "Create Capabilities on service", httpMethod = "POST",
+            notes = "Create Capabilities on service", response = Response.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Create Capabilities"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+            @ApiResponse(code = 409, message = "Capability already exist")})
+    public Response createCapabilitiesOnService(
+            @ApiParam(value = "Capability to create", required = true) String data,
+            @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return createOrUpdate(data, "services" , serviceId,
+                request, userId, false, "createCapabilities");
+    }
+
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/services/{serviceId}/capabilities")
+    @ApiOperation(value = "Update Capabilities on service", httpMethod = "PUT",
+            notes = "Update Capabilities on service", response = CapabilityDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Update Capabilities"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response updateCapabilitiesOnService(
+            @ApiParam(value = "Capabilities to update", required = true) String data,
+            @ApiParam(value = "Component Id") @PathParam("serviceId") String serviceId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return createOrUpdate(data, "services", serviceId,
+                request, userId, true, "updateCapabilities");
+    }
+
+    @GET
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/services/{serviceId}/capabilities/{capabilityId}")
+    @ApiOperation(value = "Get Capability from service", httpMethod = "GET",
+            notes = "GET Capability from service", response = CapabilityDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "GET Capability"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response getCapabilityOnService(
+            @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId,
+            @ApiParam(value = "Capability Id") @PathParam("capabilityId") String capabilityId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+        return get(capabilityId, serviceId, request, userId);
+    }
+
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/services/{serviceId}/capabilities/{capabilityId}")
+    @ApiOperation(value = "Delete capability from service", httpMethod = "DELETE",
+            notes = "Delete capability from service", response = CapabilityDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Delete capability"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response deleteCapabilityOnService(
+            @ApiParam(value = "capability Id") @PathParam("capabilityId") String capabilityId,
+            @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return delete(capabilityId, serviceId, request, userId);
+    }
+
+    private Response createOrUpdate (String data, String componentType, String componentId,
+                                     HttpServletRequest request,
+                                     String userId,
+                                     boolean isUpdate,
+                                     String errorContext) {
+        ServletContext context = request.getSession().getServletContext();
+        String url = request.getMethod() + " " + request.getRequestURI();
+
+        User modifier = new User();
+        modifier.setUserId(userId);
+        LOGGER.debug("Start create or update request of {} with modifier id {}", url, userId);
+        try {
+            String componentIdLower = componentId.toLowerCase();
+            CapabilitiesBusinessLogic businessLogic = getCapabilitiesBL(context);
+
+            Either<List<CapabilityDefinition>, ResponseFormat> mappedCapabilitiesDataEither
+                    = getMappedCapabilitiesData(data, modifier, ComponentTypeEnum.findByParamName(componentType));
+            if(mappedCapabilitiesDataEither.isRight()) {
+                LOGGER.error("Failed to create or update capabilities");
+                buildErrorResponse(mappedCapabilitiesDataEither.right().value());
+            }
+            List<CapabilityDefinition> mappedCapabilitiesData = mappedCapabilitiesDataEither.left().value();
+            Either<List<CapabilityDefinition>, ResponseFormat> actionResponse;
+            if(isUpdate) {
+                actionResponse = businessLogic.updateCapabilities(componentIdLower,
+                        mappedCapabilitiesData, modifier, errorContext, true);
+            } else {
+                actionResponse = businessLogic.createCapabilities(componentIdLower,
+                        mappedCapabilitiesData, modifier, errorContext, true);
+            }
+            if (actionResponse.isRight()) {
+                LOGGER.error("Failed to create or update capabilities");
+                return buildErrorResponse(actionResponse.right().value());
+            }
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
+                    actionResponse.left().value());
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Capabilities create or update");
+            LOGGER.error("Failed to create or update capabilities with an error", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+    }
+
+    private Response get (String capabilityIdToGet,  String componentId,
+                          HttpServletRequest request, String userId){
+        ServletContext context = request.getSession().getServletContext();
+        String url = request.getMethod() + " " + request.getRequestURI();
+
+        User modifier = new User();
+        modifier.setUserId(userId);
+        LOGGER.debug("Start get request of {} with modifier id {}", url, userId);
+
+        try {
+            String componentIdLower = componentId.toLowerCase();
+            CapabilitiesBusinessLogic businessLogic = getCapabilitiesBL(context);
+
+            Either<CapabilityDefinition, ResponseFormat> actionResponse = businessLogic
+                    .getCapability(componentIdLower, capabilityIdToGet, modifier, true);
+            if (actionResponse.isRight()) {
+                LOGGER.error("failed to get capability");
+                return buildErrorResponse(actionResponse.right().value());
+            }
+            Object result = RepresentationUtils.toFilteredRepresentation(actionResponse.left().value());
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get capability");
+            LOGGER.error("get capabilities failed with exception", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+    }
+
+    private Response delete (String capabilityId, String componentId, HttpServletRequest
+            request, String userId){
+
+        ServletContext context = request.getSession().getServletContext();
+        String url = request.getMethod() + " " + request.getRequestURI();
+
+        User modifier = new User();
+        modifier.setUserId(userId);
+        LOGGER.debug("Start delete request of {} with modifier id {}", url, userId);
+
+        try {
+            String componentIdLower = componentId.toLowerCase();
+            CapabilitiesBusinessLogic businessLogic = getCapabilitiesBL(context);
+
+            Either<CapabilityDefinition, ResponseFormat> actionResponse = businessLogic
+                    .deleteCapability(componentIdLower, capabilityId, modifier, true);
+            if (actionResponse.isRight()) {
+                LOGGER.error("failed to delete capability");
+                return buildErrorResponse(actionResponse.right().value());
+            }
+            Object result = RepresentationUtils.toRepresentation(actionResponse.left().value());
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete capability");
+            LOGGER.error("Delete capability failed with an error", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+    }
+
+    private Either<List<CapabilityDefinition>, ResponseFormat> getMappedCapabilitiesData(String inputJson, User user,
+                                                                 ComponentTypeEnum componentTypeEnum){
+        Either<UiComponentDataTransfer, ResponseFormat> mappedData = getComponentsUtils()
+                .convertJsonToObjectUsingObjectMapper(inputJson, user, UiComponentDataTransfer.class,
+                        AuditingActionEnum.CREATE_RESOURCE, componentTypeEnum);
+        Optional<List<CapabilityDefinition>> capabilityDefinitionList =
+                mappedData.left().value().getCapabilities().values().stream().findFirst();
+        return capabilityDefinitionList.<Either<List<CapabilityDefinition>, ResponseFormat>>
+                map(Either::left).orElseGet(() -> Either.right(getComponentsUtils()
+                .getResponseFormat(ActionStatus.GENERAL_ERROR)));
+    }
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/RequirementServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/RequirementServlet.java
new file mode 100644 (file)
index 0000000..51f6783
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * 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.RequirementBusinessLogic;
+import org.openecomp.sdc.be.config.BeEcompErrorManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.model.RequirementDefinition;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
+import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
+import org.openecomp.sdc.common.api.Constants;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.openecomp.sdc.exception.ResponseFormat;
+
+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.Optional;
+
+@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
+@Path("/v1/catalog")
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+@Api(value = "Requirement Servlet", description = "Requirement Servlet")
+@Singleton
+public class RequirementServlet extends AbstractValidationsServlet {
+    private static final Logger LOGGER = Logger.getLogger(RequirementServlet.class);
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/resources/{resourceId}/requirements")
+    @ApiOperation(value = "Create requirements on resource", httpMethod = "POST",
+            notes = "Create requirements on resource", response = Response.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Create requirements"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+            @ApiResponse(code = 409, message = "requirement already exist")})
+    public Response createRequirementsOnResource(
+            @ApiParam(value = "Requirement to create", required = true) String data,
+            @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return createOrUpdate(data, "resources" , resourceId, request,
+                userId, false, "createRequirements");
+    }
+
+
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/resources/{resourceId}/requirements")
+    @ApiOperation(value = "Update Requirements on resource", httpMethod = "PUT",
+            notes = "Update Requirements on resource", response = RequirementDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Update Requirements"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response updateRequirementsOnResource(
+            @ApiParam(value = "Requirements to update", required = true) String data,
+            @ApiParam(value = "Component Id") @PathParam("resourceId") String resourceId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return createOrUpdate(data, "resources", resourceId, request,
+                userId, true, "updateRequirements");
+    }
+
+    @GET
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/resources/{resourceId}/requirements/{requirementId}")
+    @ApiOperation(value = "Get Requirement from resource", httpMethod = "GET",
+            notes = "GET Requirement from resource", response = RequirementDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "GET requirement"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response getRequirementsFromResource(
+            @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId,
+            @ApiParam(value = "Requirement Id") @PathParam("requirementId") String requirementId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+        return get(requirementId, resourceId, request, userId);
+    }
+
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/resources/{resourceId}/requirements/{requirementId}")
+    @ApiOperation(value = "Delete requirements from resource", httpMethod = "DELETE",
+            notes = "Delete requirements from resource", response = RequirementDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Delete requirement"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response deleteRequirementsFromResource(
+            @ApiParam(value = "Resource Id") @PathParam("resourceId") String resourceId,
+            @ApiParam(value = "requirement Id") @PathParam("requirementId") String requirementId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return delete(requirementId, resourceId, request, userId);
+    }
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/services/{serviceId}/requirements")
+    @ApiOperation(value = "Create requirements on service", httpMethod = "POST",
+            notes = "Create requirements on service", response = Response.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Create Requirements"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+            @ApiResponse(code = 409, message = "Requirement already exist")})
+    public Response createRequirementsOnService(
+            @ApiParam(value = "Requirements to create", required = true) String data,
+            @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return createOrUpdate(data, "services" , serviceId, request, userId,
+                false , "createRequirements");
+    }
+
+
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/services/{serviceId}/requirements")
+    @ApiOperation(value = "Update requirements on service", httpMethod = "PUT",
+            notes = "Update requirements on service", response = RequirementDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Update requirements"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response updateRequirementsOnService(
+            @ApiParam(value = "Requirements to update", required = true) String data,
+            @ApiParam(value = "Component Id") @PathParam("serviceId") String serviceId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return createOrUpdate(data, "services", serviceId, request, userId,
+                true, "updateRequirements");
+    }
+
+    @GET
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/services/{serviceId}/requirements/{requirementId}")
+    @ApiOperation(value = "Get requirement from service", httpMethod = "GET",
+            notes = "GET requirement from service", response = RequirementDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "GET Requirements"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response getRequirementsOnService(
+            @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId,
+            @ApiParam(value = "Requirement Id") @PathParam("requirementId") String requirementId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+        return get(requirementId, serviceId, request, userId);
+    }
+
+
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/services/{serviceId}/requirements/{requirementId}")
+    @ApiOperation(value = "Delete requirement from service", httpMethod = "DELETE",
+            notes = "Delete requirement from service", response = RequirementDefinition.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Delete Requirements"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content")})
+    public Response deleteRequirementsOnService(
+            @ApiParam(value = "Service Id") @PathParam("serviceId") String serviceId,
+            @ApiParam(value = "Requirement Id") @PathParam("requirementId") String requirementId,
+            @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        return delete(requirementId, serviceId, request, userId);
+    }
+
+
+    private Response createOrUpdate (String data, String componentType, String componentId,
+                                     HttpServletRequest request, String userId,
+                                     boolean isUpdate, String errorContext) {
+        ServletContext context = request.getSession().getServletContext();
+        String url = request.getMethod() + " " + request.getRequestURI();
+
+        User modifier = new User();
+        modifier.setUserId(userId);
+        LOGGER.debug("Start create or update request of {} with modifier id {}", url, userId);
+
+        try {
+            String componentIdLower = componentId.toLowerCase();
+            RequirementBusinessLogic businessLogic = getRequirementBL(context);
+
+            Either<List<RequirementDefinition>, ResponseFormat> mappedRequirementDataEither =
+                    getMappedRequirementData(data, modifier, ComponentTypeEnum.findByParamName(componentType));
+            if(mappedRequirementDataEither.isRight()) {
+                LOGGER.error("Failed to create or update requirements");
+                return buildErrorResponse(mappedRequirementDataEither.right().value());
+            }
+            List<RequirementDefinition> mappedRequirementData = mappedRequirementDataEither.left().value();
+            Either<List<RequirementDefinition>, ResponseFormat> actionResponse;
+            if(isUpdate) {
+                actionResponse = businessLogic.updateRequirements(componentIdLower, mappedRequirementData, modifier,
+                        errorContext, true);
+            } else {
+                actionResponse = businessLogic.createRequirements(componentIdLower, mappedRequirementData, modifier,
+                        errorContext, true);
+            }
+
+            if (actionResponse.isRight()) {
+                LOGGER.error("Failed to create or update requirements");
+                return buildErrorResponse(actionResponse.right().value());
+            }
+
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
+                    actionResponse.left().value());
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("requirements create or update");
+            LOGGER.error("Failed to create or update requirements with an error", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+    }
+
+    private Response get (String requirementIdToGet,  String componentId,
+                          HttpServletRequest request, String userId){
+        ServletContext context = request.getSession().getServletContext();
+        String url = request.getMethod() + " " + request.getRequestURI();
+
+        User modifier = new User();
+        modifier.setUserId(userId);
+        LOGGER.debug("Start get request of {} with modifier id {}", url, userId);
+
+        try {
+            String componentIdLower = componentId.toLowerCase();
+            RequirementBusinessLogic businessLogic = getRequirementBL(context);
+
+            Either<RequirementDefinition, ResponseFormat> actionResponse = businessLogic
+                    .getRequirement(componentIdLower, requirementIdToGet, modifier, true);
+            if (actionResponse.isRight()) {
+                LOGGER.error("failed to get requirements");
+                return buildErrorResponse(actionResponse.right().value());
+            }
+            Object result = RepresentationUtils.toFilteredRepresentation(actionResponse.left().value());
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get requirements");
+            LOGGER.error("get requirements failed with exception", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+    }
+
+    private Response delete (String requirementId, String componentId, HttpServletRequest
+                                        request, String userId){
+
+        ServletContext context = request.getSession().getServletContext();
+        String url = request.getMethod() + " " + request.getRequestURI();
+
+        User modifier = new User();
+        modifier.setUserId(userId);
+        LOGGER.debug("Start delete request of {} with modifier id {}", url, userId);
+
+        try {
+            String componentIdLower = componentId.toLowerCase();
+            RequirementBusinessLogic businessLogic = getRequirementBL(context);
+
+            Either<RequirementDefinition, ResponseFormat> actionResponse = businessLogic
+                    .deleteRequirement(componentIdLower, requirementId, modifier, true);
+            if (actionResponse.isRight()) {
+                LOGGER.error("failed to delete requirements");
+                return buildErrorResponse(actionResponse.right().value());
+            }
+            Object result = RepresentationUtils.toRepresentation(actionResponse.left().value());
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete requirements");
+            LOGGER.error("Delete requirements failed with an error", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+    }
+
+    private Either<List<RequirementDefinition>, ResponseFormat> getMappedRequirementData(String inputJson, User user,
+                                                                 ComponentTypeEnum componentTypeEnum){
+        Either<UiComponentDataTransfer, ResponseFormat> mappedData = getComponentsUtils()
+                .convertJsonToObjectUsingObjectMapper(inputJson, user, UiComponentDataTransfer.class,
+                        AuditingActionEnum.CREATE_RESOURCE, componentTypeEnum);
+        Optional<List<RequirementDefinition>> requirementDefinitionList = mappedData.left().value()
+                .getRequirements().values().stream().findFirst();
+        return requirementDefinitionList.<Either<List<RequirementDefinition>, ResponseFormat>>
+                map(Either::left).orElseGet(() -> Either.right(getComponentsUtils()
+                .getResponseFormat(ActionStatus.GENERAL_ERROR)));
+    }
+}
index 00b04a4..459629f 100644 (file)
@@ -26,28 +26,44 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
+import org.apache.commons.collections4.ListUtils;
+import org.openecomp.sdc.be.components.impl.CapabilitiesBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic;
 import org.openecomp.sdc.be.components.impl.InterfaceOperationBusinessLogic;
 import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
+import org.openecomp.sdc.be.components.impl.RelationshipTypeBusinessLogic;
 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.datamodel.api.HighestFilterEnum;
+import org.openecomp.sdc.be.datatypes.components.ResourceMetadataDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
+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.RelationshipTypeDefinition;
 import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.common.datastructure.Wrapper;
 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.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+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.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
+
 
 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
 @Path("/v1/catalog")
@@ -56,6 +72,7 @@ import java.util.Map;
 public class TypesFetchServlet extends AbstractValidationsServlet {
 
     private static final Logger log = Logger.getLogger(TypesFetchServlet.class);
+    private static final String FAILED_TO_GET_ALL_NON_ABSTRACT = "failed to get all non abstract {}";
 
     @GET
     @Path("dataTypes")
@@ -154,4 +171,188 @@ public class TypesFetchServlet extends AbstractValidationsServlet {
             return buildErrorResponse(responseFormat);
         }
     }
+    @GET
+    @Path("capabilityTypes")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(value = "Get capability types", httpMethod = "GET", notes = "Returns capability types", response =
+            Response.class)
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "capabilityTypes"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+            @ApiResponse(code = 404, message = "Capability types not found")})
+    public Response getAllCapabilityTypesServlet(@Context final HttpServletRequest request, @HeaderParam(value =
+            Constants.USER_ID_HEADER) String userId) {
+
+        Wrapper<Response> responseWrapper = new Wrapper<>();
+        Wrapper<User> userWrapper = new Wrapper<>();
+        ServletContext context = request.getSession().getServletContext();
+
+        try {
+            init();
+            validateUserExist(responseWrapper, userWrapper, userId);
+
+            if (responseWrapper.isEmpty()) {
+                String url = request.getMethod() + " " + request.getRequestURI();
+                log.debug("Start handle request of {} | modifier id is {}", url, userId);
+
+                CapabilitiesBusinessLogic businessLogic = getCapabilitiesBL(context);
+                Either<Map<String, CapabilityTypeDefinition>, ResponseFormat> allDataTypes =
+                        businessLogic.getAllCapabilityTypes();
+
+                if (allDataTypes.isRight()) {
+                    log.info("Failed to get all capability types. Reason - {}", allDataTypes.right().value());
+                    Response errorResponse = buildErrorResponse(allDataTypes.right().value());
+                    responseWrapper.setInnerElement(errorResponse);
+
+                } else {
+
+                    Map<String, CapabilityTypeDefinition> dataTypes = allDataTypes.left().value();
+                    String dataTypeJson = gson.toJson(dataTypes);
+                    Response okResponse =
+                            buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), dataTypeJson);
+                    responseWrapper.setInnerElement(okResponse);
+
+                }
+            }
+
+            return responseWrapper.getInnerElement();
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Capability Types");
+            log.debug("get all capability types failed with exception", e);
+            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+            return buildErrorResponse(responseFormat);
+        }
+    }
+
+    @GET
+    @Path("relationshipTypes")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(value = "Get relationship types", httpMethod = "GET", notes = "Returns relationship types", response =
+            Response.class)
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "relationshipTypes"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+            @ApiResponse(code = 404, message = "Relationship types not found")})
+    public Response getAllRelationshipTypesServlet(@Context final HttpServletRequest request, @HeaderParam(value =
+            Constants.USER_ID_HEADER) String userId) {
+
+        Wrapper<Response> responseWrapper = new Wrapper<>();
+        Wrapper<User> userWrapper = new Wrapper<>();
+        ServletContext context = request.getSession().getServletContext();
+
+        try {
+            init();
+            validateUserExist(responseWrapper, userWrapper, userId);
+
+            if (responseWrapper.isEmpty()) {
+                String url = request.getMethod() + " " + request.getRequestURI();
+                log.debug("Start handle request of {} | modifier id is {}", url, userId);
+
+                RelationshipTypeBusinessLogic businessLogic = getRelationshipTypeBL(context);
+                Either<Map<String, RelationshipTypeDefinition>, ResponseFormat> allDataTypes =
+                        businessLogic.getAllRelationshipTypes();
+
+                if (allDataTypes.isRight()) {
+                    log.info("Failed to get all relationship types. Reason - {}", allDataTypes.right().value());
+                    Response errorResponse = buildErrorResponse(allDataTypes.right().value());
+                    responseWrapper.setInnerElement(errorResponse);
+
+                } else {
+
+                    Map<String, RelationshipTypeDefinition> dataTypes = allDataTypes.left().value();
+                    String dataTypeJson = gson.toJson(dataTypes);
+                    Response okResponse =
+                            buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), dataTypeJson);
+                    responseWrapper.setInnerElement(okResponse);
+
+                }
+            }
+
+            return responseWrapper.getInnerElement();
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Relationship Types");
+            log.debug("get all relationship types failed with exception", e);
+            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+            return buildErrorResponse(responseFormat);
+        }
+    }
+
+    @GET
+    @Path("nodeTypes")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(value = "Get node types", httpMethod = "GET", notes = "Returns node types", response = Response.class)
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "nodeTypes"), @ApiResponse(code = 403, message =
+            "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+            @ApiResponse(code = 404, message = "Node types not found")})
+    public Response getAllNodeTypesServlet(@Context final HttpServletRequest request, @HeaderParam(value =
+            Constants.USER_ID_HEADER) String userId) {
+
+        Wrapper<Response> responseWrapper = new Wrapper<>();
+        Wrapper<User> userWrapper = new Wrapper<>();
+        ServletContext context = request.getSession().getServletContext();
+        Either<Map<String, Component>, Response> response;
+        Map<String, Component> componentMap;
+
+        try {
+            init();
+            validateUserExist(responseWrapper, userWrapper, userId);
+
+            if (responseWrapper.isEmpty()) {
+                String url = request.getMethod() + " " + request.getRequestURI();
+                log.debug("Start handle request of {} | modifier id is {}", url, userId);
+
+                ComponentBusinessLogic resourceBL = getComponentBL(ComponentTypeEnum.RESOURCE, context);
+                response = getComponent(resourceBL, true, userId);
+                if (response.isRight()) {
+                    return response.right().value();
+                }
+                componentMap = new HashMap<>(response.left().value());
+
+                response = getComponent(resourceBL, false, userId);
+                if (response.isRight()) {
+                    return response.right().value();
+                }
+                componentMap.putAll(response.left().value());
+
+                String nodeTypesJson = gson.toJson(componentMap);
+                Response okResponse =
+                        buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), nodeTypesJson);
+                responseWrapper.setInnerElement(okResponse);
+            }
+
+            return responseWrapper.getInnerElement();
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Node Types");
+            log.debug("get all node types failed with exception", e);
+            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR);
+            return buildErrorResponse(responseFormat);
+        }
+    }
+
+    private Either<Map<String, Component>, Response> getComponent(ComponentBusinessLogic resourceBL, boolean isAbstract,
+                                                                  String userId) {
+        Either<List<Component>, ResponseFormat> actionResponse;
+        List<Component> componentList;
+
+        actionResponse =
+                resourceBL.getLatestVersionNotAbstractComponentsMetadata(isAbstract, HighestFilterEnum.HIGHEST_ONLY
+                        , ComponentTypeEnum.RESOURCE, null, userId);
+        if (actionResponse.isRight()) {
+            log.debug(FAILED_TO_GET_ALL_NON_ABSTRACT, ComponentTypeEnum.RESOURCE.getValue());
+            return Either.right(buildErrorResponse(actionResponse.right().value()));
+        }
+
+        componentList = actionResponse.left().value();
+
+        return Either.left(ListUtils.emptyIfNull(componentList).stream()
+                .filter(component -> ((ResourceMetadataDataDefinition) component
+                        .getComponentMetadataDefinition().getMetadataDataDefinition()).getToscaResourceName() != null)
+                .collect(Collectors.toMap(
+                        component -> ((ResourceMetadataDataDefinition) component
+                                .getComponentMetadataDefinition().getMetadataDataDefinition()).getToscaResourceName(),
+                        component -> component, (component1, component2) -> component1)));
+    }
 }
index a09e34f..8ecda2c 100644 (file)
@@ -34,6 +34,7 @@ import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.GroupTypeDefinition;
 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
+import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
 import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.normatives.ToscaTypeMetadata;
 import org.openecomp.sdc.common.api.Constants;
@@ -72,15 +73,18 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
     private final DataTypeImportManager dataTypeImportManager;
     private final GroupTypeImportManager groupTypeImportManager;
     private final PolicyTypeImportManager policyTypeImportManager;
+    private final RelationshipTypeImportManager relationshipTypeImportManager;
 
     public TypesUploadServlet(CapabilityTypeImportManager capabilityTypeImportManager, InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager, CategoriesImportManager categoriesImportManager, DataTypeImportManager dataTypeImportManager,
-                              GroupTypeImportManager groupTypeImportManager, PolicyTypeImportManager policyTypeImportManager) {
+                              GroupTypeImportManager groupTypeImportManager, PolicyTypeImportManager policyTypeImportManager,
+                              RelationshipTypeImportManager relationshipTypeImportManager) {
         this.capabilityTypeImportManager = capabilityTypeImportManager;
         this.interfaceLifecycleTypeImportManager = interfaceLifecycleTypeImportManager;
         this.categoriesImportManager = categoriesImportManager;
         this.dataTypeImportManager = dataTypeImportManager;
         this.groupTypeImportManager = groupTypeImportManager;
         this.policyTypeImportManager = policyTypeImportManager;
+        this.relationshipTypeImportManager = relationshipTypeImportManager;
     }
 
     @POST
@@ -93,6 +97,21 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
         return uploadElementTypeServletLogic(createElementsMethod, file, request, creator, NodeTypeEnum.CapabilityType.name());
     }
 
+    @POST
+    @Path("/relationship")
+    @ApiOperation(value = "Create Relationship Type from yaml", httpMethod = "POST",
+            notes = "Returns created Relationship Type", response = Response.class)
+    @ApiResponses(value = {@ApiResponse(code = 201, message = "Relationship Type created"),
+            @ApiResponse(code = 403, message = "Restricted operation"),
+            @ApiResponse(code = 400, message = "Invalid content / Missing content"),
+            @ApiResponse(code = 409, message = "Relationship Type already exist")})
+    public Response uploadRelationshipType(@ApiParam("FileInputStream") @FormDataParam("relationshipTypeZip") File file,
+                                           @Context final HttpServletRequest request,
+                                           @HeaderParam("USER_ID") String creator) {
+        return uploadElementTypeServletLogic(this::createRelationshipTypes, file, request, creator,
+                NodeTypeEnum.RelationshipType.getName());
+    }
+
     @POST
     @Path("/interfaceLifecycle")
     @ApiOperation(value = "Create Interface Lyfecycle Type from yaml", httpMethod = "POST", notes = "Returns created Interface Lifecycle Type", response = Response.class)
@@ -299,6 +318,13 @@ public class TypesUploadServlet extends AbstractValidationsServlet {
             }
         }
     }
-
+    // relationship types
+    private void createRelationshipTypes(Wrapper<Response> responseWrapper, String relationshipTypesYml) {
+        final Supplier<Either<List<ImmutablePair<RelationshipTypeDefinition, Boolean>>, ResponseFormat>>
+                generateElementTypeFromYml =
+                () -> relationshipTypeImportManager.createRelationshipTypes(relationshipTypesYml);
+        buildStatusForElementTypeCreate(responseWrapper, generateElementTypeFromYml,
+                ActionStatus.RELATIONSHIP_TYPE_ALREADY_EXIST, NodeTypeEnum.RelationshipType.name());
+    }
 
 }
index 04119fe..bd797c9 100644 (file)
@@ -258,22 +258,22 @@ public class CapabilityRequirementConverter {
 
     private Either<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsCapabilities(Map<String, Component> componentsCache, Component component, Map<String, List<CapabilityDefinition>> capabilities) {
 
-        Map<String, String[]> toscaRequirements = new HashMap<>();
+        Map<String, String[]> toscaCapabilities = new HashMap<>();
         Either<Map<String, String[]>, ToscaError> result = null;
         for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) {
             Optional<CapabilityDefinition> failedToAddRequirement = entry.getValue()
                     .stream()
-                    .filter(c->!addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""), c.getPreviousName(), c.getOwnerId(), c.getPath()))
+                    .filter(c->!addEntry(componentsCache, toscaCapabilities, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""), c.getPreviousName(), c.getOwnerId(), c.getPath()))
                     .findAny();
             if(failedToAddRequirement.isPresent()){
-                logger.debug("Failed to convert capalility {} for substitution mappings section of a tosca template of the component {}. ",
+                logger.debug("Failed to convert capability {} for substitution mappings section of a tosca template of the component {}. ",
                         failedToAddRequirement.get().getName(), component.getName());
                 result = Either.right(ToscaError.NODE_TYPE_CAPABILITY_ERROR);
             }
-            logger.debug("Finish convert capalilities for the component {}. ", component.getName());
+            logger.debug("Finish convert capabilities for the component {}. ", component.getName());
         }
         if(result == null){
-            result = Either.left(toscaRequirements);
+            result = Either.left(toscaCapabilities);
         }
         return result;
     }
@@ -284,7 +284,7 @@ public class CapabilityRequirementConverter {
             return false;
         }
         logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(), component.getUniqueId());
-        if (entry.getSourceName() != null) {
+        if (StringUtils.isNotEmpty(entry.getSourceName())) {
             addEntry(capReqMap, component, path, entry);
         }
         logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(), component.getName());
@@ -318,14 +318,15 @@ public class CapabilityRequirementConverter {
             }
         }
 
-        Optional<ComponentInstance> ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
+        Optional<ComponentInstance> ci =
+                component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
         if(!ci.isPresent()){
             logger.debug("Failed to find ci in the path is {} component {}", path, component.getUniqueId());
 
             Collections.reverse(path);
 
             logger.debug("try to reverse path {} component {}", path, component.getUniqueId());
-            ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
+            ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
         }
         if(ci.isPresent()){
             prefix = buildCapReqNamePrefix(ci.get().getNormalizedName());
@@ -352,10 +353,10 @@ public class CapabilityRequirementConverter {
 
     private void addEntry(Map<String, String[]> toscaRequirements, Component component, List<String> capPath, SubstitutionEntry entry) {
         Optional<ComponentInstance> findFirst = component.safeGetComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(Iterables.getLast(capPath))).findFirst();
-        if (findFirst.isPresent()) {
-            entry.setOwner(findFirst.get().getNormalizedName());
+        findFirst.ifPresent(componentInstance -> entry.setOwner(componentInstance.getName()));
+        if (StringUtils.isNotEmpty(entry.getOwner()) && StringUtils.isNotEmpty(entry.getSourceName())) {
+            toscaRequirements.put(entry.getFullName(), new String[] { entry.getOwner(), entry.getSourceName() });
         }
-        toscaRequirements.put(entry.getFullName(), new String[] { entry.getOwner(), entry.getSourceName() });
     }
 
     public Either<String, Boolean> buildSubstitutedName(Map<String, Component> componentsCache, String name, String previousName, List<String> path, String ownerId, ComponentInstance instance) {
@@ -469,31 +470,9 @@ public class CapabilityRequirementConverter {
         return buildCapReqNamePerOwnerByPath(componentsCache, component, c.getName(), c.getPreviousName(), c.getPath());
     }
 
-    private void convertProxyCapability(Map<String, ToscaCapability> toscaCapabilities, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes, String capabilityName) {
-        ToscaCapability toscaCapability = new ToscaCapability();
-        toscaCapability.setDescription(c.getDescription());
-        toscaCapability.setType(c.getType());
-
-        List<Object> occurrences = new ArrayList<>();
-        occurrences.add(Integer.valueOf(c.getMinOccurrences()));
-        if (c.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
-            occurrences.add(c.getMaxOccurrences());
-        } else {
-            occurrences.add(Integer.valueOf(c.getMaxOccurrences()));
-        }
-        toscaCapability.setOccurrences(occurrences);
-
-        toscaCapability.setValid_source_types(c.getValidSourceTypes());
-        List<ComponentInstanceProperty> properties = c.getProperties();
-        if (isNotEmpty(properties)) {
-            Map<String, ToscaProperty> toscaProperties = new HashMap<>();
-            for (PropertyDefinition property : properties) {
-                ToscaProperty toscaProperty = PropertyConvertor.getInstance().convertProperty(dataTypes, property, PropertyConvertor.PropertyType.CAPABILITY);
-                toscaProperties.put(property.getName(), toscaProperty);
-            }
-            toscaCapability.setProperties(toscaProperties);
-        }
-        toscaCapabilities.put(capabilityName, toscaCapability);
+    private void convertProxyCapability(Map<String, ToscaCapability> toscaCapabilities, CapabilityDefinition c,
+                                        Map<String, DataTypeDefinition> dataTypes, String capabilityName) {
+        createToscaCapability(toscaCapabilities, c, dataTypes, capabilityName);
     }
 
     private void convertCapability(Map<String, Component> componentsCache, Component component, Map<String, ToscaCapability> toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map<String, DataTypeDefinition> dataTypes , String capabilityName) {
@@ -502,6 +481,11 @@ public class CapabilityRequirementConverter {
             name = buildCapNamePerOwnerByPath(componentsCache, c, component);
         }
         logger.debug("The capability {} belongs to resource {} ", name, component.getUniqueId());
+        createToscaCapability(toscaCapabilities, c, dataTypes, name);
+    }
+
+    private void createToscaCapability(Map<String, ToscaCapability> toscaCapabilities, CapabilityDefinition c,
+                                       Map<String, DataTypeDefinition> dataTypes, String name) {
         ToscaCapability toscaCapability = new ToscaCapability();
         toscaCapability.setDescription(c.getDescription());
         toscaCapability.setType(c.getType());
@@ -529,6 +513,9 @@ public class CapabilityRequirementConverter {
     }
 
     private String buildCapReqNamePerOwnerByPath(Map<String, Component> componentsCache, Component component, String name, String previousName, List<String> path) {
+        if (CollectionUtils.isEmpty(path)) {
+            return name;
+        }
         String ownerId = path.get(path.size() - 1);
         String prefix;
         if(CollectionUtils.isNotEmpty(component.getGroups())) {
@@ -541,14 +528,14 @@ public class CapabilityRequirementConverter {
                 return name;
             }
         }
-        Optional<ComponentInstance> ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
+        Optional<ComponentInstance> ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
         if(!ci.isPresent()){
             logger.debug("Failed to find ci in the path is {} component {}", path, component.getUniqueId());
 
             Collections.reverse(path);
 
             logger.debug("try to reverse path {} component {}", path, component.getUniqueId());
-            ci = component.getComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
+            ci = component.safeGetComponentInstances().stream().filter(c->c.getUniqueId().equals(Iterables.getLast(path))).findFirst();
         }
         if(ci.isPresent()){
             prefix = buildCapReqNamePrefix(ci.get().getNormalizedName());
index 4506fa1..f446f21 100644 (file)
@@ -15,18 +15,22 @@ tosca.relationships.Root:
     Configure:
       type: tosca.interfaces.relationship.Configure        
 
+tosca.relationships.ConnectsTo:
+  derived_from: tosca.relationships.Root
+  description: This type represents a network connection relationship between two nodes.
+  valid_target_types:
+  - tosca.capabilities.Endpoint
+  properties:
+    credential:
+      type: tosca.datatypes.Credential
+      required: false
+
 tosca.relationships.RoutesTo:
   derived_from: tosca.relationships.ConnectsTo
   description: This type represents an intentional network routing between two Endpoints in different networks.
   valid_target_types:
   - tosca.capabilities.Endpoint
 
-tosca.relationships.network.LinksTo:
-  derived_from: tosca.relationships.DependsOn
-  description: This relationship type represents an association relationship between Port and Network node types.
-  valid_target_types:
-  - tosca.capabilities.network.Linkable
-
 tosca.relationships.AttachesTo:
   derived_from: tosca.relationships.Root
   description: This type represents an attachment relationship between two nodes. For example, an AttachesTo relationship type would be used for attaching a storage node to a Compute node.
@@ -52,12 +56,6 @@ tosca.relationships.AttachesTo:
         orchestrator.'
       type: string
 
-tosca.relationships.network.BindsTo:
-  derived_from: tosca.relationships.DependsOn
-  description: This type represents a network association relationship between Port and Compute node types.
-  valid_target_types:
-  - tosca.capabilities.network.Bindable
-
 tosca.relationships.HostedOn:
   derived_from: tosca.relationships.Root
   description: This type represents a hosting relationship between two nodes.
@@ -70,15 +68,27 @@ tosca.relationships.DependsOn:
   valid_target_types:
   - tosca.capabilities.Node
 
-tosca.relationships.ConnectsTo:
-  derived_from: tosca.relationships.Root
-  description: This type represents a network connection relationship between two nodes.
+tosca.relationships.network.LinksTo:
+  derived_from: tosca.relationships.DependsOn
+  description: This relationship type represents an association relationship between Port and Network node types.
   valid_target_types:
-  - tosca.capabilities.Endpoint
-  properties:
-    credential:
-      type: tosca.datatypes.Credential
-      required: false
+  - tosca.capabilities.network.Linkable
+
+tosca.relationships.network.BindsTo:
+  derived_from: tosca.relationships.DependsOn
+  description: This type represents a network association relationship between Port and Compute node types.
+  valid_target_types:
+  - tosca.capabilities.network.Bindable
+
+org.openecomp.relationships.AttachesTo:
+    derived_from: tosca.relationships.AttachesTo
+    description: This type represents an attachment relationship
+    properties:
+      location:
+        description: The relative location (e.g., path on the file system), which provides the root location to address an attached node.
+        type: string
+        status: SUPPORTED
+        required: false
 
 org.openecomp.relationships.VolumeAttachesTo:
   derived_from: org.openecomp.relationships.AttachesTo
@@ -100,15 +110,6 @@ org.openecomp.relationships.VolumeAttachesTo:
       type: string
       status: SUPPORTED
 
-org.openecomp.relationships.AttachesTo:
-    derived_from: tosca.relationships.AttachesTo
-    description: This type represents an attachment relationship
-    properties:
-      location:
-        description: The relative location (e.g., path on the file system), which provides the root location to address an attached node.
-        type: string
-        status: SUPPORTED
-        required: false
 org.openecomp.relationships.ForwardsTo:
   derived_from: tosca.relationships.Root
   valid_target_types: [org.openecomp.capabilities.Forwarder]
index 8a83290..19ffc17 100644 (file)
@@ -8,6 +8,7 @@ from importNormativeElements import *
 from importNormativeTypes import importNormativeTypes
 from importHeatTypes import importHeatTypes
 from importNormativeCapabilities import importNormativeCapabilities
+from importNormativeRelationships import importNormativeRelationships
 from importCategoryTypes import importCategories
 from importNormativeInterfaceLifecycleTypes import importNormativeInterfaceLifecycleType
 from importDataTypes import importDataTypes
@@ -116,6 +117,9 @@ def main(argv):
     fileLocation = baseFileLocation + "capability-types/"
     importNormativeCapabilities(scheme, beHost, bePort, adminUser, False, fileLocation)
 
+    fileLocation = baseFileLocation + "relationship-types/"
+    importNormativeRelationships(scheme, beHost, bePort, adminUser, False, fileLocation)
+
     fileLocation = baseFileLocation + "interface-lifecycle-types/"
     importNormativeInterfaceLifecycleType(scheme, beHost, bePort, adminUser, False, fileLocation)
 
diff --git a/catalog-be/src/main/resources/scripts/import/tosca/importNormativeRelationships.py b/catalog-be/src/main/resources/scripts/import/tosca/importNormativeRelationships.py
new file mode 100644 (file)
index 0000000..a86e520
--- /dev/null
@@ -0,0 +1,83 @@
+import pycurl
+import sys, getopt
+from StringIO import StringIO
+import json
+import copy
+from importNormativeElements import createNormativeElement
+from importCommon import *
+import importCommon 
+
+#################################################################################################################################################################################################
+#                                                                                                                                                                                                                                                                                                                                                                                      #
+# Import normative relationships
+#                                                                                                                                                      #
+#                                                                                                                                                                                                                                                                                                                                                                                              #
+# activation :                                                                                                                                                                                                                                                                                                                                                                 #
+#       python importNormativeRelationships.py [-s <scheme> | --scheme=<scheme> ] [-i <be host> | --ip=<be host>] [-p
+#  <be port> | --port=<be port> ] [-f <input file> | --ifile=<input file> ]    #
+#                                                                                                                                                                                                                                                                                                                                                                                              #
+# shortest activation (be host = localhost, be port = 8080):                                                                                                                                                                                                                                                                   #
+#              python importNormativeRelationships.py [-f <input file> | --ifile=<input file> ]
+#                                                                                                                                                      #
+#                                                                                                                                                                                                                                                                                                                                                                                      #
+#################################################################################################################################################################################################
+
+       
+def usage():
+       print sys.argv[0], '[optional -s <scheme> | --scheme=<scheme>, default http] [-i <be host> | --ip=<be host>] [-p <be port> | --port=<be port> ] [-u <user userId> | --user=<user userId> ]'
+
+
+def importNormativeRelationships(scheme, beHost, bePort, adminUser, exitOnSuccess, fileDir):
+       result = createNormativeElement(scheme, beHost, bePort, adminUser, fileDir, "/sdc2/rest/v1/catalog/uploadType/relationship", "relationshipTypes", "relationshipTypeZip")
+       
+       print_frame_line()
+        print_name_and_return_code(result[0], result[1])
+        print_frame_line()
+
+        if ( result[1] == None or result[1] not in [200, 201, 409] ):
+                importCommon.error_and_exit(1, None)
+        else:
+               if (exitOnSuccess == True):
+                       importCommon.error_and_exit(0, None)
+
+
+def main(argv):
+       print 'Number of arguments:', len(sys.argv), 'arguments.'
+
+       beHost = 'localhost' 
+       bePort = '8080'
+       adminUser = 'jh0003'
+       scheme = 'http'
+
+       try:
+               opts, args = getopt.getopt(argv,"i:p:u:h:s:",["ip=","port=","user=","scheme="])
+       except getopt.GetoptError:
+               usage()
+               importCommon.error_and_exit(2, 'Invalid input')
+                
+       for opt, arg in opts:
+       #print opt, arg
+               if opt == '-h':
+                       usage()                        
+                       sys.exit(3)
+               elif opt in ("-i", "--ip"):
+                       beHost = arg
+               elif opt in ("-p", "--port"):
+                       bePort = arg
+               elif opt in ("-u", "--user"):
+                       adminUser = arg
+               elif opt in ("-s", "--scheme"):
+                       scheme = arg
+
+       print 'scheme =',scheme,', be host =',beHost,', be port =', bePort,', user =', adminUser
+       
+       if ( beHost == None ):
+               usage()
+               sys.exit(3)
+
+       importNormativeRelationships(scheme, beHost, bePort, adminUser, True, "../../../import/tosca/relationship-types/")
+
+
+if __name__ == "__main__":
+        main(sys.argv[1:])
+
index ef1fe4d..30b5a54 100644 (file)
@@ -12,6 +12,7 @@ from importNfvTypes import importNfvTypes
 from importOnapTypes import importOnapTypes
 from importSolTypes import importSolTypes
 from importNormativeCapabilities import importNormativeCapabilities
+from importNormativeRelationships import importNormativeRelationships
 from importCategoryTypes import importCategories
 from importNormativeInterfaceLifecycleTypes import importNormativeInterfaceLifecycleType
 from importDataTypes import importDataTypes
@@ -111,12 +112,15 @@ def main(argv):
 
        print 'sleep until data type cache is updated'
        time.sleep( 70 )
-       
+
        fileLocation = baseFileLocation + "capability-types/"
        importNormativeCapabilities(scheme, beHost, bePort, adminUser, False, fileLocation)
+       
+       fileLocation = baseFileLocation + "relationship-types/"
+       importNormativeRelationships(scheme, beHost, bePort, adminUser, False, fileLocation)
 
        fileLocation = baseFileLocation + "interface-lifecycle-types/"
-       importNormativeInterfaceLifecycleType(scheme, beHost, bePort, adminUser, False, fileLocation)   
+       importNormativeInterfaceLifecycleType(scheme, beHost, bePort, adminUser, False, fileLocation)
 
        fileLocation = baseFileLocation + "categories/"
        importCategories(scheme, beHost, bePort, adminUser, False, fileLocation)
index bbeb3d6..36a5d11 100644 (file)
@@ -10,6 +10,7 @@ from importDataTypes import importDataTypes
 from importPolicyTypes import importPolicyTypes
 from importGroupTypes import importGroupTypes
 from importNormativeCapabilities import importNormativeCapabilities
+from importNormativeRelationships import importNormativeRelationships
 from importNormativeInterfaceLifecycleTypes import importNormativeInterfaceLifecycleType
 from importAnnotationTypes import import_annotation_types
 
@@ -96,6 +97,9 @@ def main(argv):
     fileLocation = baseFileLocation + "categories/"
     importCategories(scheme, beHost, bePort, adminUser, False, fileLocation)
 
+    fileLocation = baseFileLocation + "relationship-types/"
+    importNormativeRelationships(scheme, beHost, bePort, adminUser, False, fileLocation)
+
     fileLocation = baseFileLocation + "data-types/"
     importDataTypes(scheme, beHost, bePort, adminUser, False, fileLocation)
 
index bebba6c..c6d217f 100644 (file)
@@ -10,6 +10,7 @@ from importDataTypes import importDataTypes
 from importPolicyTypes import importPolicyTypes
 from importGroupTypes import importGroupTypes
 from importNormativeCapabilities import importNormativeCapabilities
+from importNormativeRelationships import importNormativeRelationships
 from importNormativeInterfaceLifecycleTypes import importNormativeInterfaceLifecycleType
 from upgradeNfvTypes import upgradeNfvTypesPerConfigFile
 from upgradeONAPTypes import upgradeOnapTypesPerConfigFile
@@ -101,6 +102,9 @@ def main(argv):
        fileLocation = baseFileLocation + "categories/"
        importCategories(scheme, beHost, bePort, adminUser, False, fileLocation)
 
+       fileLocation = baseFileLocation + "relationship-types/"
+        importNormativeRelationships(scheme, beHost, bePort, adminUser, False, fileLocation)
+
        fileLocation = baseFileLocation + "data-types/"
        importDataTypes(scheme, beHost, bePort, adminUser, False, fileLocation)
 
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CapabilitiesBusinessLogicTest.java
new file mode 100644 (file)
index 0000000..393ef58
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * 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.impl;
+
+import fj.data.Either;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.auditing.impl.AuditingManager;
+import org.openecomp.sdc.be.components.validation.CapabilitiesValidation;
+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.dao.titan.TitanOperationStatus;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
+import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.LifecycleStateEnum;
+import org.openecomp.sdc.be.model.RelationshipInfo;
+import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
+import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.jsontitan.operations.CapabilitiesOperation;
+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.GraphLockOperation;
+import org.openecomp.sdc.be.user.Role;
+import org.openecomp.sdc.be.user.UserBusinessLogic;
+import org.openecomp.sdc.common.api.ConfigurationSource;
+import org.openecomp.sdc.common.impl.ExternalConfiguration;
+import org.openecomp.sdc.common.impl.FSConfigurationSource;
+import org.openecomp.sdc.exception.ResponseFormat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyCollection;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+public class CapabilitiesBusinessLogicTest {
+    private final String componentId = "resourceId1";
+    private final String capabilityId = "uniqueId1";
+
+    private final TitanDao mockTitanDao = Mockito.mock(TitanDao.class);
+    private final UserBusinessLogic mockUserAdmin = Mockito.mock(UserBusinessLogic.class);
+    private final ToscaOperationFacade toscaOperationFacade = Mockito.mock(ToscaOperationFacade.class);
+    private final UserValidations userValidations = Mockito.mock(UserValidations.class);
+    private final CapabilitiesOperation capabilitiesOperation = Mockito.mock(CapabilitiesOperation.class);
+    private final CapabilitiesValidation capabilitiesValidation = Mockito.mock(CapabilitiesValidation.class);
+
+    private final GraphLockOperation graphLockOperation = Mockito.mock(GraphLockOperation.class);
+    private User user = null;
+
+    @InjectMocks
+    private CapabilitiesBusinessLogic capabilitiesBusinessLogicMock = new CapabilitiesBusinessLogic();
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        ExternalConfiguration.setAppName("catalog-be");
+
+        // init Configuration
+        String appConfigDir = "src/test/resources/config/catalog-be";
+        ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
+        ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
+
+        ComponentsUtils componentsUtils = new ComponentsUtils(Mockito.mock(AuditingManager.class));
+
+        // User data and management
+        user = new User();
+        user.setUserId("jh0003");
+        user.setFirstName("Jimmi");
+        user.setLastName("Hendrix");
+        user.setRole(Role.ADMIN.name());
+
+        Either<User, ActionStatus> eitherGetUser = Either.left(user);
+        when(mockUserAdmin.getUser("jh0003", false)).thenReturn(eitherGetUser);
+        when(graphLockOperation.lockComponent(Mockito.anyString(), eq(NodeTypeEnum.Resource)))
+                .thenReturn(StorageOperationStatus.OK);
+
+        //CapabilityOperation
+        when(capabilitiesValidation.validateCapabilities(anyCollection(), anyObject(), anyBoolean())
+        ).thenReturn(Either.left(true));
+        when(capabilitiesOperation.addCapabilities(anyString(), anyObject()))
+                .thenReturn(Either.left(createMockCapabilityListToReturn(
+                        createCapability("capName", "capDesc", "capType", "source1",
+                "0", "10"))));
+
+        when(capabilitiesOperation.updateCapabilities(anyString(), anyObject()))
+                .thenReturn(Either.left(createMockCapabilityListToReturn(
+                        createCapability("capName", "capDesc", "capType", "source1",
+                "0", "10"))));
+        when(capabilitiesOperation.deleteCapabilities( anyObject(), anyString()))
+                .thenReturn(StorageOperationStatus.OK);
+        when(mockTitanDao.commit()).thenReturn(TitanOperationStatus.OK);
+
+        capabilitiesBusinessLogicMock = new CapabilitiesBusinessLogic();
+        capabilitiesBusinessLogicMock.setComponentsUtils(componentsUtils);
+        capabilitiesBusinessLogicMock.setUserAdmin(mockUserAdmin);
+        capabilitiesBusinessLogicMock.setGraphLockOperation(graphLockOperation);
+        capabilitiesBusinessLogicMock.setTitanGenericDao(mockTitanDao);
+        capabilitiesBusinessLogicMock.setToscaOperationFacade(toscaOperationFacade);
+        capabilitiesBusinessLogicMock.setUserValidations(userValidations);
+        capabilitiesBusinessLogicMock.setCapabilitiesOperation(capabilitiesOperation);
+        capabilitiesBusinessLogicMock.setCapabilitiesValidation(capabilitiesValidation);
+    }
+
+    @Test
+    public void shouldPassCreateCapabilitiesFirstTimeInComponentForHappyScenario(){
+        List<CapabilityDefinition> capabilityDefinitions = createMockCapabilityListToReturn(
+                createCapability("capName", "capDesc", "capType", "source1",
+                "0", "10"));
+        Resource resource = createComponent(false);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        Either<List<CapabilityDefinition>, ResponseFormat> capabilities = capabilitiesBusinessLogicMock
+                .createCapabilities(componentId, capabilityDefinitions, user,
+                         "createCapabilities", true);
+        Assert.assertTrue(capabilities.isLeft());
+        Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition ->
+                capabilityDefinition.getName().equals("capName")));
+    }
+
+    @Test
+    public void shouldPassCreateCapabilitiesForHappyScenario(){
+        List<CapabilityDefinition> capabilityDefinitions = createMockCapabilityListToReturn(
+                createCapability("capName2", "capDesc", "capType", "source1",
+                "0", "10"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        Either<List<CapabilityDefinition>, ResponseFormat> capabilities = capabilitiesBusinessLogicMock
+                .createCapabilities(componentId, capabilityDefinitions, user,
+                        "createCapabilities", false);
+
+        Assert.assertTrue(capabilities.isLeft());
+        Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition ->
+                capabilityDefinition.getName().equals("capName2")));
+    }
+
+    @Test
+    public void shouldFailCreateCapabilitiesWhenOperationFailedInTitan(){
+        List<CapabilityDefinition> capabilityDefinitions = createMockCapabilityListToReturn(
+                createCapability("capName2", "capDesc", "capType", "source1",
+                "0", "10"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(capabilitiesOperation.addCapabilities(anyString(), anyObject()))
+                .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR));
+        when(capabilitiesOperation.updateCapabilities(anyString(), anyObject()))
+                .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR));
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        Either<List<CapabilityDefinition>, ResponseFormat> capabilities = capabilitiesBusinessLogicMock
+                .createCapabilities(componentId, capabilityDefinitions, user,
+                         "createCapabilities", true);
+
+        Assert.assertTrue(capabilities.isRight());
+    }
+    @Test
+    public void shouldPassUpdateCapabilitiesForHappyScenario(){
+
+        List<CapabilityDefinition> capabilityDefinitions = createMockCapabilityListToReturn(
+                createCapability("capName", "capDesc updated", "capType", "source1",
+                "6", "11"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<List<CapabilityDefinition>, ResponseFormat> capabilities = capabilitiesBusinessLogicMock
+                .updateCapabilities(componentId, capabilityDefinitions, user
+                        , "updateCapabilities", true);
+        Assert.assertTrue(capabilities.isLeft());
+        Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition ->
+                capabilityDefinition.getMaxOccurrences().equals("11")));
+    }
+
+    @Test
+    public void shouldPassUpdateCapabilityTypeUpdateWhenTypeIsNotAvailable(){
+
+        List<CapabilityDefinition> capabilityDefinitions = createMockCapabilityListToReturn(
+                createCapability("capName", "capDesc updated", "capTypeUpdate", "source1",
+                "6", "11"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<List<CapabilityDefinition>, ResponseFormat> capabilities = capabilitiesBusinessLogicMock
+                .updateCapabilities(componentId, capabilityDefinitions, user,
+                        "updateCapabilities",true);
+        Assert.assertTrue(capabilities.isLeft());
+        Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition ->
+                capabilityDefinition.getMaxOccurrences().equals("11")));
+    }
+
+    @Test
+    public void shouldPassUpdateCapabilityTypeUpdateWhenTypeIsAvailable(){
+
+        List<CapabilityDefinition> capabilityDefinitions = createMockCapabilityListToReturn(
+                createCapability("capName", "capDesc updated", "capTypeUpdate1", "source1",
+                "6", "11"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+
+        CapabilityDefinition capability = createCapability("capName", "capDesc", "capTypeUpdate1",
+                "source1", "0", "10");
+        capability.setUniqueId("unique2");
+        List<CapabilityDefinition> capabilityDefinitions1 = createMockCapabilityListToReturn(capability);
+        Map<String, List<CapabilityDefinition>> capabilityMap = new HashMap<>();
+        capabilityMap.put("capTypeUpdate1", capabilityDefinitions1);
+        resource.getCapabilities().putAll(capabilityMap);
+
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<List<CapabilityDefinition>, ResponseFormat> capabilities = capabilitiesBusinessLogicMock
+                .updateCapabilities(componentId, capabilityDefinitions, user,
+                        "updateCapabilities",true);
+        Assert.assertTrue(capabilities.isLeft());
+        Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition ->
+                capabilityDefinition.getMaxOccurrences().equals("11")));
+    }
+
+    @Test
+    public void shouldFailUpdateCapabilitiesWhenOperaitonFailedInTitan(){
+        List<CapabilityDefinition> capabilityDefinitions = createMockCapabilityListToReturn(
+                createCapability("capName2", "capDesc", "capType", "source1",
+                "0", "10"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(capabilitiesOperation.addCapabilities(anyString(), anyObject()))
+                .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR));
+        when(capabilitiesOperation.updateCapabilities(anyString(), anyObject()))
+                .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR));
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        Either<List<CapabilityDefinition>, ResponseFormat> capabilities = capabilitiesBusinessLogicMock
+                .updateCapabilities(componentId, capabilityDefinitions, user,
+                        "updateCapabilities", true);
+
+        Assert.assertTrue(capabilities.isRight());
+    }
+
+    @Test
+    public void shouldPassDeleteCapabilitiesForHappyScenario(){
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<CapabilityDefinition, ResponseFormat> deleteCapabilityEither =
+                capabilitiesBusinessLogicMock.deleteCapability(componentId, capabilityId, user, true);
+        Assert.assertTrue(deleteCapabilityEither.isLeft());
+
+    }
+
+    @Test
+    public void shouldFailDeleteCapabilitiesWhenOperationFailedInTitan(){
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        when(capabilitiesOperation.deleteCapabilities(anyObject(), anyString()))
+                .thenReturn(StorageOperationStatus.GENERAL_ERROR);
+        Either<CapabilityDefinition, ResponseFormat> deleteCapabilityEither
+                = capabilitiesBusinessLogicMock.deleteCapability(componentId, capabilityId, user, true);
+        Assert.assertTrue(deleteCapabilityEither.isRight());
+    }
+
+    @Test
+    public void shouldFailDeleteCapabilitiesWhenCapabilityUsedInServiceComposition(){
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.left(Collections.singletonList(createParentService())));
+        Either<CapabilityDefinition, ResponseFormat> deleteCapabilityEither
+                = capabilitiesBusinessLogicMock.deleteCapability(componentId, capabilityId, user, true);
+        Assert.assertTrue(deleteCapabilityEither.isRight());
+    }
+
+    @Test
+    public void shouldPassGetCapabilitiesForHappyScenario(){
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<CapabilityDefinition, ResponseFormat> getCapabilityEither
+                = capabilitiesBusinessLogicMock.getCapability(componentId, capabilityId, user, true);
+        Assert.assertTrue(getCapabilityEither.isLeft());
+
+    }
+
+    @Test
+    public void shouldFailGetCapabilitiesWhenCapabilityNotExist(){
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<CapabilityDefinition, ResponseFormat> getCapabilityEither
+                = capabilitiesBusinessLogicMock.getCapability(componentId, "capId1", user, true);
+        Assert.assertTrue(getCapabilityEither.isRight());
+
+    }
+
+    private Resource createComponent(boolean needCapability) {
+        Resource resource = new Resource();
+        resource.setName("Resource1");
+        resource.addCategory("Network Layer 2-3", "Router");
+        resource.setDescription("My short description");
+        List<String> tgs = new ArrayList<>();
+        tgs.add("test");
+        tgs.add(resource.getName());
+        resource.setTags(tgs);
+
+        if(needCapability) {
+            List<CapabilityDefinition> capabilityDefinitions = createMockCapabilityListToReturn(
+                    createCapability("capName", "capDesc", "capType", "source1",
+                    "0", "10"));
+            Map<String, List<CapabilityDefinition>> capabilityMap = new HashMap<>();
+            capabilityMap.put("capType", capabilityDefinitions);
+            resource.setCapabilities(capabilityMap);
+        }
+            resource.setName(resource.getName());
+            resource.setVersion("0.1");
+            resource.setUniqueId(resource.getName().toLowerCase() + ":" + resource.getVersion());
+            resource.setCreatorUserId(user.getUserId());
+            resource.setCreatorFullName(user.getFirstName() + " " + user.getLastName());
+            resource.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
+        return resource;
+    }
+
+    private List<CapabilityDefinition> createMockCapabilityListToReturn(CapabilityDefinition capabilityDefinition) {
+        List<CapabilityDefinition> capabilityDefinitions = new ArrayList<>();
+        capabilityDefinitions.add(capabilityDefinition);
+        return capabilityDefinitions;
+    }
+
+    private void validateUserRoles(Role... roles) {
+        List<Role> listOfRoles = Stream.of(roles).collect(Collectors.toList());
+    }
+
+    private CapabilityDefinition createCapability(String name, String description, String type,
+                                                  String validSourceTypes, String minOccurrences,
+                                                  String maxOccurrences) {
+        CapabilityDefinition capabilityDefinition = new CapabilityDefinition();
+        capabilityDefinition.setName(name);
+        capabilityDefinition.setDescription(description);
+        capabilityDefinition.setType(type);
+        capabilityDefinition.setValidSourceTypes(Collections.singletonList(validSourceTypes));
+        capabilityDefinition.setMaxOccurrences(maxOccurrences);
+        capabilityDefinition.setMinOccurrences(minOccurrences);
+        capabilityDefinition.setUniqueId(capabilityId);
+
+        return capabilityDefinition;
+    }
+
+    private Service createParentService() {
+        Service service = new Service();
+        service.setUniqueId("serviceUniqueId");
+
+        List<RequirementCapabilityRelDef> resourceInstancesRelations = new ArrayList<>();
+        RequirementCapabilityRelDef relationDef = new RequirementCapabilityRelDef();
+        relationDef.setFromNode("fromNode");
+        relationDef.setToNode("toNode");
+
+        List<CapabilityRequirementRelationship> relationships = new ArrayList<>();
+        CapabilityRequirementRelationship capabilityRequirementRelationship = new CapabilityRequirementRelationship();
+
+        RelationshipInfo relation = new RelationshipInfo();
+        relation.setCapabilityUid(capabilityId);
+        relation.setRequirementUid("reqUniqueId1");
+        capabilityRequirementRelationship.setRelation(relation);
+
+        relationships.add(capabilityRequirementRelationship);
+        relationDef.setRelationships(relationships);
+        resourceInstancesRelations.add(relationDef);
+
+        service.setComponentInstancesRelations(resourceInstancesRelations);
+
+        return service;
+    }
+
+}
\ No newline at end of file
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/RequirementBusinessLogicTest.java
new file mode 100644 (file)
index 0000000..3cac5f5
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * 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.impl;
+
+import fj.data.Either;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.auditing.impl.AuditingManager;
+import org.openecomp.sdc.be.components.validation.RequirementValidation;
+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.dao.titan.TitanOperationStatus;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
+import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.LifecycleStateEnum;
+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.User;
+import org.openecomp.sdc.be.model.jsontitan.operations.RequirementOperation;
+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.GraphLockOperation;
+import org.openecomp.sdc.be.user.Role;
+import org.openecomp.sdc.be.user.UserBusinessLogic;
+import org.openecomp.sdc.common.api.ConfigurationSource;
+import org.openecomp.sdc.common.impl.ExternalConfiguration;
+import org.openecomp.sdc.common.impl.FSConfigurationSource;
+import org.openecomp.sdc.exception.ResponseFormat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyCollection;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+public class RequirementBusinessLogicTest {
+    private final String componentId = "resourceId1";
+    private final String requirementId = "uniqueId1";
+
+    private final TitanDao mockTitanDao = Mockito.mock(TitanDao.class);
+    private final UserBusinessLogic mockUserAdmin = Mockito.mock(UserBusinessLogic.class);
+    private final ToscaOperationFacade toscaOperationFacade = Mockito.mock(ToscaOperationFacade.class);
+    private final UserValidations userValidations = Mockito.mock(UserValidations.class);
+    private final RequirementOperation requirementOperation = Mockito.mock(RequirementOperation.class);
+    private final RequirementValidation requirementValidation = Mockito.mock(RequirementValidation.class);
+
+    private final GraphLockOperation graphLockOperation = Mockito.mock(GraphLockOperation.class);
+    private User user = null;
+
+    @InjectMocks
+    private RequirementBusinessLogic requirementsBusinessLogicMock = new RequirementBusinessLogic();
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        ExternalConfiguration.setAppName("catalog-be");
+
+        // init Configuration
+        String appConfigDir = "src/test/resources/config/catalog-be";
+        ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration
+                .getChangeListener(), appConfigDir);
+        ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
+
+        ComponentsUtils componentsUtils = new ComponentsUtils(Mockito.mock(AuditingManager.class));
+        // User data and management
+        user = new User();
+        user.setUserId("jh0003");
+        user.setFirstName("Jimmi");
+        user.setLastName("Hendrix");
+        user.setRole(Role.ADMIN.name());
+
+        Either<User, ActionStatus> eitherGetUser = Either.left(user);
+        when(mockUserAdmin.getUser("jh0003", false)).thenReturn(eitherGetUser);
+        when(graphLockOperation.lockComponent(Mockito.anyString(), eq(NodeTypeEnum.Resource)))
+                .thenReturn(StorageOperationStatus.OK);
+
+        //CapabilityOperation
+        when(requirementValidation.validateRequirements(anyCollection(), anyObject(), anyBoolean()))
+                .thenReturn(Either.left(true));
+        when(requirementOperation.addRequirement(anyString(), anyObject()))
+                .thenReturn(Either.left(createMockRequirementListToReturn(createRequirement(
+                        "reqName", "capType", "node", "source1",
+                        "0", "10"))));
+
+        when(requirementOperation.updateRequirement(anyString(), anyObject()))
+                .thenReturn(Either.left(createMockRequirementListToReturn(createRequirement(
+                        "reqName", "capType", "node", "source1",
+                "0", "10"))));
+        when(requirementOperation.deleteRequirements( anyObject(), anyString()))
+                .thenReturn(StorageOperationStatus.OK);
+        when(mockTitanDao.commit()).thenReturn(TitanOperationStatus.OK);
+
+        requirementsBusinessLogicMock = new RequirementBusinessLogic();
+
+        requirementsBusinessLogicMock.setComponentsUtils(componentsUtils);
+        requirementsBusinessLogicMock.setUserAdmin(mockUserAdmin);
+        requirementsBusinessLogicMock.setGraphLockOperation(graphLockOperation);
+        requirementsBusinessLogicMock.setTitanGenericDao(mockTitanDao);
+        requirementsBusinessLogicMock.setToscaOperationFacade(toscaOperationFacade);
+        requirementsBusinessLogicMock.setUserValidations(userValidations);
+        requirementsBusinessLogicMock.setRequirementOperation(requirementOperation);
+        requirementsBusinessLogicMock.setRequirementValidation(requirementValidation);
+    }
+
+    @Test
+    public void shouldPassCreateRequirementsFirstTimeInComponentForHappyScenario(){
+        List<RequirementDefinition> requirementDefinitions = createMockRequirementListToReturn(
+                createRequirement("reqName", "reqDesc", "capType", "source1",
+                "0", "10"));
+        Resource resource = createComponent(false);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        Either<List<RequirementDefinition>, ResponseFormat> requirements = requirementsBusinessLogicMock
+                .createRequirements(componentId, requirementDefinitions, user,
+                         "createRequirements", true);
+        Assert.assertTrue(requirements.isLeft());
+        Assert.assertTrue(requirements.left().value().stream().anyMatch(requirementDefinition ->
+                requirementDefinition.getName().equals("reqName")));
+    }
+
+    @Test
+    public void shouldPassCreateRequirementsForHappyScenario(){
+        List<RequirementDefinition> requirementDefinitions = createMockRequirementListToReturn(
+                createRequirement("reqName2", "capType", "node", "source1",
+                "0", "10"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        Either<List<RequirementDefinition>, ResponseFormat> requirements = requirementsBusinessLogicMock
+                .createRequirements(componentId, requirementDefinitions, user,
+                         "createRequirements", true);
+
+        Assert.assertTrue(requirements.isLeft());
+        Assert.assertTrue(requirements.left().value().stream().anyMatch(requirementDefinition ->
+                requirementDefinition.getName().equals("reqName2")));
+    }
+
+    @Test
+    public void shouldPassUpdateRequirementsForHappyScenario(){
+
+        List<RequirementDefinition> requirementDefinitions = createMockRequirementListToReturn(
+                createRequirement("reqName", "capType", "node", "source1",
+                "6", "11"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<List<RequirementDefinition>, ResponseFormat> capabilities = requirementsBusinessLogicMock
+                .updateRequirements(componentId, requirementDefinitions, user,
+                         "updateRequirements", true);
+        Assert.assertTrue(capabilities.isLeft());
+        Assert.assertTrue(capabilities.left().value().stream().anyMatch(requirementDefinition ->
+                requirementDefinition.getMaxOccurrences().equals("11")));
+    }
+
+    @Test
+    public void shouldPassDeleteRequirementsForHappyScenario(){
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<RequirementDefinition, ResponseFormat> deleteRequirementEither
+                = requirementsBusinessLogicMock.deleteRequirement(componentId, requirementId, user, true);
+        Assert.assertTrue(deleteRequirementEither.isLeft());
+
+    }
+
+    @Test
+    public void shouldPassUpdateRequirementCapabilityUpdateWhenCapabilityNotExist(){
+
+        List<RequirementDefinition> requirementDefinitions
+                = createMockRequirementListToReturn(createRequirement(
+                        "reqName", "capTypeUpdate", "node", "source1",
+                "6", "11"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<List<RequirementDefinition>, ResponseFormat> updateRequirements
+                = requirementsBusinessLogicMock.updateRequirements(componentId, requirementDefinitions,
+                user,  "updateRequirements", true);
+        Assert.assertTrue(updateRequirements.isLeft());
+        Assert.assertTrue(updateRequirements.left().value().stream().anyMatch(requirementDefinition ->
+                requirementDefinition.getMaxOccurrences().equals("11")));
+    }
+
+    @Test
+    public void shouldPassUpdateRequirementTypeWhenCapabilityExist(){
+
+        List<RequirementDefinition> requirementDefinitions = createMockRequirementListToReturn(
+                createRequirement("reqName", "capTypeUpdate1", "node",
+                        "source1","6", "11"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+
+        RequirementDefinition requirement = createRequirement("reqName",
+                "capTypeUpdate1", "node", "source1",
+                "6", "11");
+        requirement.setUniqueId("unique2");
+        List<RequirementDefinition> requirementDefinitions1 = createMockRequirementListToReturn(requirement);
+        Map<String, List<RequirementDefinition>> requirementMap = new HashMap<>();
+        requirementMap.put("capTypeUpdate1", requirementDefinitions1);
+        resource.getRequirements().putAll(requirementMap);
+
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<List<RequirementDefinition>, ResponseFormat> capabilities
+                = requirementsBusinessLogicMock.updateRequirements(componentId, requirementDefinitions,
+                user,  "updateRequirements", true);
+        Assert.assertTrue(capabilities.isLeft());
+        Assert.assertTrue(capabilities.left().value().stream().anyMatch(capabilityDefinition ->
+                capabilityDefinition.getMaxOccurrences().equals("11")));
+    }
+
+    @Test
+    public void shouldFailUpdateRequirementWhenOperationFailedInTitan(){
+        List<RequirementDefinition> requirementDefinitions = createMockRequirementListToReturn(
+                createRequirement("reqName", "capType", "node", "source1",
+                "6", "11"));
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(requirementOperation.addRequirement(anyString(), anyObject()))
+                .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR));
+        when(requirementOperation.updateRequirement(anyString(), anyObject()))
+                .thenReturn(Either.right(StorageOperationStatus.GENERAL_ERROR));
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        Either<List<RequirementDefinition>, ResponseFormat> capabilities = requirementsBusinessLogicMock
+                .updateRequirements(componentId, requirementDefinitions, user,
+                        "updateRequirements", true);
+
+        Assert.assertTrue(capabilities.isRight());
+    }
+
+    
+    @Test
+    public void shouldFailDeleteRequirementWhenOperationFailedInTitan(){
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        when(requirementOperation.deleteRequirements(anyObject(), anyString()))
+                .thenReturn(StorageOperationStatus.GENERAL_ERROR);
+        Either<RequirementDefinition, ResponseFormat> deleteRequirementEither
+                = requirementsBusinessLogicMock.deleteRequirement(componentId, requirementId, user, true);
+        Assert.assertTrue(deleteRequirementEither.isRight());
+    }
+
+    @Test
+    public void shouldFailDeleteRequirementWhenRequirementUsedInServiceComposition(){
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.left(Collections.singletonList(createParentService())));
+        Either<RequirementDefinition, ResponseFormat> deleteRequirementEither
+                = requirementsBusinessLogicMock.deleteRequirement(componentId, requirementId, user, true);
+        Assert.assertTrue(deleteRequirementEither.isRight());
+    }
+
+    @Test
+    public void shouldPassGetRequirementsForHappyScenario(){
+        Resource resource = createComponent(true);
+        resource.setComponentType(ComponentTypeEnum.RESOURCE);
+        validateUserRoles(Role.ADMIN, Role.DESIGNER);
+        when(toscaOperationFacade.getToscaElement(anyString(), any(ComponentParametersView.class)))
+                .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getParentComponents(anyString()))
+                .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+        Either<RequirementDefinition, ResponseFormat> getRequirementEither
+                = requirementsBusinessLogicMock.getRequirement(componentId, requirementId, user, true);
+        Assert.assertTrue(getRequirementEither.isLeft());
+
+    }
+
+    private Resource createComponent(boolean needRequirements) {
+        Resource resource = new Resource();
+        resource.setName("Resource1");
+        resource.addCategory("Network Layer 2-3", "Router");
+        resource.setDescription("My short description");
+        List<String> tgs = new ArrayList<>();
+        tgs.add("test");
+        tgs.add(resource.getName());
+        resource.setTags(tgs);
+
+        if(needRequirements) {
+            List<RequirementDefinition> requirementDefinitions = createMockRequirementListToReturn(
+                    createRequirement("reqName", "capType", "node", "source1",
+                    "0", "10"));
+            Map<String, List<RequirementDefinition>> requirementsMap = new HashMap<>();
+            requirementsMap.put("capType", requirementDefinitions);
+            resource.setRequirements(requirementsMap);
+        }
+        resource.setName(resource.getName());
+        resource.setVersion("0.1");
+        resource.setUniqueId(resource.getName().toLowerCase() + ":" + resource.getVersion());
+        resource.setCreatorUserId(user.getUserId());
+        resource.setCreatorFullName(user.getFirstName() + " " + user.getLastName());
+        resource.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
+        return resource;
+    }
+
+    private List<RequirementDefinition> createMockRequirementListToReturn(RequirementDefinition requirementDefinition) {
+        List<RequirementDefinition> requirementDefinitions = new ArrayList<>();
+        requirementDefinitions.add(requirementDefinition);
+        return requirementDefinitions;
+    }
+
+    private void validateUserRoles(Role... roles) {
+        List<Role> listOfRoles = Stream.of(roles).collect(Collectors.toList());
+    }
+
+    private RequirementDefinition createRequirement(String name, String capability, String node,
+                                                    String relationship, String minOccurrences,
+                                                    String maxOccurrences) {
+        RequirementDefinition requirementDefinition = new RequirementDefinition();
+        requirementDefinition.setName(name);
+        requirementDefinition.setCapability(capability);
+        requirementDefinition.setNode(node);
+        requirementDefinition.setRelationship(relationship);
+        requirementDefinition.setMaxOccurrences(maxOccurrences);
+        requirementDefinition.setMinOccurrences(minOccurrences);
+        requirementDefinition.setUniqueId(requirementId);
+
+        return requirementDefinition;
+    }
+
+    private Service createParentService() {
+        Service service = new Service();
+        service.setUniqueId("serviceUniqueId");
+
+        List<RequirementCapabilityRelDef> resourceInstancesRelations = new ArrayList<>();
+        RequirementCapabilityRelDef relationDef = new RequirementCapabilityRelDef();
+        relationDef.setFromNode("fromNode");
+        relationDef.setToNode("toNode");
+
+        List<CapabilityRequirementRelationship> relationships = new ArrayList<>();
+        CapabilityRequirementRelationship capabilityRequirementRelationship = new CapabilityRequirementRelationship();
+
+        RelationshipInfo relation = new RelationshipInfo();
+        relation.setCapabilityUid("capabilityId");
+        relation.setRequirementUid(requirementId);
+        capabilityRequirementRelationship.setRelation(relation);
+
+        relationships.add(capabilityRequirementRelationship);
+        relationDef.setRelationships(relationships);
+        resourceInstancesRelations.add(relationDef);
+
+        service.setComponentInstancesRelations(resourceInstancesRelations);
+
+        return service;
+    }
+
+}
\ No newline at end of file
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidationTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/CapabilitiesValidationTest.java
new file mode 100644 (file)
index 0000000..b4856b9
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * 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.validation;
+
+
+import fj.data.Either;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.exception.ResponseFormat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+public class CapabilitiesValidationTest  {
+    private ResponseFormatManager responseFormatManagerMock;
+    private final Component component = createComponent();
+    private final CapabilitiesValidationUtilTest capabilitiesValidationUtilTest = new CapabilitiesValidationUtilTest();
+    @Before
+    public void init() {
+        MockitoAnnotations.initMocks(this);
+        responseFormatManagerMock = Mockito.mock(ResponseFormatManager.class);
+        when(responseFormatManagerMock.getResponseFormat(any())).thenReturn(new ResponseFormat());
+        when(responseFormatManagerMock.getResponseFormat(any(), any())).thenReturn(new ResponseFormat());
+        when(responseFormatManagerMock.getResponseFormat(any(), any(), any())).thenReturn(new ResponseFormat());
+    }
+
+    @Test
+    public void shouldPassCapabilitiesValidationForHappyScenario() {
+        List<CapabilityDefinition> capabilityDefinitions = new ArrayList<>();
+        capabilityDefinitions.add(createCapability("capName", "capDesc", "capType", "source1",
+                "0", "10"));
+        Either<Boolean, ResponseFormat> validateCapabilitiesResponseEither = capabilitiesValidationUtilTest
+                .validateCapabilities(capabilityDefinitions, component, false);
+        Assert.assertTrue(validateCapabilitiesResponseEither.isLeft());
+    }
+
+    @Test
+    public void shouldFailWhenCapabilityNameAlreadyExist() {
+        List<CapabilityDefinition> capabilityDefinitions = new ArrayList<>();
+        capabilityDefinitions.add(createCapability("capNameC", "capDesc", "capType", "source1",
+                "0", "10"));
+        Either<Boolean, ResponseFormat> validateCapabilitiesResponseEither = capabilitiesValidationUtilTest
+                .validateCapabilities(capabilityDefinitions, component, false);
+        Assert.assertTrue(validateCapabilitiesResponseEither.isRight());
+    }
+
+    @Test
+    public void shouldFailWhenCapabilityNameEmpty() {
+        List<CapabilityDefinition> capabilityDefinitions = new ArrayList<>();
+        capabilityDefinitions.add(createCapability("", "capDesc", "capType", "source1",
+                "0", "10"));
+        Either<Boolean, ResponseFormat> validateCapabilitiesResponseEither = capabilitiesValidationUtilTest
+                .validateCapabilities(capabilityDefinitions, component, false);
+        Assert.assertTrue(validateCapabilitiesResponseEither.isRight());
+    }
+
+    @Test
+    public void shouldFailWhenCapabilityTypeEmpty() {
+        List<CapabilityDefinition> capabilityDefinitions = new ArrayList<>();
+        capabilityDefinitions.add(createCapability("capName1", "capDesc", "", "source1",
+                "0", "10"));
+        Either<Boolean, ResponseFormat> validateCapabilitiesResponseEither = capabilitiesValidationUtilTest
+                .validateCapabilities(capabilityDefinitions, component, false);
+        Assert.assertTrue(validateCapabilitiesResponseEither.isRight());
+    }
+
+    @Test
+    public void shouldFailWhenCapabilityMaxOccurrencesLessThanMinOccurrences() {
+        List<CapabilityDefinition> capabilityDefinitions = new ArrayList<>();
+        capabilityDefinitions.add(createCapability("capName1", "capDesc", "capType", "source1",
+                "111", "3"));
+        Either<Boolean, ResponseFormat> validateCapabilitiesResponseEither = capabilitiesValidationUtilTest
+                .validateCapabilities(capabilityDefinitions, component, false);
+        Assert.assertTrue(validateCapabilitiesResponseEither.isRight());
+    }
+
+    @Test
+    public void shouldFailWhenCapabilityNotFoundForUpdate() {
+        List<CapabilityDefinition> capabilityDefinitions = new ArrayList<>();
+        CapabilityDefinition capabilityToUpdate = createCapability("capName1", "capDesc", "capType", "source1",
+                "1", "3");
+        capabilityToUpdate.setUniqueId("uniqueId2");
+
+        capabilityDefinitions.add(capabilityToUpdate);
+        Either<Boolean, ResponseFormat> validateCapabilitiesResponseEither = capabilitiesValidationUtilTest
+                .validateCapabilities(capabilityDefinitions, component, true);
+        Assert.assertTrue(validateCapabilitiesResponseEither.isRight());
+    }
+
+    private CapabilityDefinition createCapability(String name, String description, String type,
+                                                  String validSourceTypes, String minOccurrences,
+                                                  String maxOccurrences) {
+        CapabilityDefinition capabilityDefinition = new CapabilityDefinition();
+        capabilityDefinition.setName(name);
+        capabilityDefinition.setDescription(description);
+        capabilityDefinition.setType(type);
+        capabilityDefinition.setValidSourceTypes(Collections.singletonList(validSourceTypes));
+        capabilityDefinition.setMaxOccurrences(maxOccurrences);
+        capabilityDefinition.setMinOccurrences(minOccurrences);
+        capabilityDefinition.setUniqueId("uniqueId");
+
+
+        return capabilityDefinition;
+    }
+
+    private Resource createComponent() {
+        Resource resource = new Resource();
+        resource.setName("Resource1");
+        resource.addCategory("Network Layer 2-3", "Router");
+        resource.setDescription("My short description");
+        List<String> tgs = new ArrayList<>();
+        tgs.add("test");
+        tgs.add(resource.getName());
+        resource.setTags(tgs);
+
+        List<CapabilityDefinition> capabilityDefinitions = new ArrayList<>();
+        capabilityDefinitions.add(createCapability("capNameC", "capDesc", "capType", "source1",
+                "0", "10"));
+            Map<String, List<CapabilityDefinition>> capabilityMap = new HashMap<>();
+            capabilityMap.put("capTypeC", capabilityDefinitions);
+            resource.setCapabilities(capabilityMap);
+
+        return resource;
+    }
+
+    private class CapabilitiesValidationUtilTest extends CapabilitiesValidation {
+
+        protected ResponseFormatManager getResponseFormatManager() {
+            return responseFormatManagerMock;
+        }
+    }
+}
\ No newline at end of file
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/RequirementValidationTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/validation/RequirementValidationTest.java
new file mode 100644 (file)
index 0000000..ff9bcd1
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 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.validation;
+
+import fj.data.Either;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.RequirementDefinition;
+import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.exception.ResponseFormat;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+public class RequirementValidationTest {
+    private ResponseFormatManager responseFormatManagerMock;
+    private final Component component = createComponent();
+    private final RequirementValidationUtilTest requirementValidationUtilTest = new RequirementValidationUtilTest();
+    @Before
+    public void init() {
+        MockitoAnnotations.initMocks(this);
+        responseFormatManagerMock = Mockito.mock(ResponseFormatManager.class);
+        when(responseFormatManagerMock.getResponseFormat(any())).thenReturn(new ResponseFormat());
+        when(responseFormatManagerMock.getResponseFormat(any(), any())).thenReturn(new ResponseFormat());
+        when(responseFormatManagerMock.getResponseFormat(any(), any(), any())).thenReturn(new ResponseFormat());
+    }
+
+    @Test
+    public void shouldPassRequirementsValidationForHappyScenario() {
+        List<RequirementDefinition> requirementsDefinitions = new ArrayList<>();
+        requirementsDefinitions.add(createRequirement("reqName", "capType", "node", "source1",
+                "0", "10"));
+        Either<Boolean, ResponseFormat> validateRequirementsResponseEither = requirementValidationUtilTest
+                .validateRequirements(requirementsDefinitions, component, false);
+        Assert.assertTrue(validateRequirementsResponseEither.isLeft());
+    }
+
+    @Test
+    public void shouldFailWhenRequirementNameAlreadyExist() {
+        List<RequirementDefinition> requirementsDefinitions = new ArrayList<>();
+        requirementsDefinitions.add(createRequirement("ReqNameC", "capType", "node", "source1",
+                "0", "10"));
+        Either<Boolean, ResponseFormat> validateRequirementsResponseEither = requirementValidationUtilTest
+                .validateRequirements(requirementsDefinitions, component, false);
+        Assert.assertTrue(validateRequirementsResponseEither.isRight());
+    }
+
+    @Test
+    public void shouldFailWhenRequirementNameEmpty() {
+        List<RequirementDefinition> requirementsDefinitions = new ArrayList<>();
+        requirementsDefinitions.add(createRequirement("", "capType", "node", "source1",
+                "0", "10"));
+        Either<Boolean, ResponseFormat> validateRequirementsResponseEither = requirementValidationUtilTest
+                .validateRequirements(requirementsDefinitions, component, false);
+        Assert.assertTrue(validateRequirementsResponseEither.isRight());
+    }
+
+    @Test
+    public void shouldFailWhenRequirementCapabilityEmpty() {
+        List<RequirementDefinition> requirementsDefinitions = new ArrayList<>();
+        requirementsDefinitions.add(createRequirement("reqName1", "", "node", "source1",
+                "0", "10"));
+        Either<Boolean, ResponseFormat> validateRequirementsResponseEither = requirementValidationUtilTest
+                .validateRequirements(requirementsDefinitions, component, false);
+        Assert.assertTrue(validateRequirementsResponseEither.isRight());
+    }
+
+    @Test
+    public void shouldFailWhenRequirementMaxOccurrencesLessThanMinOccurrences() {
+        List<RequirementDefinition> requirementsDefinitions = new ArrayList<>();
+        requirementsDefinitions.add(createRequirement("reqName1", "capType", "node", "source1",
+                "111", "3"));
+        Either<Boolean, ResponseFormat> validateRequirementsResponseEither = requirementValidationUtilTest
+                .validateRequirements(requirementsDefinitions, component, false);
+        Assert.assertTrue(validateRequirementsResponseEither.isRight());
+    }
+
+    @Test
+    public void shouldFailWhenRequirementNotFoundForUpdate() {
+        List<RequirementDefinition> requirementsDefinitions = new ArrayList<>();
+        RequirementDefinition requirementsToUpdate = createRequirement("reqName1", "capType", "node", "source1",
+                "1", "3");
+        requirementsToUpdate.setUniqueId("uniqueId2");
+
+        requirementsDefinitions.add(requirementsToUpdate);
+        Either<Boolean, ResponseFormat> validateRequirementsResponseEither = requirementValidationUtilTest
+                .validateRequirements(requirementsDefinitions, component, true);
+        Assert.assertTrue(validateRequirementsResponseEither.isRight());
+    }
+
+    private RequirementDefinition createRequirement(String name, String capability, String node,
+                                                    String relationship, String minOccurrences,
+                                                    String maxOccurrences) {
+        RequirementDefinition requirementDefinition = new RequirementDefinition();
+        requirementDefinition.setName(name);
+        requirementDefinition.setCapability(capability);
+        requirementDefinition.setNode(node);
+        requirementDefinition.setRelationship(relationship);
+        requirementDefinition.setMaxOccurrences(maxOccurrences);
+        requirementDefinition.setMinOccurrences(minOccurrences);
+        requirementDefinition.setUniqueId("uniqueId");
+
+        return requirementDefinition;
+    }
+
+    private Resource createComponent() {
+        Resource resource = new Resource();
+        resource.setName("Resource1");
+        resource.addCategory("Network Layer 2-3", "Router");
+        resource.setDescription("My short description");
+        List<String> tgs = new ArrayList<>();
+        tgs.add("test");
+        tgs.add(resource.getName());
+        resource.setTags(tgs);
+
+        List<RequirementDefinition> requirementsDefinitions = new ArrayList<>();
+        requirementsDefinitions.add(createRequirement("ReqNameC", "reqDesc", "capType", "source1",
+                "0", "10"));
+        Map<String, List<RequirementDefinition>> requirementsMap = new HashMap<>();
+        requirementsMap.put("capTypeC", requirementsDefinitions);
+        resource.setRequirements(requirementsMap);
+
+        return resource;
+    }
+
+    private class RequirementValidationUtilTest extends RequirementValidation {
+
+        protected ResponseFormatManager getResponseFormatManager() {
+            return responseFormatManagerMock;
+        }
+    }
+}
\ No newline at end of file
index e97f13c..807ded8 100644 (file)
@@ -125,7 +125,7 @@ public class TypesUploadServletTest extends JerseyTest {
     protected ResourceConfig configure() {
 
         ResourceConfig resourceConfig = new ResourceConfig()
-        .register(new TypesUploadServlet(importManager, null, null, null, null, null));
+        .register(new TypesUploadServlet(importManager, null, null, null, null, null, null));
 
         resourceConfig.register(MultiPartFeature.class);
         resourceConfig.register(new AbstractBinder() {
index ff6e048..15a7fa7 100644 (file)
@@ -145,5 +145,18 @@ public enum ActionStatus {
 
 
     //InterfaceLifeCycleType
-    INTERFACE_LIFECYCLE_TYPES_NOT_FOUND
+    INTERFACE_LIFECYCLE_TYPES_NOT_FOUND,
+
+    //Capability related
+    CAPABILITY_NOT_FOUND, CAPABILITY_NAME_MANDATORY, CAPABILITY_TYPE_MANDATORY,CAPABILITY_NAME_ALREADY_IN_USE,
+    MAX_OCCURRENCES_SHOULD_BE_GREATER_THAN_MIN_OCCURRENCES, CAPABILITY_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION,
+    CAPABILITY_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION,INVALID_CAPABILITY_NAME,
+
+    RELATIONSHIP_TYPE_ALREADY_EXIST, MISSING_RELATIONSHIP_TYPE, CAPABILITY_TYPE_CANNOT_BE_EMPTY,
+
+
+    //Requirement related
+    REQUIREMENT_NOT_FOUND,  REQUIREMENT_NAME_MANDATORY, REQUIREMENT_CAPABILITY_MANDATORY,REQUIREMENT_NAME_ALREADY_IN_USE,
+    REQUIREMENT_DELETION_NOT_ALLOWED_USED_IN_COMPOSITION, REQUIREMENT_UPDATE_NOT_ALLOWED_USED_IN_COMPOSITION, INVALID_REQUIREMENT_NAME
+    ;
 }
index a6bb026..350909e 100644 (file)
@@ -172,6 +172,7 @@ public class GraphElementFactory {
                                element = clazz.cast(new InputValueData(properties));
                                break;
                        case RelationshipType:
+                               element = clazz.cast(new RelationshipTypeData(properties));
                                break;
                        case LockNode:
                                element = clazz.cast(new GraphNodeLock(properties));
index 108d5e7..9ba7048 100644 (file)
@@ -33,7 +33,7 @@ public enum VertexTypeEnum {
        INTERFACE_ARTIFACTS                     ("interface_artifacts",                 InterfaceDataDefinition.class),
        INSTANCE_ARTIFACTS                      ("instance_artifacts",                  MapArtifactDataDefinition.class),
        PROPERTIES                                      ("properties",                                  PropertyDataDefinition.class),
-       CAPABILTIES                                     ("capabilities",                                ListCapabilityDataDefinition.class),
+       CAPABILITIES                            ("capabilities",                                ListCapabilityDataDefinition.class),
        CAPABILITIES_PROPERTIES         ("capabilities_properties",             MapPropertiesDataDefinition.class),     
        REQUIREMENTS                            ("requirements",                                ListRequirementDataDefinition.class),
        ATTRIBUTES                                      ("attributes",                                  PropertyDataDefinition.class),
index 1da09e0..b3f9037 100644 (file)
 package org.openecomp.sdc.be.dao.neo4j;
 
 public enum GraphPropertiesDictionary {
-//                                             field name                                      class type                              unique          indexed 
+//                                             field name                                      class type                              unique          indexed
 //                                                                                                     stored in graph                         index   
-       // Common
-       LABEL                           ("nodeLabel",                           String.class,                           false,          true),
-       HEALTH_CHECK            ("healthcheckis",                       String.class,                           true,           true),
-       // Resource
-       NAME                            ("name",                                        String.class,                           false,          true),
-       TOSCA_RESOURCE_NAME     ("toscaResourceName",           String.class,                           false,          true),
-       CATEGORY_NAME           ("categoryName",                        String.class,                           false,          true),
-       VERSION                         ("version",                                     String.class,                           false,          true),
-       CREATION_DATE           ("creationDate",                        Long.class,                             false,          false),
-       LAST_UPDATE_DATE        ("modificationDate",            Long.class,                             false,          false),
-       IS_HIGHEST_VERSION      ("highestVersion",                      Boolean.class,                          false,          true),
-       IS_ABSTRACT                     ("abstract",                            Boolean.class,                          false,          true),
-       DESCRIPTION                     ("description",                         String.class,                           false,          false),
-       UNIQUE_ID                       ("uid",                                         String.class,                           true,           true),
-       STATE                           ("state",                                       String.class,                           false,          true),
-       TYPE                            ("type",                                        String.class,                           false,          true),
-       REQUIRED                        ("required",                            Boolean.class,                          false,          false),
-       DEFAULT_VALUE           ("defaultValue",                        String.class,                           false,          false),
-       CONSTRAINTS                     ("constraints",                         String.class,                   false,          false),
-       CONTACT_ID                      ("contactId",                           String.class,                           false,          false),
-       VENDOR_NAME                     ("vendorName",                          String.class,                           false,          false),
-       VENDOR_RELEASE          ("vendorRelease",                       String.class,                           false,          false),
-       CONFORMANCE_LEVEL       ("conformanceLevel",            String.class,                           false,          false),
-       ICON                            ("icon",                                        String.class,                           false,          false),
-       TAGS                            ("tags",                                        String.class,                   false,          false),
-       UUID                            ("uuid",                                        String.class,                           false,          true),
-       COST                            ("cost",                                        String.class,                           false,          false),
-       LICENSE_TYPE            ("licenseType",                         String.class,                           false,          false),
-       NORMALIZED_NAME         ("normalizedName",                      String.class,                           false,          true),
-       SYSTEM_NAME                     ("systemName",                          String.class,                           false,          true),
-       IS_DELETED                      ("deleted",                                     Boolean.class,                          false,          true),
-       RESOURCE_TYPE           ("resourceType",                        String.class,                           false,          true),
-       ENTRY_SCHEMA            ("entry_schema",                        String.class,                           false,          false),
-       CSAR_UUID                       ("csarUuid",                            String.class,                           false,          true),
-       CSAR_VERSION            ("csarVersion",                         String.class,                           false,          true),
-       IMPORTED_TOSCA_CHECKSUM ("importedToscaChecksum",                               String.class,                           false,          true),
-       GENERATED                       ("generated",                           Boolean.class,                          false,          false),
-       // User
-       USERID                          ("userId",                                      String.class,                           true,           true),
-       EMAIL                           ("email",                                       String.class,                           false,          false),
-       FIRST_NAME                      ("firstName",                           String.class,                           false,          false),
-       LAST_NAME                       ("lastName",                            String.class,                           false,          false),
-       ROLE                            ("role",                                        String.class,                           false,          true),
-       USER_STATUS                     ("status",                                      String.class,                           false,          true),
-       VALID_SOURCE_TYPES  ("validSourceTypes",        String.class,               false,              false),
-       NODE                            ("node",                                        String.class,                           false,          false),
-       VALUE                           ("value",                                       String.class,                           false,          false),
-       HIDDEN                          ("Hidden",                                      Boolean.class,                          false,          false),
-       PROPERTIES                      ("properties",                          String.class,                           false,          false),
-       POSITION_X                      ("positionX",                           String.class,                           false,          false),
-       POSITION_Y                      ("positionY",                           String.class,                           false,          false),
-       RELATIONSHIP_TYPE       ("relationshipType",            String.class,                           false,          false),
-       ARTIFACT_TYPE           ("artifactType",                        String.class,                           false,          true),
-       ARTIFACT_REF            ("artifactRef",                         String.class,                           false,          false),
-       ARTIFACT_REPOSITORY     ("artifactRepository",          String.class,                           false,          false),
-       ARTIFACT_CHECKSUM       ("artifactChecksum",            String.class,                           false,          false),
-       CREATOR                         ("creator",                                     String.class,                           false,          false),
-       CREATOR_ID          ("creatorId",                               String.class,                           false,          false),
-       LAST_UPDATER            ("lastUpdater",                         String.class,                           false,          false),
-       CREATOR_FULL_NAME       ("creatorFullName",                     String.class,                           false,          false),
-       UPDATER_FULL_NAME       ("updaterFullName",                     String.class,                           false,          false),
-       ES_ID                           ("esId",                                        String.class,                           false,          false),
-       ARTIFACT_LABEL          ("artifactLabel",                       String.class,                           false,          true),
-       ARTIFACT_DISPLAY_NAME("artifactDisplayName",    String.class,                           false,          true),
-       INSTANCE_COUNTER        ("instanceCounter",                     Integer.class,                          false,          false),
-       PROJECT_CODE            ("projectCode",                         String.class,                           false,          false),
-       DISTRIBUTION_STATUS     ("distributionStatus",          String.class,                           false,          false),
-       IS_VNF                          ("isVNF",                                       Boolean.class,                          false,          false),
-       LAST_LOGIN_TIME         ("lastLoginTime",                       Long.class,                                     false,          true),
-       ATTRIBUTE_COUNTER       ("attributeCounter",            Integer.class,                          false,          false),
-       INPUT_COUNTER           ("inputCounter",                        Integer.class,                          false,          false),
-       PROPERTY_COUNTER        ("propertyCounter",                     Integer.class,                          false,          false),
-       API_URL                         ("apiUrl",                                      String.class,                           false,          false),
-       SERVICE_API                     ("serviceApi",                          Boolean.class,                          false,          true),
-       ADDITIONAL_INFO_PARAMS ("additionalInfo",       String.class,              false,               false),
-       ADDITIONAL_INFO_ID_TO_KEY ("idToKey",                   String.class,              false,               false),
-       ARTIFACT_GROUP_TYPE ("artifactGroupType",       String.class,              false,               true),
-       ARTIFACT_TIMEOUT        ("timeout",                                     Integer.class,                          false,          false),
-       IS_ACTIVE                       ("isActive",                            Boolean.class,                          false,          true),
-       PROPERTY_VALUE_RULES ("propertyValueRules",             String.class,                           false,          false),
-       //authantication
-       CONSUMER_NAME           ("consumerName",                        String.class,                           true,           true),
-       CONSUMER_PASSWORD       ("consumerPassword",            String.class,                           false,          false),
-       CONSUMER_SALT           ("consumerSalt",                        String.class,                           false,          false),
-       CONSUMER_LAST_AUTHENTICATION_TIME       ("consumerLastAuthenticationTime",              Long.class,                             false,          false),
-       CONSUMER_DETAILS_LAST_UPDATED_TIME      ("consumerDetailsLastupdatedtime",              Long.class,                             false,          false),
-       LAST_MODIFIER_USER_ID("lastModfierUserId",              String.class,                           false,          false),
-       ARTIFACT_VERSION        ("artifactVersion",                     String.class,                           false,          false),
-       ARTIFACT_UUID           ("artifactUUID",                        String.class,                           false,          false),
-       PAYLOAD_UPDATE_DATE     ("payloadUpdateDate",           Long.class,                             false,          false),
-       HEAT_PARAMS_UPDATE_DATE ("heatParamsUpdateDate",Long.class,                             false,          false),
-       //product
-       FULL_NAME                       ("fullName",                            String.class,               false,              true),
-       //was changed as part of migration from 1602 to 1602 ( in 1602 was defined as unique. it's problem to reconfigure the index )
-       CONSTANT_UUID           ("constantUuidNew",                     String.class,               false,              true),
-       CONTACTS                        ("contacts",                            String.class,                           false,          false),
-       //categorys
-       ICONS                           ("icons",                                       String.class,                           false,          false),
-       //relation
-       CAPABILITY_OWNER_ID     ("capOwnerId",                          String.class,                           false,          false),
-       REQUIREMENT_OWNER_ID ("reqOwnerId",                             String.class,                           false,          false),
-       CAPABILITY_ID           ("capabiltyId",                         String.class,                           false,          false),
-       REQUIREMENT_ID          ("requirementId",                       String.class,                           false,          false),
-       PROPERTY_ID             ("propertyId",                          String.class,                           false,          false),
-       PROPERTY_NAME           ("propertyName",                        String.class,                           false,          false),
-       //component instance
-       ORIGIN_TYPE             ("originType",                          String.class,                           false,          false),
-       //requirement & capabilty
-       MIN_OCCURRENCES         ("minOccurrences",                      String.class,                           false,          false),
-       MAX_OCCURRENCES         ("maxOccurrences",                      String.class,                           false,          false),
-       //Data type
-       DERIVED_FROM            ("derivedFrom",                         String.class,                           false,          false), 
-       MEMBERS                         ("members",                                     String.class,                           false,          false),
-       TARGETS                         ("targets ",                            String.class,                           false,          false),
-       METADATA                        ("metadata",                            String.class,                           false,          false),
-       INVARIANT_UUID          ("invariantUuid",                       String.class,                           false,          true), 
-       IS_BASE                         ("isBase",                                      Boolean.class,                          false,          true), 
-       GROUP_UUID                      ("groupUuid",                       String.class,                               false,          true), 
-       STATUS                          ("status",                              String.class,                           false,          false),
-       FUNCTIONAL_MENU         ("functionalMenu",                      String.class,                           false,          false),
-       REQUIRED_ARTIFACTS      ("requiredArtifacts",           String.class,                           false,          false),
-       CUSTOMIZATION_UUID      ("customizationUUID",           String.class,                           false,          false),
-       IS_ARCHIVED                             ("isArchived",                  Boolean.class,                          false,          true),
-       IS_VSP_ARCHIVED                 ("isVspArchived",               Boolean.class,                          false,          true),
-       ARCHIVE_TIME                    ("archiveTime",                 Long.class,                             false,          true);
+    // Common
+    LABEL("nodeLabel", String.class, false, true),
+    HEALTH_CHECK("healthcheckis", String.class, true, true),
+    // Resource
+    NAME("name", String.class, false, true),
+    TOSCA_RESOURCE_NAME("toscaResourceName", String.class, false, true),
+    CATEGORY_NAME("categoryName", String.class, false, true),
+    VERSION("version", String.class, false, true),
+    CREATION_DATE("creationDate", Long.class, false, false),
+    LAST_UPDATE_DATE("modificationDate", Long.class, false, false),
+    IS_HIGHEST_VERSION("highestVersion", Boolean.class, false, true),
+    IS_ABSTRACT("abstract", Boolean.class, false, true),
+    DESCRIPTION("description", String.class, false, false),
+    UNIQUE_ID("uid", String.class, true, true),
+    STATE("state", String.class, false, true),
+    TYPE("type", String.class, false, true),
+    REQUIRED("required", Boolean.class, false, false),
+    DEFAULT_VALUE("defaultValue", String.class, false, false),
+    CONSTRAINTS("constraints", String.class, false, false),
+    CONTACT_ID("contactId", String.class, false, false),
+    VENDOR_NAME("vendorName", String.class, false, false),
+    VENDOR_RELEASE("vendorRelease", String.class, false, false),
+    CONFORMANCE_LEVEL("conformanceLevel", String.class, false, false),
+    ICON("icon", String.class, false, false),
+    TAGS("tags", String.class, false, false),
+    UUID("uuid", String.class, false, true),
+    COST("cost", String.class, false, false),
+    LICENSE_TYPE("licenseType", String.class, false, false),
+    NORMALIZED_NAME("normalizedName", String.class, false, true),
+    SYSTEM_NAME("systemName", String.class, false, true),
+    IS_DELETED("deleted", Boolean.class, false, true),
+    RESOURCE_TYPE("resourceType", String.class, false, true),
+    ENTRY_SCHEMA("entry_schema", String.class, false, false),
+    CSAR_UUID("csarUuid", String.class, false, true),
+    CSAR_VERSION("csarVersion", String.class, false, true),
+    IMPORTED_TOSCA_CHECKSUM("importedToscaChecksum", String.class, false, true),
+    GENERATED("generated", Boolean.class, false, false),
+    // User
+    USERID("userId", String.class, true, true),
+    EMAIL("email", String.class, false, false),
+    FIRST_NAME("firstName", String.class, false, false),
+    LAST_NAME("lastName", String.class, false, false),
+    ROLE("role", String.class, false, true),
+    USER_STATUS("status", String.class, false, true),
+    VALID_SOURCE_TYPES("validSourceTypes", String.class, false, false),
+    VALID_TARGET_TYPES("validTargetTypes", String.class, false, false),
+    NODE("node", String.class, false, false),
+    VALUE("value", String.class, false, false),
+    HIDDEN("Hidden", Boolean.class, false, false),
+    PROPERTIES("properties", String.class, false, false),
+    POSITION_X("positionX", String.class, false, false),
+    POSITION_Y("positionY", String.class, false, false),
+    RELATIONSHIP_TYPE("relationshipType", String.class, false, false),
+    ARTIFACT_TYPE("artifactType", String.class, false, true),
+    ARTIFACT_REF("artifactRef", String.class, false, false),
+    ARTIFACT_REPOSITORY("artifactRepository", String.class, false, false),
+    ARTIFACT_CHECKSUM("artifactChecksum", String.class, false, false),
+    CREATOR("creator", String.class, false, false),
+    CREATOR_ID("creatorId", String.class, false, false),
+    LAST_UPDATER("lastUpdater", String.class, false, false),
+    CREATOR_FULL_NAME("creatorFullName", String.class, false, false),
+    UPDATER_FULL_NAME("updaterFullName", String.class, false, false),
+    ES_ID("esId", String.class, false, false),
+    ARTIFACT_LABEL("artifactLabel", String.class, false, true),
+    ARTIFACT_DISPLAY_NAME("artifactDisplayName", String.class, false, true),
+    INSTANCE_COUNTER("instanceCounter", Integer.class, false, false),
+    PROJECT_CODE("projectCode", String.class, false, false),
+    DISTRIBUTION_STATUS("distributionStatus", String.class, false, false),
+    IS_VNF("isVNF", Boolean.class, false, false),
+    LAST_LOGIN_TIME("lastLoginTime", Long.class, false, true),
+    ATTRIBUTE_COUNTER("attributeCounter", Integer.class, false, false),
+    INPUT_COUNTER("inputCounter", Integer.class, false, false),
+    PROPERTY_COUNTER("propertyCounter", Integer.class, false, false),
+    API_URL("apiUrl", String.class, false, false),
+    SERVICE_API("serviceApi", Boolean.class, false, true),
+    ADDITIONAL_INFO_PARAMS("additionalInfo", String.class, false, false),
+    ADDITIONAL_INFO_ID_TO_KEY("idToKey", String.class, false, false),
+    ARTIFACT_GROUP_TYPE("artifactGroupType", String.class, false, true),
+    ARTIFACT_TIMEOUT("timeout", Integer.class, false, false),
+    IS_ACTIVE("isActive", Boolean.class, false, true),
+    PROPERTY_VALUE_RULES("propertyValueRules", String.class, false, false),
+    //authantication
+    CONSUMER_NAME("consumerName", String.class, true, true),
+    CONSUMER_PASSWORD("consumerPassword", String.class, false, false),
+    CONSUMER_SALT("consumerSalt", String.class, false, false),
+    CONSUMER_LAST_AUTHENTICATION_TIME("consumerLastAuthenticationTime", Long.class, false, false),
+    CONSUMER_DETAILS_LAST_UPDATED_TIME("consumerDetailsLastupdatedtime", Long.class, false, false),
+    LAST_MODIFIER_USER_ID("lastModfierUserId", String.class, false, false),
+    ARTIFACT_VERSION("artifactVersion", String.class, false, false),
+    ARTIFACT_UUID("artifactUUID", String.class, false, false),
+    PAYLOAD_UPDATE_DATE("payloadUpdateDate", Long.class, false, false),
+    HEAT_PARAMS_UPDATE_DATE("heatParamsUpdateDate", Long.class, false, false),
+    //product
+    FULL_NAME("fullName", String.class, false, true),
+    //was changed as part of migration from 1602 to 1602 ( in 1602 was defined as unique. it's problem to reconfigure the index )
+    CONSTANT_UUID("constantUuidNew", String.class, false, true),
+    CONTACTS("contacts", String.class, false, false),
+    //categorys
+    ICONS("icons", String.class, false, false),
+    //relation
+    CAPABILITY_OWNER_ID("capOwnerId", String.class, false, false),
+    REQUIREMENT_OWNER_ID("reqOwnerId", String.class, false, false),
+    CAPABILITY_ID("capabiltyId", String.class, false, false),
+    REQUIREMENT_ID("requirementId", String.class, false, false),
+    PROPERTY_ID("propertyId", String.class, false, false),
+    PROPERTY_NAME("propertyName", String.class, false, false),
+    //component instance
+    ORIGIN_TYPE("originType", String.class, false, false),
+    //requirement & capabilty
+    MIN_OCCURRENCES("minOccurrences", String.class, false, false),
+    MAX_OCCURRENCES("maxOccurrences", String.class, false, false),
+    //Data type
+    DERIVED_FROM("derivedFrom", String.class, false, false),
+    MEMBERS("members", String.class, false, false),
+    TARGETS("targets ", String.class, false, false),
+    METADATA("metadata", String.class, false, false),
+    INVARIANT_UUID("invariantUuid", String.class, false, true),
+    IS_BASE("isBase", Boolean.class, false, true),
+    GROUP_UUID("groupUuid", String.class, false, true),
+    STATUS("status", String.class, false, false),
+    FUNCTIONAL_MENU("functionalMenu", String.class, false, false),
+    REQUIRED_ARTIFACTS("requiredArtifacts", String.class, false, false),
+    CUSTOMIZATION_UUID("customizationUUID", String.class, false, false),
+    IS_ARCHIVED("isArchived", Boolean.class, false, true),
+    IS_VSP_ARCHIVED("isVspArchived", Boolean.class, false, true),
+    ARCHIVE_TIME("archiveTime", Long.class, false, true);
 
 
-       private final String property;
-       private final Class clazz;
-       private final boolean unique;
-       private final boolean indexed;
-       
-       GraphPropertiesDictionary(String property,Class clazz, boolean unique,boolean indexed) {
-               this.property = property;
-               this.clazz = clazz;
-               this.unique = unique;
-               this.indexed = indexed;
-       }
-       
+    private final String property;
+    private final Class clazz;
+    private final boolean unique;
+    private final boolean indexed;
 
-       public String getProperty() {
-               return property;
-       }
+    GraphPropertiesDictionary(String property, Class clazz, boolean unique, boolean indexed) {
+        this.property = property;
+        this.clazz = clazz;
+        this.unique = unique;
+        this.indexed = indexed;
+    }
 
-       public Class getClazz() {
-               return clazz;
-       }
 
-       public boolean isUnique() {
-               return unique;
-       }
+    public String getProperty() {
+        return property;
+    }
 
-       public boolean isIndexed() {
-               return indexed;
-       }
+    public Class getClazz() {
+        return clazz;
+    }
+
+    public boolean isUnique() {
+        return unique;
+    }
+
+    public boolean isIndexed() {
+        return indexed;
+    }
 }
index 32a86e4..440cdda 100644 (file)
@@ -57,13 +57,20 @@ public class RelationshipTypeData extends GraphNode {
                relationshipTypeDataDefinition
                                .setDescription((String) properties.get(GraphPropertiesDictionary.DESCRIPTION.getProperty()));
 
-               Type listType = new TypeToken<List<String>>() {
+               Type listSourceType = new TypeToken<List<String>>() {
                }.getType();
                List<String> validSourceTypesfromJson = getGson().fromJson(
-                               (String) properties.get(GraphPropertiesDictionary.VALID_SOURCE_TYPES.getProperty()), listType);
+                               (String) properties.get(GraphPropertiesDictionary.VALID_SOURCE_TYPES.getProperty()), listSourceType);
 
                relationshipTypeDataDefinition.setValidSourceTypes(validSourceTypesfromJson);
 
+        Type listTargetType = new TypeToken<List<String>>() {
+        }.getType();
+        List<String> validTargetTypesfromJson = getGson().fromJson(
+                (String) properties.get(GraphPropertiesDictionary.VALID_TARGET_TYPES.getProperty()), listTargetType);
+
+        relationshipTypeDataDefinition.setValidTargetTypes(validTargetTypesfromJson);
+
                // relationshipTypeDataDefinition.setValidSourceTypes((List<String>)
                // properties.get(GraphPropertiesDictionary.VALID_SOURCE_TYPES
                // .getProperty()));
@@ -98,6 +105,9 @@ public class RelationshipTypeData extends GraphNode {
                addIfExists(map, GraphPropertiesDictionary.VALID_SOURCE_TYPES,
                                relationshipTypeDataDefinition.getValidSourceTypes());
 
+        addIfExists(map, GraphPropertiesDictionary.VALID_TARGET_TYPES,
+                relationshipTypeDataDefinition.getValidTargetTypes());
+
                addIfExists(map, GraphPropertiesDictionary.CREATION_DATE, relationshipTypeDataDefinition.getCreationTime());
 
                addIfExists(map, GraphPropertiesDictionary.LAST_UPDATE_DATE,
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/RelationshipTypeDefinition.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/RelationshipTypeDefinition.java
new file mode 100644 (file)
index 0000000..5b03d0c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.RelationshipInstDataDefinition;
+import org.openecomp.sdc.be.resources.data.RelationshipTypeData;
+
+import java.util.Map;
+
+/**
+ * Specifies the capabilities that the Node Type exposes.
+ */
+public class RelationshipTypeDefinition extends RelationshipInstDataDefinition {
+
+    private String derivedFrom;
+
+    private Map<String, PropertyDefinition> properties;
+
+    public RelationshipTypeDefinition() {
+        super();
+    }
+
+    public RelationshipTypeDefinition(RelationshipInstDataDefinition p) {
+        super(p);
+    }
+
+    public RelationshipTypeDefinition(RelationshipTypeData relationshipTypeData) {
+        this.setUniqueId(relationshipTypeData.getUniqueId());
+        this.setType(relationshipTypeData.getRelationshipTypeDataDefinition().getType());
+        this.setDescription(relationshipTypeData.getRelationshipTypeDataDefinition().getDescription());
+        this.setValidSourceTypes(relationshipTypeData.getRelationshipTypeDataDefinition().getValidSourceTypes());
+    }
+
+    public String getDerivedFrom() {
+        return derivedFrom;
+    }
+
+    public void setDerivedFrom(String derivedFrom) {
+        this.derivedFrom = derivedFrom;
+    }
+
+    public Map<String, PropertyDefinition> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Map<String, PropertyDefinition> properties) {
+        this.properties = properties;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + " [ derivedFrom=" + derivedFrom + ", properties=" + properties + " ]";
+    }
+}
index 7ac941e..4babd5d 100644 (file)
@@ -34,9 +34,6 @@ public class NodeType extends ToscaElement{
     private List<String> derivedFrom;
     private List<String> derivedList;
     private Map<String, PropertyDataDefinition> attributes;
-    private Map<String, ListCapabilityDataDefinition> capabilties;
-    private Map<String, MapPropertiesDataDefinition> capabiltiesProperties;
-    private Map<String, ListRequirementDataDefinition> requirements;
     private Map<String, InterfaceDataDefinition> interfaceArtifacts;
 
     public List<String> getDerivedList() {
@@ -63,30 +60,6 @@ public class NodeType extends ToscaElement{
         this.attributes = attributes;
     }
 
-    public Map<String, ListCapabilityDataDefinition> getCapabilties() {
-        return capabilties;
-    }
-
-    public void setCapabilties(Map<String, ListCapabilityDataDefinition> capabilties) {
-        this.capabilties = capabilties;
-    }
-
-    public Map<String, ListRequirementDataDefinition> getRequirements() {
-        return requirements;
-    }
-
-    public void setRequirements(Map<String, ListRequirementDataDefinition> requirements) {
-        this.requirements = requirements;
-    }
-
-    public Map<String, MapPropertiesDataDefinition> getCapabiltiesProperties() {
-        return capabiltiesProperties;
-    }
-
-    public void setCapabiltiesProperties(Map<String, MapPropertiesDataDefinition> capabiltiesProperties) {
-        this.capabiltiesProperties = capabiltiesProperties;
-    }
-
     public Map<String, InterfaceDataDefinition> getInterfaceArtifacts() {
         return interfaceArtifacts;
     }
index 0f0c63f..a18c75b 100644 (file)
@@ -22,6 +22,9 @@ package org.openecomp.sdc.be.model.jsontitan.datamodel;
 
 import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
@@ -45,6 +48,9 @@ public abstract class ToscaElement {
     private Map<String, ArtifactDataDefinition> deploymentArtifacts;
     private Map<String, AdditionalInfoParameterDataDefinition> additionalInformation;
     private Map<String, PropertyDataDefinition> properties;
+    private Map<String, ListCapabilityDataDefinition> capabilities;
+    private Map<String, MapPropertiesDataDefinition> capabiltiesProperties;
+    private Map<String, ListRequirementDataDefinition> requirements;
 
     protected ToscaElementTypeEnum toscaType;
     // User
@@ -125,6 +131,30 @@ public abstract class ToscaElement {
         this.allVersions = allVersions;
     }
 
+    public Map<String, ListCapabilityDataDefinition> getCapabilities() {
+        return capabilities;
+    }
+
+    public void setCapabilities(Map<String, ListCapabilityDataDefinition> capabilities) {
+        this.capabilities = capabilities;
+    }
+
+    public Map<String, ListRequirementDataDefinition> getRequirements() {
+        return requirements;
+    }
+
+    public void setRequirements(Map<String, ListRequirementDataDefinition> requirements) {
+        this.requirements = requirements;
+    }
+
+    public Map<String, MapPropertiesDataDefinition> getCapabilitiesProperties() {
+        return capabiltiesProperties;
+    }
+
+    public void setCapabilitiesProperties(Map<String, MapPropertiesDataDefinition> capabiltiesProperties) {
+        this.capabiltiesProperties = capabiltiesProperties;
+    }
+
     // metadata properties
     // ----------------------------
     public Object getMetadataValue(JsonPresentationFields name) {
index 5280175..b18fb96 100644 (file)
@@ -24,6 +24,7 @@ import com.thinkaurelius.titan.core.TitanVertex;
 import fj.data.Either;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
@@ -1390,6 +1391,15 @@ public abstract class BaseOperation {
 
         StorageOperationStatus status = StorageOperationStatus.OK;
         String currKey = (String) toscaDataElement.getToscaPresentationValue(mapKeyField);
+
+        if(StringUtils.isEmpty(currKey) && toscaDataElement instanceof ListDataDefinition) {
+            ToscaDataDefinition toscaDataDefinition = ((ListDataDefinition<? extends ToscaDataDefinition>) toscaDataElement)
+                    .getListToscaDataDefinition().get(0);
+            if(toscaDataDefinition != null) {
+            currKey = (String) toscaDataDefinition.getToscaPresentationValue(mapKeyField);
+            }
+        }
+
         if (StringUtils.isEmpty(currKey)) {
             CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Failed to add tosca data to tosca element {}. The key is empty. ");
             status = StorageOperationStatus.BAD_REQUEST;
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperation.java
new file mode 100644 (file)
index 0000000..a8337b6
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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.jsontitan.operations;
+
+import fj.data.Either;
+import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
+import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
+import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@org.springframework.stereotype.Component("capabilities-operation")
+public class CapabilitiesOperation extends BaseOperation {
+    private static final Logger LOGGER = LoggerFactory.getLogger(CapabilitiesOperation.class);
+
+    public Either<List<CapabilityDefinition>, StorageOperationStatus> addCapabilities(
+            String componentId,
+            List<CapabilityDefinition> capabilityDefinitions) {
+        return addOrUpdateCapabilities(componentId, capabilityDefinitions, false);
+    }
+
+    public Either<List<CapabilityDefinition>, StorageOperationStatus> updateCapabilities(
+            String componentId,
+            List<CapabilityDefinition> capabilityDefinitions) {
+        return addOrUpdateCapabilities(componentId, capabilityDefinitions, true);
+    }
+
+    private Either<List<CapabilityDefinition>, StorageOperationStatus> addOrUpdateCapabilities(String componentId,
+                                                                                               List<CapabilityDefinition> capabilityDefinitions,
+                                                                                               boolean isUpdateAction) {
+        StorageOperationStatus statusRes = performUpdateToscaAction(isUpdateAction,
+                componentId, Collections
+                        .singletonList(convertToListCapabilityDataDefinition(capabilityDefinitions)));
+        if (!statusRes.equals(StorageOperationStatus.OK)) {
+            titanDao.rollback();
+            LOGGER.error("Failed to find the parent capability of capability type {}."
+                    + " status is {}", componentId, statusRes);
+            return Either.right(statusRes);
+        }
+        titanDao.commit();
+        return Either.left(capabilityDefinitions);
+    }
+
+    public StorageOperationStatus deleteCapabilities(Component component,
+                                                     String capabilityIdToDelete) {
+        return deleteToscaDataElements(component.getUniqueId(),
+                EdgeLabelEnum.CAPABILITIES,
+                Collections.singletonList(capabilityIdToDelete));
+    }
+
+    private static ListCapabilityDataDefinition convertToListCapabilityDataDefinition(
+            List<CapabilityDefinition> capabilities) {
+        List<CapabilityDataDefinition> capabilityDefinitions = new ArrayList<>(capabilities);
+        return new ListCapabilityDataDefinition(capabilityDefinitions);
+    }
+
+    private StorageOperationStatus performUpdateToscaAction(boolean isUpdate,
+                                                            String componentId,
+                                                            List<ListCapabilityDataDefinition> toscaDataList) {
+        if (isUpdate) {
+            return updateToscaDataOfToscaElement(componentId, EdgeLabelEnum.CAPABILITIES,
+                    VertexTypeEnum.CAPABILITIES, toscaDataList, JsonPresentationFields.TYPE);
+        } else {
+            return addToscaDataToToscaElement(componentId, EdgeLabelEnum.CAPABILITIES,
+                    VertexTypeEnum.CAPABILITIES, toscaDataList, JsonPresentationFields.TYPE);
+        }
+    }
+}
index 95f518a..7bd36ea 100644 (file)
@@ -668,58 +668,145 @@ public class NodeTemplateOperation extends BaseOperation {
         return instInput;
     }
 
+    private MapListCapabilityDataDefinition prepareCalculatedCapabiltyForTopologyTemplate(
+            Map<String, ListCapabilityDataDefinition> capabilities,
+            ComponentInstanceDataDefinition componentInstance,
+            MapListCapabilityDataDefinition calculatedCap) {
+        if (capabilities != null) {
+            MapListCapabilityDataDefinition allCalculatedCap =
+                    new MapListCapabilityDataDefinition(calculatedCap);
+            populateCapability(capabilities, componentInstance, allCalculatedCap);
+            return allCalculatedCap;
+        }
+        return null;
+    }
+
+    private void populateCapability(Map<String, ListCapabilityDataDefinition> capabilities,
+                                    ComponentInstanceDataDefinition componentInstance,
+                                    MapListCapabilityDataDefinition allCalculatedCap) {
+        capabilities.forEach((key, value) -> {
+            List<CapabilityDataDefinition> listCapabilities = value.getListToscaDataDefinition()
+                    .stream().map(CapabilityDataDefinition::new).collect(Collectors.toList());
+            listCapabilities.forEach(cap -> {
+                cap.setSource(componentInstance.getComponentUid());
+                cap.addToPath(componentInstance.getUniqueId());
+                cap.setOwnerId(componentInstance.getUniqueId());
+                cap.setOwnerName(componentInstance.getName());
+                cap.setLeftOccurrences(cap.getMaxOccurrences());
+                allCalculatedCap.add(key, cap);
+            });
+        });
+    }
+
+    private MapListRequirementDataDefinition prepareCalculatedRequirementForTopologyTemplate(
+            Map<String, ListRequirementDataDefinition> requirements,
+            ComponentInstanceDataDefinition componentInstance,
+            MapListRequirementDataDefinition calculatedReqs) {
+        if (requirements != null) {
+            MapListRequirementDataDefinition allCalculatedReq =
+                    new MapListRequirementDataDefinition(calculatedReqs);
+
+            populateRequirement(requirements, componentInstance, allCalculatedReq);
+            return allCalculatedReq;
+        }
+        return null;
+    }
+    private void populateRequirement(Map<String, ListRequirementDataDefinition> requirements,
+                                     ComponentInstanceDataDefinition componentInstance,
+                                     MapListRequirementDataDefinition allCalculatedReq) {
+        requirements.forEach((key, value) -> {
+            List<RequirementDataDefinition> listRequirements = value.getListToscaDataDefinition()
+                    .stream().map(RequirementDataDefinition::new).collect(Collectors.toList());
+            listRequirements.forEach(req -> {
+                req.setSource(componentInstance.getComponentUid());
+                req.addToPath(componentInstance.getUniqueId());
+                req.setOwnerId(componentInstance.getUniqueId());
+                req.setOwnerName(componentInstance.getName());
+                req.setLeftOccurrences(req.getMaxOccurrences());
+                allCalculatedReq.add(key, req);
+            });
+        });
+    }
+
+
+
     private StorageOperationStatus addCalculatedCapReqFromTopologyTemplate(TopologyTemplate originTopologyTemplate, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex) {
         Map<String, MapListCapabilityDataDefinition> calculatedCapabilities = originTopologyTemplate.getCalculatedCapabilities();
 
+        MapListCapabilityDataDefinition allCalculatedCap = new MapListCapabilityDataDefinition();
         if (calculatedCapabilities != null) {
-            MapListCapabilityDataDefinition allCalculatedCap = new MapListCapabilityDataDefinition();
-            calculatedCapabilities.entrySet().forEach(enntryPerInstance -> {
-                Map<String, ListCapabilityDataDefinition> mapByType = enntryPerInstance.getValue().getMapToscaDataDefinition();
-                mapByType.entrySet().forEach(entryPerType ->
-                    entryPerType.getValue().getListToscaDataDefinition().forEach(cap -> {
-                        cap.addToPath(componentInstance.getUniqueId());
-                        allCalculatedCap.add(entryPerType.getKey(), cap);
-                    }));
+            calculatedCapabilities.forEach((key1, value1) -> {
+                Map<String, ListCapabilityDataDefinition> mapByType = value1.getMapToscaDataDefinition();
+                mapByType.forEach((key, value) -> value.getListToscaDataDefinition().forEach(cap -> {
+                    cap.addToPath(componentInstance.getUniqueId());
+                    allCalculatedCap.add(key, cap);
+                }));
             });
-
-            StorageOperationStatus calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES, allCalculatedCap,
-                    componentInstance.getUniqueId());
-
-            if (calculatedResult != StorageOperationStatus.OK) {
-                return calculatedResult;
+        }
+        MapListCapabilityDataDefinition allCaps;
+        Map<String, ListCapabilityDataDefinition> capabilities = originTopologyTemplate.getCapabilities();
+        if (MapUtils.isNotEmpty(capabilities)) {
+            allCaps = prepareCalculatedCapabiltyForTopologyTemplate(capabilities, componentInstance,
+                    allCalculatedCap);
+        } else {
+            allCaps = new MapListCapabilityDataDefinition(allCalculatedCap);
+        }
+        if(!allCaps.isEmpty()) {
+            StorageOperationStatus calculatedCapabilitiesResult =
+                    addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex,
+                            EdgeLabelEnum.CALCULATED_CAPABILITIES, VertexTypeEnum.CALCULATED_CAPABILITIES,
+                            allCaps, componentInstance.getUniqueId());
+            if (calculatedCapabilitiesResult != StorageOperationStatus.OK) {
+                return calculatedCapabilitiesResult;
             }
             MapListCapabilityDataDefinition fullCalculatedCap = new MapListCapabilityDataDefinition();
-            calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.FULLFILLED_CAPABILITIES, VertexTypeEnum.FULLFILLED_CAPABILITIES, fullCalculatedCap, componentInstance.getUniqueId());
-
-            if (calculatedResult != StorageOperationStatus.OK) {
-                return calculatedResult;
+            calculatedCapabilitiesResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex,
+                    EdgeLabelEnum.FULLFILLED_CAPABILITIES, VertexTypeEnum.FULLFILLED_CAPABILITIES,
+                    fullCalculatedCap, componentInstance.getUniqueId());
+            if (calculatedCapabilitiesResult != StorageOperationStatus.OK) {
+                return calculatedCapabilitiesResult;
             }
         }
-        Map<String, MapListRequirementDataDefinition> calculatedRequirements = originTopologyTemplate.getCalculatedRequirements();
+        Map<String, MapListRequirementDataDefinition> calculatedRequirements =
+                originTopologyTemplate.getCalculatedRequirements();
+        MapListRequirementDataDefinition allCalculatedReq = new MapListRequirementDataDefinition();
         if (calculatedRequirements != null) {
-
-            MapListRequirementDataDefinition allCalculatedReq = new MapListRequirementDataDefinition();
-            calculatedRequirements.entrySet().forEach(enntryPerInstance -> {
-                Map<String, ListRequirementDataDefinition> mapByType = enntryPerInstance.getValue().getMapToscaDataDefinition();
-                mapByType.entrySet().forEach(entryPerType ->
-                    entryPerType.getValue().getListToscaDataDefinition().forEach(req -> {
-                        req.addToPath(componentInstance.getUniqueId());
-                        allCalculatedReq.add(entryPerType.getKey(), req);
-                    }));
+            calculatedRequirements.forEach((key, value) -> {
+                Map<String, ListRequirementDataDefinition> mapByType =
+                        value.getMapToscaDataDefinition();
+                mapByType.forEach((key1, value1) -> value1.getListToscaDataDefinition().forEach(req -> {
+                    req.addToPath(componentInstance.getUniqueId());
+                    allCalculatedReq.add(key1, req);
+                }));
             });
 
-            StorageOperationStatus calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_REQUIREMENTS, VertexTypeEnum.CALCULATED_REQUIREMENTS, allCalculatedReq,
-                    componentInstance.getUniqueId());
-            if (calculatedResult != StorageOperationStatus.OK) {
-                return calculatedResult;
+        }
+
+        MapListRequirementDataDefinition allReqs;
+        Map<String, ListRequirementDataDefinition> requirements = originTopologyTemplate.getRequirements();
+        if (MapUtils.isNotEmpty(requirements)) {
+            allReqs = prepareCalculatedRequirementForTopologyTemplate(requirements,
+                    componentInstance, allCalculatedReq);
+        } else
+            allReqs = new MapListRequirementDataDefinition(allCalculatedReq);
+
+        if(!allReqs.isEmpty()) {
+            StorageOperationStatus calculatedRequirementResult =
+                    addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex,
+                            EdgeLabelEnum.CALCULATED_REQUIREMENTS, VertexTypeEnum.CALCULATED_REQUIREMENTS,
+                            allReqs, componentInstance.getUniqueId());
+            if (calculatedRequirementResult != StorageOperationStatus.OK) {
+                return calculatedRequirementResult;
             }
             MapListRequirementDataDefinition fullCalculatedReq = new MapListRequirementDataDefinition();
-            calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.FULLFILLED_REQUIREMENTS, VertexTypeEnum.FULLFILLED_REQUIREMENTS, fullCalculatedReq, componentInstance.getUniqueId());
-            if (calculatedResult != StorageOperationStatus.OK) {
-                return calculatedResult;
+            calculatedRequirementResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex,
+                    EdgeLabelEnum.FULLFILLED_REQUIREMENTS, VertexTypeEnum.FULLFILLED_REQUIREMENTS,
+                    fullCalculatedReq,
+                    componentInstance.getUniqueId());
+            if (calculatedRequirementResult != StorageOperationStatus.OK) {
+                return calculatedRequirementResult;
             }
         }
-
         Map<String, MapCapabilityProperty> calculatedCapabilitiesProperties = originTopologyTemplate.getCalculatedCapabilitiesProperties();
         Map<String, MapPropertiesDataDefinition> updateKeyMap = new HashMap<>();
 
@@ -730,9 +817,27 @@ public class NodeTemplateOperation extends BaseOperation {
                     updateKeyMap.put(newKey, entry.getValue());
                 }
             }
-            MapCapabilityProperty mapCapabilityProperty = new MapCapabilityProperty(updateKeyMap);
-            StorageOperationStatus calculatedResult = addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex, EdgeLabelEnum.CALCULATED_CAP_PROPERTIES, VertexTypeEnum.CALCULATED_CAP_PROPERTIES, mapCapabilityProperty,
-                    componentInstance.getUniqueId());
+        }
+        Map<String, MapPropertiesDataDefinition> capabilitiesProperties =
+                originTopologyTemplate.getCapabilitiesProperties();
+        Map<String, MapPropertiesDataDefinition> updateKeyMapCapabilitiesProperties;
+        if (MapUtils.isNotEmpty(capabilitiesProperties)) {
+            updateKeyMapCapabilitiesProperties = capabilitiesProperties.entrySet().stream()
+                    .collect(Collectors.toMap(e -> createCapPropertyKey(e.getKey(),
+                            componentInstance.getUniqueId()), Entry::getValue));
+        }
+        else {
+            updateKeyMapCapabilitiesProperties = new HashMap<>();
+        }
+        updateKeyMap.putAll(updateKeyMapCapabilitiesProperties);
+        MapCapabilityProperty mapCapabilityProperty = new MapCapabilityProperty(updateKeyMap);
+
+        if(MapUtils.isNotEmpty(capabilitiesProperties) || MapUtils.isNotEmpty(calculatedCapabilitiesProperties )) {
+            StorageOperationStatus calculatedResult =
+                    addToscaDataDeepElementsBlockToToscaElement(updatedContainerVertex,
+                            EdgeLabelEnum.CALCULATED_CAP_PROPERTIES,
+                            VertexTypeEnum.CALCULATED_CAP_PROPERTIES, mapCapabilityProperty,
+                            componentInstance.getUniqueId());
             if (calculatedResult != StorageOperationStatus.OK) {
                 return calculatedResult;
             }
@@ -857,7 +962,7 @@ public class NodeTemplateOperation extends BaseOperation {
      */
     private StorageOperationStatus addCalculatedCapReqFromNodeType(NodeType originNodeType, ComponentInstanceDataDefinition componentInstance, GraphVertex updatedContainerVertex) {
 
-        Map<String, ListCapabilityDataDefinition> capabilities = originNodeType.getCapabilties();
+        Map<String, ListCapabilityDataDefinition> capabilities = originNodeType.getCapabilities();
         MapListCapabilityDataDefinition allCalculatedCap = prepareCalculatedCapabiltyForNodeType(capabilities, componentInstance);
         StorageOperationStatus calculatedResult;
         if (allCalculatedCap != null) {
@@ -867,7 +972,7 @@ public class NodeTemplateOperation extends BaseOperation {
                 return calculatedResult;
             }
         }
-        Map<String, MapPropertiesDataDefinition> capabiltiesProperties = originNodeType.getCapabiltiesProperties();
+        Map<String, MapPropertiesDataDefinition> capabiltiesProperties = originNodeType.getCapabilitiesProperties();
         if (capabiltiesProperties != null) {
             Map<String, MapPropertiesDataDefinition> updateKeyMap = capabiltiesProperties.entrySet().stream().collect(Collectors.toMap(e -> createCapPropertyKey(e.getKey(), componentInstance.getUniqueId()), Entry::getValue));
             MapCapabilityProperty mapCapabilityProperty = new MapCapabilityProperty(updateKeyMap);
@@ -918,17 +1023,7 @@ public class NodeTemplateOperation extends BaseOperation {
         if (capabilities != null) {
             MapListCapabilityDataDefinition allCalculatedCap = new MapListCapabilityDataDefinition();
 
-            capabilities.entrySet().forEach(e -> {
-                List<CapabilityDataDefinition> listCapabilities = e.getValue().getListToscaDataDefinition().stream().map(CapabilityDataDefinition::new).collect(Collectors.toList());
-                listCapabilities.forEach(cap -> {
-                    cap.setSource(componentInstance.getComponentUid());
-                    cap.addToPath(componentInstance.getUniqueId());
-                    cap.setOwnerId(componentInstance.getUniqueId());
-                    cap.setOwnerName(componentInstance.getName());
-                    cap.setLeftOccurrences(cap.getMaxOccurrences());
-                    allCalculatedCap.add(e.getKey(), cap);
-                });
-            });
+            populateCapability(capabilities, componentInstance, allCalculatedCap);
             return allCalculatedCap;
         }
         return null;
@@ -945,17 +1040,7 @@ public class NodeTemplateOperation extends BaseOperation {
         if (requirements != null) {
             MapListRequirementDataDefinition allCalculatedReq = new MapListRequirementDataDefinition();
 
-            requirements.entrySet().forEach(e -> {
-                List<RequirementDataDefinition> listRequirements = e.getValue().getListToscaDataDefinition().stream().map(RequirementDataDefinition::new).collect(Collectors.toList());
-                listRequirements.forEach(req -> {
-                    req.setSource(componentInstance.getComponentUid());
-                    req.addToPath(componentInstance.getUniqueId());
-                    req.setOwnerId(componentInstance.getUniqueId());
-                    req.setOwnerName(componentInstance.getName());
-                    req.setLeftOccurrences(req.getMaxOccurrences());
-                    allCalculatedReq.add(e.getKey(), req);
-                });
-            });
+            populateRequirement(requirements, componentInstance, allCalculatedReq);
             return allCalculatedReq;
         }
         return null;
@@ -1135,7 +1220,7 @@ public class NodeTemplateOperation extends BaseOperation {
                 requirementAndRelationshipPair.setId(relationshipInstData.getUniqueId());
                 CapabilityRequirementRelationship capReqRel = new CapabilityRequirementRelationship();
                 capReqRel.setRelation(requirementAndRelationshipPair);
-                capReqRel.setCapability((CapabilityDataDefinition) associateRes.left().value().get(JsonPresentationFields.CAPAPILITY));
+                capReqRel.setCapability((CapabilityDataDefinition) associateRes.left().value().get(JsonPresentationFields.CAPABILITY));
                 capReqRel.setRequirement((RequirementDataDefinition) associateRes.left().value().get(JsonPresentationFields.REQUIREMENT));
                 relationshipsResult.add(capReqRel);
                 CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "update customization UUID for from CI {} and to CI {}", relation.getFromNode(), relation.getToNode());
@@ -1680,7 +1765,7 @@ public class NodeTemplateOperation extends BaseOperation {
             CapabilityDataDefinition cap = iteratorCap.next();
             if (cap.getUniqueId().equals(relationPair.getCapabilityUid()) && cap.getOwnerId().equals(relationPair.getCapabilityOwnerId())) {
                 capabilityForRelation = cap;
-                capReqRelationship.put(JsonPresentationFields.CAPAPILITY, (T) capabilityForRelation);
+                capReqRelationship.put(JsonPresentationFields.CAPABILITY, (T) capabilityForRelation);
                 String leftOccurrences = cap.getLeftOccurrences();
                 if (leftOccurrences != null && !leftOccurrences.equals(CapabilityDataDefinition.MAX_OCCURRENCES)) {
                     Integer leftIntValue = Integer.parseInt(leftOccurrences);
@@ -1807,23 +1892,23 @@ public class NodeTemplateOperation extends BaseOperation {
         return relationshipInstData;
     }
 
-    public StorageOperationStatus associateComponentInstancesToComponent(Component containerComponent, Map<ComponentInstance, Resource> resourcesInstancesMap, GraphVertex containerVertex, boolean allowDeleted) {
+    public <T extends Component> StorageOperationStatus associateComponentInstancesToComponent(Component containerComponent, Map<ComponentInstance, T> componentInstanceTMap, GraphVertex containerVertex, boolean allowDeleted) {
 
         StorageOperationStatus result = null;
         String containerId = containerComponent.getUniqueId();
         Map<String, ComponentInstanceDataDefinition> instancesJsonData = null;
         Either<GraphVertex, TitanOperationStatus> updateElement = null;
-        if (!validateInstanceNames(resourcesInstancesMap)) {
+        if (!validateInstanceNames(componentInstanceTMap)) {
             result = StorageOperationStatus.INCONSISTENCY;
         }
-        if (result == null && !validateInstanceNames(resourcesInstancesMap)) {
+        if (result == null && !validateInstanceNames(componentInstanceTMap)) {
             result = StorageOperationStatus.INCONSISTENCY;
         }
-        if (result == null && !allowDeleted && !validateDeletedResources(resourcesInstancesMap)) {
+        if (result == null && !allowDeleted && !validateDeletedResources(componentInstanceTMap)) {
             result = StorageOperationStatus.INCONSISTENCY;
         }
         if (result == null) {
-            instancesJsonData = convertToComponentInstanceDataDefinition(resourcesInstancesMap, containerId);
+            instancesJsonData = convertToComponentInstanceDataDefinition(componentInstanceTMap, containerId);
         }
         if (result == null && MapUtils.isNotEmpty(instancesJsonData)) {
             containerVertex.setJsonMetadataField(JsonPresentationFields.LAST_UPDATE_DATE, System.currentTimeMillis());
@@ -1846,21 +1931,21 @@ public class NodeTemplateOperation extends BaseOperation {
         return result;
     }
 
-    private Map<String, ComponentInstanceDataDefinition> convertToComponentInstanceDataDefinition(Map<ComponentInstance, Resource> resourcesInstancesMap, String containerId) {
+    private <T extends Component> Map<String, ComponentInstanceDataDefinition> convertToComponentInstanceDataDefinition(Map<ComponentInstance, T> componentInstanceTMap, String containerId) {
 
         Map<String, ComponentInstanceDataDefinition> instances = new HashMap<>();
-        for (Entry<ComponentInstance, Resource> entry : resourcesInstancesMap.entrySet()) {
+        for (Entry<ComponentInstance, T> entry : componentInstanceTMap.entrySet()) {
             ComponentInstanceDataDefinition instance = buildComponentInstanceDataDefinition(entry.getKey(), containerId, null, true, ModelConverter.convertToToscaElement(entry.getValue()));
             instances.put(instance.getUniqueId(), instance);
         }
         return instances;
     }
 
-    private boolean validateDeletedResources(Map<ComponentInstance, Resource> resourcesInstancesMap) {
+    private <T extends Component> boolean validateDeletedResources(Map<ComponentInstance, T> resourcesInstancesMap) {
         boolean result = true;
-        for (Resource resource : resourcesInstancesMap.values()) {
-            if (resource.getIsDeleted() != null && resource.getIsDeleted()) {
-                CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Component {} is already deleted. Cannot add component instance. ", resource.getName());
+        for (Component component : resourcesInstancesMap.values()) {
+            if (component.getIsDeleted() != null && component.getIsDeleted()) {
+                CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, "Component {} is already deleted. Cannot add component instance. ", component.getName());
                 result = false;
                 break;
             }
@@ -1868,7 +1953,7 @@ public class NodeTemplateOperation extends BaseOperation {
         return result;
     }
 
-    private boolean validateInstanceNames(Map<ComponentInstance, Resource> resourcesInstancesMap) {
+    private <T extends Component> boolean validateInstanceNames(Map<ComponentInstance, T> resourcesInstancesMap) {
         boolean result = true;
         Set<String> names = new HashSet<>();
         for (ComponentInstance instance : resourcesInstancesMap.keySet()) {
index d9ced8c..967fc16 100644 (file)
@@ -289,7 +289,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
     private TitanOperationStatus setComponentCapPropertiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
         Either<Map<String, MapPropertiesDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES_PROPERTIES);
         if (result.isLeft()) {
-            toscaElement.setCapabiltiesProperties(result.left().value());
+            toscaElement.setCapabilitiesProperties(result.left().value());
         } else {
             if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
                 return result.right().value();
@@ -317,7 +317,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
     private TitanOperationStatus setResourceCapabilitiesFromGraph(GraphVertex componentV, NodeType toscaElement) {
         Either<Map<String, ListCapabilityDataDefinition>, TitanOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES);
         if (result.isLeft()) {
-            toscaElement.setCapabilties(result.left().value());
+            toscaElement.setCapabilities(result.left().value());
         } else {
             if (result.right().value() != TitanOperationStatus.NOT_FOUND) {
                 return result.right().value();
@@ -448,7 +448,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
         }
         Map<String, ListCapabilityDataDefinition> capabiltiesAll = dataFromDerived.left().value();
 
-        Map<String, ListCapabilityDataDefinition> capabilties = nodeType.getCapabilties();
+        Map<String, ListCapabilityDataDefinition> capabilties = nodeType.getCapabilities();
         if (capabilties != null) {
             if (capabiltiesAll == null) {
                 capabiltiesAll = new HashMap<>();
@@ -483,7 +483,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
             });
         });
         if (!capabiltiesAll.isEmpty()) {
-            Either<GraphVertex, StorageOperationStatus> assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILTIES, EdgeLabelEnum.CAPABILITIES, capabiltiesAll);
+            Either<GraphVertex, StorageOperationStatus> assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILITIES, EdgeLabelEnum.CAPABILITIES, capabiltiesAll);
             if (assosiateElementToData.isRight()) {
                 return assosiateElementToData.right().value();
             }
@@ -556,7 +556,7 @@ public class NodeTypeOperation extends ToscaElementOperation {
             return dataFromDerived.right().value();
         }
         Map<String, MapPropertiesDataDefinition> propertiesAll = dataFromDerived.left().value();
-        Map<String, MapPropertiesDataDefinition> capabiltiesProps = nodeType.getCapabiltiesProperties();
+        Map<String, MapPropertiesDataDefinition> capabiltiesProps = nodeType.getCapabilitiesProperties();
         if (capabiltiesProps != null) {
             capabiltiesProps.values().forEach(l -> {
                 if (l.getMapToscaDataDefinition() != null && l.getMapToscaDataDefinition().values() != null) {
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/RequirementOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/RequirementOperation.java
new file mode 100644 (file)
index 0000000..1fd3750
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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.jsontitan.operations;
+
+import fj.data.Either;
+import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
+import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
+import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.RequirementDefinition;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@org.springframework.stereotype.Component("requirement-operation")
+public class RequirementOperation extends BaseOperation {
+    private static final Logger LOGGER = LoggerFactory.getLogger(RequirementOperation.class);
+
+    public Either<List<RequirementDefinition>, StorageOperationStatus> addRequirement(
+            String componentId,
+            List<RequirementDefinition> requirementDefinitions) {
+        return addOrUpdateRequirements( componentId, requirementDefinitions, false);
+    }
+
+    public Either<List<RequirementDefinition>, StorageOperationStatus> updateRequirement(
+            String componentId,
+            List<RequirementDefinition> requirementDefinitions) {
+        return addOrUpdateRequirements( componentId, requirementDefinitions, true);
+    }
+
+
+    private Either<List<RequirementDefinition>, StorageOperationStatus> addOrUpdateRequirements(String componentId,
+                                                                 List<RequirementDefinition> requirementDefinitions,
+                                                                                                boolean isUpdateAction) {
+
+        StorageOperationStatus statusRes = performUpdateToscaAction(isUpdateAction,
+                componentId, Collections
+                        .singletonList(convertToListRequirementDataDefinition(requirementDefinitions)));
+        if (!statusRes.equals(StorageOperationStatus.OK)) {
+            titanDao.rollback();
+            LOGGER.error("Failed to find the parent capability of capability type {}."
+                    + " status is {}", componentId, statusRes);
+            return Either.right(statusRes);
+        }
+        titanDao.commit();
+        return Either.left(requirementDefinitions);
+    }
+
+    public StorageOperationStatus deleteRequirements(Component component,
+                                                     String requirementToDelete) {
+        return deleteToscaDataElements(component.getUniqueId(),
+                EdgeLabelEnum.REQUIREMENTS, Collections.singletonList(requirementToDelete));
+    }
+
+    private static ListRequirementDataDefinition convertToListRequirementDataDefinition(
+            List<RequirementDefinition> requirementDefinitions) {
+        List<RequirementDataDefinition> requirementDataDefinitions =
+                new ArrayList<>(requirementDefinitions);
+        return new ListRequirementDataDefinition(requirementDataDefinitions);
+    }
+
+    private StorageOperationStatus performUpdateToscaAction(boolean isUpdate,
+                                                            String componentId, List<ListRequirementDataDefinition> toscaDataList) {
+        if (isUpdate) {
+            return updateToscaDataOfToscaElement(componentId, EdgeLabelEnum.REQUIREMENTS,
+                    VertexTypeEnum.REQUIREMENTS, toscaDataList, JsonPresentationFields.CAPABILITY);
+        } else {
+            return addToscaDataToToscaElement(componentId, EdgeLabelEnum.REQUIREMENTS,
+                    VertexTypeEnum.REQUIREMENTS, toscaDataList, JsonPresentationFields.CAPABILITY);
+        }
+    }
+}
index 38c6b5d..0954257 100644 (file)
@@ -50,6 +50,8 @@ 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.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.MapDataDefinition;
@@ -272,6 +274,15 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
                 return assosiateElementToData.right().value();
             }
         }
+        Map<String, ListCapabilityDataDefinition> capabilities = topologyTemplate.getCapabilities();
+        if(MapUtils.isNotEmpty(capabilities)) {
+            Either<GraphVertex, StorageOperationStatus> associateElementToData =
+                    associateElementToData(nodeTypeVertex, VertexTypeEnum.CAPABILITIES,
+                            EdgeLabelEnum.CAPABILITIES, capabilities);
+            if (associateElementToData.isRight()) {
+                return associateElementToData.right().value();
+            }
+        }
         return StorageOperationStatus.OK;
 
     }
@@ -291,6 +302,15 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
                 return assosiateElementToData.right().value();
             }
         }
+        Map<String, ListRequirementDataDefinition> requirements = topologyTemplate.getRequirements();
+        if(MapUtils.isNotEmpty(requirements)) {
+            Either<GraphVertex, StorageOperationStatus> associateElementToData =
+                    associateElementToData(nodeTypeVertex, VertexTypeEnum.REQUIREMENTS,
+                            EdgeLabelEnum.REQUIREMENTS, requirements);
+            if (associateElementToData.isRight()) {
+                return associateElementToData.right().value();
+            }
+        }
         return StorageOperationStatus.OK;
     }
 
@@ -905,6 +925,15 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
                 return result.right().value();
             }
         }
+        Either<Map<String, ListRequirementDataDefinition>, TitanOperationStatus> requirementResult =
+                getDataFromGraph(componentV, EdgeLabelEnum.REQUIREMENTS);
+        if (requirementResult.isLeft()) {
+            toscaElement.setRequirements(requirementResult.left().value());
+        } else {
+            if (requirementResult.right().value() != TitanOperationStatus.NOT_FOUND) {
+                return requirementResult.right().value();
+            }
+        }
         return TitanOperationStatus.OK;
 
     }
@@ -926,6 +955,15 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
                 return result.right().value();
             }
         }
+        Either<Map<String, ListCapabilityDataDefinition>, TitanOperationStatus> capabilitiesResult =
+                getDataFromGraph(componentV, EdgeLabelEnum.CAPABILITIES);
+        if (capabilitiesResult.isLeft()) {
+            toscaElement.setCapabilities(capabilitiesResult.left().value());
+        } else {
+            if (capabilitiesResult.right().value() != TitanOperationStatus.NOT_FOUND) {
+                return capabilitiesResult.right().value();
+            }
+        }
         return TitanOperationStatus.OK;
     }
 
@@ -1139,6 +1177,21 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
             return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
         }
 
+        status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT,
+                EdgeLabelEnum.REQUIREMENTS);
+        if (status != TitanOperationStatus.OK) {
+            log.debug("Failed to disassociate requirements for {} error {}",
+                    toscaElementVertex.getUniqueId(), status);
+            Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+        }
+        status = titanDao.disassociateAndDeleteLast(toscaElementVertex, Direction.OUT,
+                EdgeLabelEnum.CAPABILITIES);
+        if (status != TitanOperationStatus.OK) {
+            log.debug("Failed to disassociate capabilities for {} error {}",
+                    toscaElementVertex.getUniqueId(), status);
+            Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(status));
+        }
+
         toscaElementVertex.getVertex().remove();
         log.trace("Tosca element vertex for {} was removed", toscaElementVertex.getUniqueId());
 
@@ -1444,5 +1497,32 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
         filter.setIgnoreRequirements(false);
         return filter;
     }
+    public void updateCapReqOwnerId(String componentId, TopologyTemplate toscaElement) {
+        GraphVertex toscaElementV = titanDao.getVertexById(componentId, JsonParseFlagEnum.NoParse)
+                .left().on(this::throwStorageException);
+        updateCapOwnerId(toscaElement, componentId);
+        updateReqOwnerId(toscaElement, componentId);
+        topologyTemplateOperation
+
+                .updateFullToscaData(toscaElementV, EdgeLabelEnum.CAPABILITIES,
+                        VertexTypeEnum.CAPABILITIES, toscaElement.getCapabilities());
+        topologyTemplateOperation
+                .updateFullToscaData(toscaElementV, EdgeLabelEnum.REQUIREMENTS,
+                        VertexTypeEnum.REQUIREMENTS, toscaElement.getRequirements());
+    }
+
+    private void updateCapOwnerId(ToscaElement toscaElement, String ownerId) {
+        if(MapUtils.isNotEmpty(toscaElement.getCapabilities())) {
+            toscaElement.getCapabilities().values().stream().flatMap(listCapDef -> listCapDef.getListToscaDataDefinition().stream())
+                    .forEach(capabilityDefinition -> capabilityDefinition.setOwnerId(ownerId));
+        }
+    }
+
+    private void updateReqOwnerId(ToscaElement toscaElement, String ownerId) {
+        if(MapUtils.isNotEmpty(toscaElement.getRequirements())) {
+            toscaElement.getRequirements().values().stream().flatMap(listReqDef -> listReqDef.getListToscaDataDefinition().stream())
+                    .forEach(requirementDefinition -> requirementDefinition.setOwnerId(ownerId));
+        }
+    }
 
 }
index d8a4fc4..a69c80c 100644 (file)
@@ -2546,5 +2546,8 @@ public class ToscaOperationFacade {
         }
         return Either.left(parentComponents);
     }
-
+    public void updateCapReqOwnerId(String componentId) {
+        topologyTemplateOperation
+                .updateCapReqOwnerId(componentId, getTopologyTemplate(componentId));
+    }
 }
index 5e40bd5..6fbd7ad 100644 (file)
@@ -152,6 +152,8 @@ public class ModelConverter {
         convertServiceInterfaces(topologyTemplate, service);
 
         convertNodeFiltersComponents(topologyTemplate, service);
+        setCapabilitiesToComponent(topologyTemplate, service);
+        setRequirementsToComponent(topologyTemplate, service);
         return service;
     }
 
@@ -200,6 +202,8 @@ public class ModelConverter {
             convertPolicies(topologyTemplate, resource);
             convertNodeFiltersComponents(topologyTemplate, resource);
             convertProperties(topologyTemplate, resource);
+            setCapabilitiesToComponent(topologyTemplate, resource);
+            setRequirementsToComponent(topologyTemplate, resource);
         }
         convertArtifacts(toscaElement, resource);
         convertAdditionalInformation(toscaElement, resource);
@@ -401,6 +405,7 @@ public class ModelConverter {
     }
 
     private static void convertCapabilities(Component component, TopologyTemplate topologyTemplate) {
+        convertTopologyTemplateCapabilities(component, topologyTemplate);
         if(componentInstancesCapabilitiesExist(component) || groupsCapabilitiesExist(component)){
             topologyTemplate.setCalculatedCapabilities(new HashMap<>());
             topologyTemplate.setCalculatedCapabilitiesProperties(new HashMap<>());
@@ -418,6 +423,65 @@ public class ModelConverter {
         }
     }
 
+    private static void convertTopologyTemplateCapabilities(Component component, ToscaElement toscaElement) {
+        Map<String, List<CapabilityDefinition>> capabilities = component.getCapabilities();
+
+        Map<String, ListCapabilityDataDefinition> toscaCapMap = new HashMap<>();
+        Map<String, MapPropertiesDataDefinition> toscaCapPropMap = new HashMap<>();
+
+        if (MapUtils.isNotEmpty(capabilities )) {
+            capabilities.forEach((s, caps) -> {
+                        if (CollectionUtils.isNotEmpty(caps)) {
+                            List<CapabilityDataDefinition> capList = caps.stream().filter(capabilityDefinition -> capabilityDefinition.getOwnerId()
+                                    .equals(component.getUniqueId())).map(CapabilityDataDefinition::new).collect(Collectors.toList());
+
+                            populateCapabilityMap(toscaCapMap, toscaCapPropMap, s, caps, capList);
+                        }
+                    }
+            );
+
+            toscaElement.setCapabilities(toscaCapMap);
+            toscaElement.setCapabilitiesProperties(toscaCapPropMap);
+        }
+    }
+    private static void populateCapabilityMap(Map<String, ListCapabilityDataDefinition> toscaCapMap,
+                                              Map<String, MapPropertiesDataDefinition> toscaCapPropMap,
+                                              String s, List<CapabilityDefinition> caps,
+                                              List<CapabilityDataDefinition> capList) {
+        ListCapabilityDataDefinition listCapabilityDataDefinition = new ListCapabilityDataDefinition(capList);
+        toscaCapMap.put(s, listCapabilityDataDefinition);
+
+        for (CapabilityDefinition cap : caps) {
+            List<ComponentInstanceProperty> capPrps = cap.getProperties();
+            if (CollectionUtils.isNotEmpty(capPrps)) {
+                MapPropertiesDataDefinition dataToCreate = new MapPropertiesDataDefinition();
+                for (ComponentInstanceProperty cip : capPrps) {
+                    dataToCreate.put(cip.getName(), new PropertyDataDefinition(cip));
+                }
+                toscaCapPropMap.put(s + CAP_PROP_DELIM + cap.getName(), dataToCreate);
+            }
+        }
+    }
+
+    private static void convertTopologyTemplateRequirements(Component component, ToscaElement toscaElement) {
+        Map<String, List<RequirementDefinition>> requirements = component.getRequirements();
+
+        Map<String, ListRequirementDataDefinition> toscaReqMap = new HashMap<>();
+
+        if (MapUtils.isNotEmpty(requirements )) {
+            requirements.forEach((s, reqs)-> {
+                        if (CollectionUtils.isNotEmpty(reqs)) {
+                            List<RequirementDataDefinition> reqList = reqs.stream().filter(requirementDefinition -> requirementDefinition.getOwnerId()
+                                    .equals(component.getUniqueId())).map(RequirementDataDefinition::new).collect(Collectors.toList());
+
+                            ListRequirementDataDefinition listRequirementDataDefinition = new ListRequirementDataDefinition(reqList);
+                            toscaReqMap.put(s, listRequirementDataDefinition);
+                        }
+                    }
+            );
+            toscaElement.setRequirements(toscaReqMap);
+        }
+    }
     private static void convertComponentInstancesCapabilities(Component component, TopologyTemplate topologyTemplate) {
         if (componentInstancesCapabilitiesExist(component)) {
             component.getComponentInstances()
@@ -510,6 +574,7 @@ public class ModelConverter {
 
     private static void convertRequirements(Component component, TopologyTemplate topologyTemplate) {
 
+        convertTopologyTemplateRequirements(component, topologyTemplate);
         if (component.getRequirements() != null && component.getComponentInstances() != null) {
             topologyTemplate.setCalculatedRequirements(new HashMap<>());
             for (ComponentInstance instance : component.getComponentInstances()) {
@@ -759,27 +824,13 @@ public class ModelConverter {
                     if (caps != null && !caps.isEmpty()) {
                                                List<CapabilityDataDefinition> capList = caps.stream().map(CapabilityDataDefinition::new).collect(Collectors.toList());
 
-                        ListCapabilityDataDefinition listCapabilityDataDefinition = new ListCapabilityDataDefinition(capList);
-                        toscaCapMap.put(s, listCapabilityDataDefinition);
-
-                        for (CapabilityDefinition cap : caps) {
-                            List<ComponentInstanceProperty> capPrps = cap.getProperties();
-                            if (capPrps != null && !capPrps.isEmpty()) {
-
-                                MapPropertiesDataDefinition dataToCreate = new MapPropertiesDataDefinition();
-                                for (ComponentInstanceProperty cip : capPrps) {
-                                    dataToCreate.put(cip.getName(), new PropertyDataDefinition(cip));
-                                }
-
-                                toscaCapPropMap.put(s + CAP_PROP_DELIM + cap.getName(), dataToCreate);
-                            }
-                        }
+                        populateCapabilityMap(toscaCapMap, toscaCapPropMap, s, caps, capList);
                     }
                 }
                        );
 
-            toscaElement.setCapabilties(toscaCapMap);
-            toscaElement.setCapabiltiesProperties(toscaCapPropMap);
+            toscaElement.setCapabilities(toscaCapMap);
+            toscaElement.setCapabilitiesProperties(toscaCapPropMap);
         }
     }
 
@@ -812,8 +863,8 @@ public class ModelConverter {
     }
 
     private static void convertCapabilities(NodeType toscaElement, Component component) {
-        Map<String, ListCapabilityDataDefinition> toscaCapabilities = toscaElement.getCapabilties();
-        Map<String, MapPropertiesDataDefinition> toscaCapPropMap = toscaElement.getCapabiltiesProperties();
+        Map<String, ListCapabilityDataDefinition> toscaCapabilities = toscaElement.getCapabilities();
+        Map<String, MapPropertiesDataDefinition> toscaCapPropMap = toscaElement.getCapabilitiesProperties();
 
         Map<String, List<CapabilityDefinition>> compCap = new HashMap<>();
         if (toscaCapabilities == null || toscaCapabilities.isEmpty())
@@ -1295,7 +1346,76 @@ public class ModelConverter {
         }
     }
 
-       private static void setCapabilitiesToComponentAndGroups(TopologyTemplate topologyTemplate, Component component) {
+    private static void setCapabilitiesToComponent(TopologyTemplate topologyTemplate, Component component) {
+        Map<String, ListCapabilityDataDefinition> capabilities = topologyTemplate.getCapabilities();
+        Map<String, List<CapabilityDefinition>> componentCapabilities = component.getCapabilities();
+        if(MapUtils.isNotEmpty(capabilities)) {
+            if(componentCapabilities == null) {
+                componentCapabilities = new HashMap<>();
+            }
+            componentCapabilities.putAll(groupCapabilityByType(capabilities));
+            component.setCapabilities(componentCapabilities);
+        }
+
+    }
+    private static Map<String, List<CapabilityDefinition>> groupCapabilityByType(Map<String,
+            ListCapabilityDataDefinition> capabilities) {
+        Map<String, List<CapabilityDefinition>>  groupedCapabilities = new HashMap<>();
+
+        Set<String> typesSet = new HashSet<>();
+        List<CapabilityDefinition> allCapabilityDefinitions = new ArrayList<>();
+        for (Entry<String, ListCapabilityDataDefinition> capabilitiesEntry : capabilities.entrySet()) {
+            typesSet.addAll( capabilitiesEntry.getValue().getListToscaDataDefinition()
+                    .stream().map(CapabilityDataDefinition::getType).collect(Collectors.toSet()));
+
+            allCapabilityDefinitions.addAll(capabilitiesEntry.getValue().getListToscaDataDefinition()
+                    .stream().map(CapabilityDefinition::new).collect(Collectors.toList()));
+        }
+
+        for(String capType : typesSet) {
+            groupedCapabilities.put(capType, allCapabilityDefinitions.stream()
+                    .filter(capabilityDefinition -> capabilityDefinition.getType()
+                            .equals(capType)).collect(Collectors.toList()));
+        }
+        return groupedCapabilities;
+    }
+
+    private static void setRequirementsToComponent(TopologyTemplate topologyTemplate, Component component) {
+        Map<String, ListRequirementDataDefinition> requirements = topologyTemplate.getRequirements();
+        Map<String, List<RequirementDefinition>> componentRequirements = component.getRequirements();
+        if(MapUtils.isNotEmpty(requirements)) {
+            if(componentRequirements == null) {
+                componentRequirements = new HashMap<>();
+            }
+            componentRequirements.putAll(groupRequirementByType(requirements));
+            component.setRequirements(componentRequirements);
+        }
+    }
+
+    private static Map<String, List<RequirementDefinition>> groupRequirementByType(Map<String,
+            ListRequirementDataDefinition> requirements) {
+        Map<String, List<RequirementDefinition>>  groupedRequirement = new HashMap<>();
+
+        Set<String> typesSet = new HashSet<>();
+        List<RequirementDefinition> allRequirements = new ArrayList<>();
+        for (Entry<String, ListRequirementDataDefinition> requirementsEntry : requirements.entrySet()) {
+            typesSet.addAll( requirementsEntry.getValue().getListToscaDataDefinition()
+                    .stream().map(RequirementDataDefinition::getCapability).collect(Collectors.toSet()));
+
+            allRequirements.addAll(requirementsEntry.getValue().getListToscaDataDefinition()
+                    .stream().map(RequirementDefinition::new).collect(Collectors.toList()));
+        }
+
+        for(String capType : typesSet) {
+            groupedRequirement.put(capType, allRequirements.stream().filter(requirementDefinition ->
+                    requirementDefinition.getCapability().equals(capType)).collect(Collectors.toList()));
+        }
+        return groupedRequirement;
+
+    }
+
+
+    private static void setCapabilitiesToComponentAndGroups(TopologyTemplate topologyTemplate, Component component) {
 
                Map<String, MapCapabilityProperty> calculatedCapProperties = topologyTemplate.getCalculatedCapabilitiesProperties();
 
index 7f8e07e..4316f73 100644 (file)
 package org.openecomp.sdc.be.model.operations.api;
 
 import fj.data.Either;
+import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
 import org.openecomp.sdc.be.model.CapabilityTypeDefinition;
 
+import java.util.Map;
+
 public interface ICapabilityTypeOperation {
 
     /**
@@ -43,4 +46,5 @@ public interface ICapabilityTypeOperation {
     public Either<CapabilityTypeDefinition, StorageOperationStatus> getCapabilityType(String uniqueId);
 
     public Either<CapabilityTypeDefinition, StorageOperationStatus> getCapabilityType(String uniqueId, boolean inTransaction);
+    Either<Map<String, CapabilityTypeDefinition>, TitanOperationStatus> getAllCapabilityTypes();
 }
index 97f3e80..3a4a272 100644 (file)
@@ -42,6 +42,7 @@ import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -58,6 +59,10 @@ public class CapabilityTypeOperation extends AbstractOperation implements ICapab
     }
 
     private static final Logger log = Logger.getLogger(CapabilityTypeOperation.class.getName());
+    private static final String DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Data type {} cannot be found in graph."
+            + " status is {}";
+    private static final String FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE = "Failed to fetch properties of data type {}";
+
 
     /**
      * FOR TEST ONLY
@@ -268,10 +273,15 @@ public class CapabilityTypeOperation extends AbstractOperation implements ICapab
         CapabilityTypeData ctData = capabilityTypesRes.left().value();
         CapabilityTypeDefinition capabilityTypeDefinition = new CapabilityTypeDefinition(ctData.getCapabilityTypeDataDefinition());
 
-        TitanOperationStatus propertiesStatus = fillProperties(uniqueId, capabilityTypeDefinition);
-        if (propertiesStatus != TitanOperationStatus.OK) {
+        Either<Map<String, PropertyDefinition>, TitanOperationStatus> propertiesStatus =
+                OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.CapabilityType);
+        if (propertiesStatus.isRight() && propertiesStatus.right().value() != TitanOperationStatus.OK) {
             log.error("Failed to fetch properties of capability type {}", uniqueId);
-            return Either.right(propertiesStatus);
+            return Either.right(propertiesStatus.right().value());
+        }
+
+        if (propertiesStatus.isLeft()) {
+            capabilityTypeDefinition.setProperties(propertiesStatus.left().value());
         }
 
         Either<ImmutablePair<CapabilityTypeData, GraphEdge>, TitanOperationStatus> parentNode = titanGenericDao.getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId, GraphEdgeLabels.DERIVED_FROM,
@@ -295,24 +305,6 @@ public class CapabilityTypeOperation extends AbstractOperation implements ICapab
         return result;
     }
 
-    private TitanOperationStatus fillProperties(String uniqueId, CapabilityTypeDefinition capabilityTypeDefinition) {
-
-        Either<Map<String, PropertyDefinition>, TitanOperationStatus> findPropertiesOfNode = propertyOperation.findPropertiesOfNode(NodeTypeEnum.CapabilityType, uniqueId);
-        if (findPropertiesOfNode.isRight()) {
-            TitanOperationStatus titanOperationStatus = findPropertiesOfNode.right().value();
-            log.debug("After looking for properties of vertex {}. status is {}", uniqueId, titanOperationStatus);
-            if (TitanOperationStatus.NOT_FOUND.equals(titanOperationStatus)) {
-                return TitanOperationStatus.OK;
-            } else {
-                return titanOperationStatus;
-            }
-        } else {
-            Map<String, PropertyDefinition> properties = findPropertiesOfNode.left().value();
-            capabilityTypeDefinition.setProperties(properties);
-            return TitanOperationStatus.OK;
-        }
-    }
-
     public Either<Boolean, StorageOperationStatus> isCapabilityTypeDerivedFrom(String childCandidateType, String parentCandidateType) {
         return derivedFromOperation.isTypeDerivedFrom(childCandidateType, parentCandidateType, null, NodeTypeEnum.CapabilityType, CapabilityTypeData.class, t -> t.getCapabilityTypeDataDefinition().getType());
     }
@@ -417,4 +409,107 @@ public class CapabilityTypeOperation extends AbstractOperation implements ICapab
     public Either<CapabilityTypeDefinition, StorageOperationStatus> getCapabilityType(String uniqueId) {
         return getCapabilityType(uniqueId, true);
     }
+    public Either<Map<String, CapabilityTypeDefinition>, TitanOperationStatus> getAllCapabilityTypes() {
+
+        Map<String, CapabilityTypeDefinition> capabilityTypes = new HashMap<>();
+        Either<Map<String, CapabilityTypeDefinition>, TitanOperationStatus> result = Either.left(capabilityTypes);
+
+        Either<List<CapabilityTypeData>, TitanOperationStatus> getAllCapabilityTypes =
+                titanGenericDao.getByCriteria(NodeTypeEnum.CapabilityType, null, CapabilityTypeData.class);
+        if (getAllCapabilityTypes.isRight()) {
+            TitanOperationStatus status = getAllCapabilityTypes.right().value();
+            if (status != TitanOperationStatus.NOT_FOUND) {
+                return Either.right(status);
+            } else {
+                return result;
+            }
+        }
+
+        List<CapabilityTypeData> list = getAllCapabilityTypes.left().value();
+        if (list != null) {
+
+            log.trace("Number of data types to load is {}", list.size());
+            //Set properties
+            for (CapabilityTypeData capabilityTypeData : list) {
+
+                log.trace("Going to fetch data type {}. uid is {}",
+                        capabilityTypeData.getCapabilityTypeDataDefinition().getType(),
+                        capabilityTypeData.getUniqueId());
+                Either<CapabilityTypeDefinition, TitanOperationStatus> capabilityTypesByUid =
+                        getAndAddPropertiesANdDerivedFrom(capabilityTypeData.getUniqueId(), capabilityTypes);
+                if (capabilityTypesByUid.isRight()) {
+                    TitanOperationStatus status = capabilityTypesByUid.right().value();
+                    if (status == TitanOperationStatus.NOT_FOUND) {
+                        status = TitanOperationStatus.INVALID_ID;
+                    }
+                    return Either.right(status);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    private void fillDerivedFrom(String uniqueId, CapabilityTypeDefinition capabilityType) {
+        log.debug("#fillDerivedFrom - fetching capability type {} derived node", capabilityType.getType());
+        derivedFromOperation.getDerivedFromChild(uniqueId, NodeTypeEnum.CapabilityType, CapabilityTypeData.class)
+                .right()
+                .bind(this::handleDerivedFromNotExist)
+                .left()
+                .map(derivedFrom -> setDerivedFrom(capabilityType, derivedFrom));
+
+    }
+
+    private Either<CapabilityTypeData, StorageOperationStatus> handleDerivedFromNotExist(StorageOperationStatus err) {
+        if (err == StorageOperationStatus.NOT_FOUND) {
+            return Either.left(null);
+        }
+        return Either.right(err);
+    }
+
+    private CapabilityTypeData setDerivedFrom(CapabilityTypeDefinition capabilityTypeDefinition, CapabilityTypeData derivedFrom) {
+        if (derivedFrom != null) {
+            capabilityTypeDefinition.setDerivedFrom(derivedFrom.getCapabilityTypeDataDefinition().getType());
+        }
+        return derivedFrom;
+    }
+
+    private Either<CapabilityTypeDefinition, TitanOperationStatus> getAndAddPropertiesANdDerivedFrom(
+            String uniqueId, Map<String, CapabilityTypeDefinition> capabilityTypeDefinitionMap) {
+        if (capabilityTypeDefinitionMap.containsKey(uniqueId)) {
+            return Either.left(capabilityTypeDefinitionMap.get(uniqueId));
+        }
+
+        Either<CapabilityTypeData, TitanOperationStatus> capabilityTypesRes =
+                titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.CapabilityType), uniqueId,
+                        CapabilityTypeData.class);
+
+        if (capabilityTypesRes.isRight()) {
+            TitanOperationStatus status = capabilityTypesRes.right().value();
+            log.debug(DATA_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
+            return Either.right(status);
+        }
+
+        CapabilityTypeData ctData = capabilityTypesRes.left().value();
+        CapabilityTypeDefinition capabilityTypeDefinition =
+                new CapabilityTypeDefinition(ctData.getCapabilityTypeDataDefinition());
+
+        Either<Map<String, PropertyDefinition>, TitanOperationStatus> propertiesStatus =
+                OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.CapabilityType);
+
+        if (propertiesStatus.isRight() && propertiesStatus.right().value() != TitanOperationStatus.OK) {
+            log.error(FAILED_TO_FETCH_PROPERTIES_OF_DATA_TYPE, uniqueId);
+            return Either.right(propertiesStatus.right().value());
+        }
+
+        if (propertiesStatus.isLeft()) {
+            capabilityTypeDefinition.setProperties(propertiesStatus.left().value());
+        }
+
+        fillDerivedFrom(uniqueId, capabilityTypeDefinition);
+
+        capabilityTypeDefinitionMap.put(capabilityTypeDefinition.getType(), capabilityTypeDefinition);
+
+        return Either.left(capabilityTypeDefinition);
+    }
 }
index dcaafe5..a06d342 100644 (file)
@@ -1,15 +1,23 @@
 package org.openecomp.sdc.be.model.operations.impl;
 
+import fj.data.Either;
 import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.operations.StorageException;
+import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.springframework.stereotype.Component;
 
+import java.util.Map;
+
 @Component
 public class OperationUtils {
 
     private final TitanDao titanDao;
 
+    private static final Logger logger = Logger.getLogger(OperationUtils.class.getName());
+
     public OperationUtils(TitanDao titanDao) {
         this.titanDao = titanDao;
     }
@@ -18,4 +26,23 @@ public class OperationUtils {
         titanDao.rollback();
         throw new StorageException(status);
     }
+
+    static Either<Map<String, PropertyDefinition>, TitanOperationStatus> fillProperties(String uniqueId,
+                                                                                        PropertyOperation propertyOperation,
+                                                                                        NodeTypeEnum nodeTypeEnum) {
+
+        Either<Map<String, PropertyDefinition>, TitanOperationStatus> findPropertiesOfNode =
+                propertyOperation.findPropertiesOfNode(nodeTypeEnum, uniqueId);
+        if (findPropertiesOfNode.isRight()) {
+            TitanOperationStatus titanOperationStatus = findPropertiesOfNode.right().value();
+            logger.debug("After looking for properties of vertex {}. status is {}", uniqueId, titanOperationStatus);
+            if (TitanOperationStatus.NOT_FOUND.equals(titanOperationStatus)) {
+                return Either.right(TitanOperationStatus.OK);
+            } else {
+                return Either.right(titanOperationStatus);
+            }
+        } else {
+            return Either.left(findPropertiesOfNode.left().value());
+        }
+    }
 }
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperation.java
new file mode 100644 (file)
index 0000000..13ad7a7
--- /dev/null
@@ -0,0 +1,513 @@
+package org.openecomp.sdc.be.model.operations.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import fj.data.Either;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openecomp.sdc.be.dao.graph.datatype.GraphEdge;
+import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
+import org.openecomp.sdc.be.dao.neo4j.GraphEdgeLabels;
+import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
+import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.resources.data.PropertyData;
+import org.openecomp.sdc.be.resources.data.RelationshipTypeData;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("relationship-type-operation")
+public class RelationshipTypeOperation extends AbstractOperation {
+
+    @Autowired
+    private PropertyOperation propertyOperation;
+
+    @Autowired
+    private DerivedFromOperation derivedFromOperation;
+
+    private static final Logger logger = Logger.getLogger(RelationshipTypeOperation.class.getName());
+    private static final String RELATIONSHIP_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS = "Relationship type {} cannot be "
+            + "found in "
+            + "graph status is {}";
+    private static final String FAILED_TO_FETCH_PROPERTIES_OF_RELATIONSHIP_TYPE = "Failed to fetch properties of "
+            + "relationship type {}";
+
+    public Either<RelationshipTypeDefinition, TitanOperationStatus> getRelationshipTypeByName(String name) {
+        String uid = UniqueIdBuilder.buildRelationshipTypeUid(name);
+        Either<RelationshipTypeDefinition, TitanOperationStatus> result = getRelationshipTypeByUid(uid);
+        if (result.isRight()) {
+            TitanOperationStatus status = result.right().value();
+            if (status != TitanOperationStatus.NOT_FOUND) {
+                logger.error("Failed to get information on relationship type {} status is {}", name, status);
+            }
+            return Either.right(status);
+        }
+        return Either.left(result.left().value());
+    }
+
+    public Either<RelationshipTypeDefinition, TitanOperationStatus> getRelationshipTypeByUid(String uniqueId) {
+
+        Either<RelationshipTypeDefinition, TitanOperationStatus> result;
+
+        Either<RelationshipTypeData, TitanOperationStatus> relationshipTypesRes =
+                titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(
+                        NodeTypeEnum.RelationshipType), uniqueId, RelationshipTypeData.class);
+
+        if (relationshipTypesRes.isRight()) {
+            TitanOperationStatus status = relationshipTypesRes.right().value();
+            logger.debug("Relationship type {} cannot be found in graph. status is {}", uniqueId, status);
+            return Either.right(status);
+        }
+
+        RelationshipTypeData relationshipTypeData = relationshipTypesRes.left().value();
+        RelationshipTypeDefinition relationshipTypeDefinition =
+                new RelationshipTypeDefinition(relationshipTypeData.getRelationshipTypeDataDefinition());
+
+        Either<Map<String, PropertyDefinition>, TitanOperationStatus> propertiesStatus =
+                OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.RelationshipType);
+        if (propertiesStatus.isRight() && propertiesStatus.right().value() != TitanOperationStatus.OK) {
+            logger.error("Failed to fetch properties of relationship type {}", uniqueId);
+            return Either.right(propertiesStatus.right().value());
+        }
+
+        if (propertiesStatus.isLeft()) {
+            relationshipTypeDefinition.setProperties(propertiesStatus.left().value());
+        }
+
+        Either<ImmutablePair<RelationshipTypeData, GraphEdge>, TitanOperationStatus> parentNode = titanGenericDao
+                .getChild(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipType), uniqueId,
+                        GraphEdgeLabels.DERIVED_FROM,
+                        NodeTypeEnum.RelationshipType, RelationshipTypeData.class);
+        logger.debug("After retrieving DERIVED_FROM node of {}. status is {}", uniqueId, parentNode);
+        if (parentNode.isRight()) {
+            TitanOperationStatus titanOperationStatus = parentNode.right().value();
+            if (titanOperationStatus != TitanOperationStatus.NOT_FOUND) {
+                logger.error("Failed to find the parent relationship of relationship type {}. status is {}", uniqueId,
+                        titanOperationStatus);
+                result = Either.right(titanOperationStatus);
+                return result;
+            }
+        } else {
+            // derived from node was found
+            ImmutablePair<RelationshipTypeData, GraphEdge> immutablePair = parentNode.left().value();
+            RelationshipTypeData parentCT = immutablePair.getKey();
+            relationshipTypeDefinition.setDerivedFrom(parentCT.getRelationshipTypeDataDefinition().getType());
+        }
+        result = Either.left(relationshipTypeDefinition);
+
+        return result;
+    }
+
+    private Either<RelationshipTypeDefinition, StorageOperationStatus> validateUpdateProperties(
+            RelationshipTypeDefinition relationshipTypeDefinition) {
+        TitanOperationStatus error = null;
+        if (MapUtils.isNotEmpty(relationshipTypeDefinition.getProperties())
+                && relationshipTypeDefinition.getDerivedFrom() != null) {
+            Either<Map<String, PropertyDefinition>, TitanOperationStatus> allPropertiesRes =
+                    getAllRelationshipTypePropertiesFromAllDerivedFrom(relationshipTypeDefinition.getDerivedFrom());
+            if (allPropertiesRes.isRight() && !TitanOperationStatus.NOT_FOUND.equals(allPropertiesRes.right().value())) {
+                error = allPropertiesRes.right().value();
+                logger.debug("Couldn't fetch derived from property nodes for relationship type {}, error: {}",
+                        relationshipTypeDefinition.getType(), error);
+            }
+            error = getTitanOperationStatus(relationshipTypeDefinition, error, allPropertiesRes);
+        }
+        if (error == null) {
+            return Either.left(relationshipTypeDefinition);
+        }
+        return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(error));
+    }
+
+    private TitanOperationStatus getTitanOperationStatus(RelationshipTypeDefinition relationshipTypeDefinition,
+                                                         TitanOperationStatus error,
+                                                         Either<Map<String, PropertyDefinition>, TitanOperationStatus> allPropertiesRes) {
+        if (error == null && !allPropertiesRes.left().value().isEmpty()) {
+            Map<String, PropertyDefinition> derivedFromProperties = allPropertiesRes.left().value();
+            relationshipTypeDefinition.getProperties().entrySet().stream()
+                    .filter(e -> derivedFromProperties.containsKey(e.getKey()) && e.getValue().getType() == null)
+                    .forEach(e -> e.getValue().setType(derivedFromProperties.get(e.getKey()).getType()));
+
+            List<PropertyDefinition>
+                    properties = new ArrayList<>(relationshipTypeDefinition.getProperties().values());
+            Either<List<PropertyDefinition>, TitanOperationStatus> validatePropertiesRes =
+                    propertyOperation.validatePropertiesUniqueness(allPropertiesRes.left().value(), properties);
+            if (validatePropertiesRes.isRight()) {
+                error = validatePropertiesRes.right().value();
+            }
+        }
+        return error;
+    }
+
+    private Either<Map<String, PropertyDefinition>, TitanOperationStatus> getAllRelationshipTypePropertiesFromAllDerivedFrom(
+            String firstParentType) {
+        return propertyOperation.getAllTypePropertiesFromAllDerivedFrom(firstParentType, NodeTypeEnum.RelationshipType,
+                RelationshipTypeData.class);
+    }
+
+    public Either<RelationshipTypeDefinition, StorageOperationStatus> addRelationshipType(
+            RelationshipTypeDefinition relationshipTypeDefinition,
+            boolean inTransaction) {
+
+        Either<RelationshipTypeDefinition, StorageOperationStatus> result = null;
+
+        try {
+            Either<RelationshipTypeDefinition, StorageOperationStatus> validationRes =
+                    validateUpdateProperties(relationshipTypeDefinition);
+            if (validationRes.isRight()) {
+                logger.error(
+                        "#addRelationshipType - One or all properties of relationship type {} not valid. status is {}"
+                        , relationshipTypeDefinition, validationRes.right().value());
+                return validationRes;
+            }
+
+            Either<RelationshipTypeData, StorageOperationStatus> eitherStatus =
+                    addRelationshipTypeToGraph(relationshipTypeDefinition);
+
+            result = eitherStatus.left()
+                    .map(RelationshipTypeData::getUniqueId)
+                    .left()
+                    .bind(uniqueId -> getRelationshipType(uniqueId, inTransaction));
+
+            if (result.isLeft()) {
+                logger.debug("#addRelationshipType - The returned RelationshipTypeDefinition is {}",
+                        result.left().value());
+            }
+
+            return result;
+        } finally {
+            if (!inTransaction) {
+                if (result == null || result.isRight()) {
+                    logger.error("#addRelationshipType - Going to execute rollback on graph.");
+                    titanGenericDao.rollback();
+                } else {
+                    logger.debug("#addRelationshipType - Going to execute commit on graph.");
+                    titanGenericDao.commit();
+                }
+            }
+        }
+    }
+
+    public Either<RelationshipTypeDefinition, StorageOperationStatus> getRelationshipType(String uniqueId,
+                                                                                          boolean inTransaction) {
+
+        Either<RelationshipTypeDefinition, StorageOperationStatus> result;
+        try {
+
+            Either<RelationshipTypeDefinition, TitanOperationStatus> ctResult = this.getRelationshipTypeByUid(uniqueId);
+
+            if (ctResult.isRight()) {
+                TitanOperationStatus status = ctResult.right().value();
+                if (status != TitanOperationStatus.NOT_FOUND) {
+                    logger.error("Failed to retrieve information on relationship type {}. status is {}", uniqueId,
+                            status);
+                }
+                result = Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(ctResult.right().value()));
+                return result;
+            }
+
+            result = Either.left(ctResult.left().value());
+
+            return result;
+        } finally {
+            if (!inTransaction) {
+                logger.debug("Going to execute commit on graph.");
+                titanGenericDao.commit();
+            }
+        }
+    }
+
+    private Either<RelationshipTypeData, StorageOperationStatus> addRelationshipTypeToGraph(
+            RelationshipTypeDefinition relationshipTypeDefinition) {
+
+        logger.debug("Got relationship type {}", relationshipTypeDefinition);
+
+        String ctUniqueId = UniqueIdBuilder.buildRelationshipTypeUid(relationshipTypeDefinition.getType());
+        RelationshipTypeData relationshipTypeData = buildRelationshipTypeData(relationshipTypeDefinition, ctUniqueId);
+
+        logger.debug("Before adding relationship type to graph. relationshipTypeData = {}", relationshipTypeData);
+        Either<RelationshipTypeData, TitanOperationStatus> createCTResult =
+                titanGenericDao.createNode(relationshipTypeData, RelationshipTypeData.class);
+        logger.debug("After adding relationship type to graph. status is = {}", createCTResult);
+
+        if (createCTResult.isRight()) {
+            TitanOperationStatus operationStatus = createCTResult.right().value();
+            logger.error("Failed to relationship type {} to graph. status is {}", relationshipTypeDefinition.getType(),
+                    operationStatus);
+            return Either.right(DaoStatusConverter.convertTitanStatusToStorageStatus(operationStatus));
+        }
+
+        RelationshipTypeData resultCTD = createCTResult.left().value();
+        Map<String, PropertyDefinition> propertiesMap = relationshipTypeDefinition.getProperties();
+        Either<Map<String, PropertyData>, TitanOperationStatus> addPropertiesToRelationshipType = propertyOperation
+                .addPropertiesToElementType(resultCTD.getUniqueId(), NodeTypeEnum.RelationshipType, propertiesMap);
+        if (addPropertiesToRelationshipType.isRight()) {
+            logger.error("Failed add properties {} to relationship {}", propertiesMap,
+                    relationshipTypeDefinition.getType());
+            return Either.right(DaoStatusConverter
+                    .convertTitanStatusToStorageStatus(addPropertiesToRelationshipType.right().value()));
+        }
+
+        return addDerivedFromRelation(relationshipTypeDefinition, ctUniqueId)
+                .left()
+                .map(updatedDerivedFrom -> createCTResult.left().value());
+
+
+    }
+
+    private RelationshipTypeData buildRelationshipTypeData(RelationshipTypeDefinition relationshipTypeDefinition,
+                                                           String ctUniqueId) {
+
+        RelationshipTypeData relationshipTypeData = new RelationshipTypeData(relationshipTypeDefinition);
+
+        relationshipTypeData.getRelationshipTypeDataDefinition().setUniqueId(ctUniqueId);
+        Long creationDate = relationshipTypeData.getRelationshipTypeDataDefinition().getCreationTime();
+        if (creationDate == null) {
+            creationDate = System.currentTimeMillis();
+        }
+        relationshipTypeData.getRelationshipTypeDataDefinition().setCreationTime(creationDate);
+        relationshipTypeData.getRelationshipTypeDataDefinition().setModificationTime(creationDate);
+        return relationshipTypeData;
+    }
+
+    private Either<GraphRelation, StorageOperationStatus> addDerivedFromRelation(
+            RelationshipTypeDefinition relationshipTypeDefinition,
+            String relationshipTypeUniqueId) {
+        String derivedFrom = relationshipTypeDefinition.getDerivedFrom();
+        if (derivedFrom == null) {
+            return Either.left(null);
+        }
+        logger.debug(
+                "#addDerivedFromRelation - adding derived from relation between relationship type {} to its parent "
+                        + "{}", relationshipTypeDefinition.getType(), derivedFrom);
+        return getRelationshipTypeByType(derivedFrom)
+                .right()
+                .map(DaoStatusConverter::convertTitanStatusToStorageStatus)
+                .left()
+                .bind(derivedFromRelationship -> derivedFromOperation.addDerivedFromRelation(relationshipTypeUniqueId,
+                        derivedFromRelationship.getUniqueId(), NodeTypeEnum.RelationshipType));
+    }
+
+    private Either<RelationshipTypeDefinition, TitanOperationStatus> getRelationshipTypeByType(
+            String relationshipType) {
+        // Optimization: In case of Relationship Type its unique ID is the same as type
+        return getRelationshipTypeByUid(relationshipType);
+    }
+
+    public Either<RelationshipTypeDefinition, StorageOperationStatus> updateRelationshipType(
+            RelationshipTypeDefinition newRelationshipTypeDefinition,
+            RelationshipTypeDefinition oldRelationshipTypeDefinition, boolean inTransaction) {
+        logger.debug("updating relationship type {}", newRelationshipTypeDefinition.getType());
+        Either<RelationshipTypeDefinition, StorageOperationStatus> updateRelationshipEither = null;
+
+        try {
+            updateRelationshipEither =
+                    updateRelationshipTypeOnGraph(newRelationshipTypeDefinition, oldRelationshipTypeDefinition);
+        } finally {
+            if (!inTransaction) {
+                if (updateRelationshipEither == null || updateRelationshipEither.isRight()) {
+                    titanGenericDao.rollback();
+                } else {
+                    titanGenericDao.commit();
+                }
+            }
+        }
+        return updateRelationshipEither;
+    }
+
+    private Either<RelationshipTypeDefinition, StorageOperationStatus> updateRelationshipTypeOnGraph(
+            RelationshipTypeDefinition newRelationshipTypeDefinition,
+            RelationshipTypeDefinition oldRelationshipTypeDefinition) {
+        updateRelationshipTypeData(newRelationshipTypeDefinition, oldRelationshipTypeDefinition);
+        return titanGenericDao
+                .updateNode(new RelationshipTypeData(newRelationshipTypeDefinition), RelationshipTypeData.class)
+                .right()
+                .map(DaoStatusConverter::convertTitanStatusToStorageStatus)
+                .left()
+                .bind(updatedNode -> updateRelationshipTypeProperties(newRelationshipTypeDefinition.getUniqueId(),
+                        newRelationshipTypeDefinition.getProperties()))
+                .left()
+                .bind(updatedProperties -> updateRelationshipTypeDerivedFrom(newRelationshipTypeDefinition,
+                        oldRelationshipTypeDefinition.getDerivedFrom()))
+                .left()
+                .map(updatedDerivedFrom -> newRelationshipTypeDefinition);
+    }
+
+    private Either<Map<String, PropertyData>, StorageOperationStatus> updateRelationshipTypeProperties(
+            String relationshipTypeId, Map<String, PropertyDefinition> properties) {
+        logger.debug(
+                "#updateRelationshipTypeProperties - updating relationship type properties for relationship type with "
+                        + "id {}", relationshipTypeId);
+        return propertyOperation.deletePropertiesAssociatedToNode(NodeTypeEnum.RelationshipType, relationshipTypeId)
+                .left()
+                .bind(deleteProps -> addPropertiesToRelationshipType(relationshipTypeId, properties));
+    }
+
+    private Either<GraphRelation, StorageOperationStatus> updateRelationshipTypeDerivedFrom(
+            RelationshipTypeDefinition newRelationshipTypeDefinition, String currDerivedFromRelationshipType) {
+        String relationshipTypeId = newRelationshipTypeDefinition.getUniqueId();
+        logger.debug(
+                "#updateRelationshipTypeDerivedFrom - updating relationship derived from relation for relationship "
+                        + "type with id {}. old derived type {}. new derived type {}", relationshipTypeId,
+                currDerivedFromRelationshipType, newRelationshipTypeDefinition.getDerivedFrom());
+        StorageOperationStatus deleteDerivedRelationStatus =
+                deleteDerivedFromRelationshipType(relationshipTypeId, currDerivedFromRelationshipType);
+        if (deleteDerivedRelationStatus != StorageOperationStatus.OK) {
+            return Either.right(deleteDerivedRelationStatus);
+        }
+        return addDerivedFromRelation(newRelationshipTypeDefinition, relationshipTypeId);
+    }
+
+    private void updateRelationshipTypeData(RelationshipTypeDefinition newRelationshipTypeDefinition,
+                                            RelationshipTypeDefinition oldRelationshipTypeDefinition) {
+        newRelationshipTypeDefinition.setUniqueId(oldRelationshipTypeDefinition.getUniqueId());
+        newRelationshipTypeDefinition.setCreationTime(oldRelationshipTypeDefinition.getCreationTime());
+        newRelationshipTypeDefinition.setModificationTime(System.currentTimeMillis());
+    }
+
+    private Either<Map<String, PropertyData>, StorageOperationStatus> addPropertiesToRelationshipType(
+            String relationshipTypeId, Map<String, PropertyDefinition> properties) {
+        logger.debug(
+                "#addPropertiesToRelationshipType - adding relationship type properties for relationship type with "
+                        + "id {}", relationshipTypeId);
+        return propertyOperation
+                .addPropertiesToElementType(relationshipTypeId, NodeTypeEnum.RelationshipType, properties)
+                .right()
+                .map(DaoStatusConverter::convertTitanStatusToStorageStatus);
+    }
+
+    private StorageOperationStatus deleteDerivedFromRelationshipType(String relationshipTypeId,
+                                                                     String derivedFromType) {
+        if (derivedFromType == null) {
+            return StorageOperationStatus.OK;
+        }
+        logger.debug("#deleteDerivedFromRelationshipType - deleting derivedFrom relation for relationship type with id "
+                + "{} and its derived type {}", relationshipTypeId, derivedFromType);
+        return getRelationshipTypeByType(derivedFromType)
+                .either(derivedFromNode -> derivedFromOperation
+                                .removeDerivedFromRelation(relationshipTypeId, derivedFromNode.getUniqueId(),
+                                        NodeTypeEnum.RelationshipType),
+                        DaoStatusConverter::convertTitanStatusToStorageStatus);
+    }
+
+    public Either<Map<String, RelationshipTypeDefinition>, TitanOperationStatus> getAllRelationshipTypes() {
+
+        Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap = new HashMap<>();
+        Either<Map<String, RelationshipTypeDefinition>, TitanOperationStatus> result = Either.left(relationshipTypeDefinitionMap);
+
+        Either<List<RelationshipTypeData>, TitanOperationStatus> getAllRelationshipTypes =
+                titanGenericDao.getByCriteria(NodeTypeEnum.RelationshipType, null, RelationshipTypeData.class);
+        if (getAllRelationshipTypes.isRight()) {
+            TitanOperationStatus status = getAllRelationshipTypes.right().value();
+            if (status != TitanOperationStatus.NOT_FOUND) {
+                return Either.right(status);
+            } else {
+                return result;
+            }
+        }
+
+        List<RelationshipTypeData> list = getAllRelationshipTypes.left().value();
+        if (list != null) {
+
+            logger.trace("Number of relationship types to load is {}", list.size());
+            //Set properties
+            Either<Map<String, RelationshipTypeDefinition>, TitanOperationStatus> status =
+                    getMapTitanOperationStatusEither(relationshipTypeDefinitionMap, list);
+            if (status != null) {
+                return status;
+            }
+        }
+
+        return result;
+    }
+
+    private Either<Map<String, RelationshipTypeDefinition>, TitanOperationStatus> getMapTitanOperationStatusEither(
+            Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap,
+            List<RelationshipTypeData> list) {
+        for (RelationshipTypeData relationshipTypeData : list) {
+
+            logger.trace("Going to fetch relationship type {}. uid is {}",
+                    relationshipTypeData.getRelationshipTypeDataDefinition().getType(),
+                    relationshipTypeData.getUniqueId());
+            Either<RelationshipTypeDefinition, TitanOperationStatus> relationshipTypesByUid =
+                    getAndAddPropertiesANdDerivedFrom(relationshipTypeData.getUniqueId(), relationshipTypeDefinitionMap);
+            if (relationshipTypesByUid.isRight()) {
+                TitanOperationStatus status = relationshipTypesByUid.right().value();
+                if (status == TitanOperationStatus.NOT_FOUND) {
+                    status = TitanOperationStatus.INVALID_ID;
+                }
+                return Either.right(status);
+            }
+        }
+        return null;
+    }
+
+    private Either<RelationshipTypeDefinition, TitanOperationStatus> getAndAddPropertiesANdDerivedFrom(
+            String uniqueId, Map<String, RelationshipTypeDefinition> relationshipTypeDefinitionMap) {
+        if (relationshipTypeDefinitionMap.containsKey(uniqueId)) {
+            return Either.left(relationshipTypeDefinitionMap.get(uniqueId));
+        }
+
+        Either<RelationshipTypeData, TitanOperationStatus> relationshipTypesRes =
+                titanGenericDao.getNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipType), uniqueId,
+                        RelationshipTypeData.class);
+
+        if (relationshipTypesRes.isRight()) {
+            TitanOperationStatus status = relationshipTypesRes.right().value();
+            logger.debug(RELATIONSHIP_TYPE_CANNOT_BE_FOUND_IN_GRAPH_STATUS_IS, uniqueId, status);
+            return Either.right(status);
+        }
+
+        RelationshipTypeData ctData = relationshipTypesRes.left().value();
+        RelationshipTypeDefinition relationshipTypeDefinition =
+                new RelationshipTypeDefinition(ctData.getRelationshipTypeDataDefinition());
+
+        Either<Map<String, PropertyDefinition>, TitanOperationStatus> propertiesStatus =
+                OperationUtils.fillProperties(uniqueId, propertyOperation, NodeTypeEnum.RelationshipType);
+        if (propertiesStatus.isRight() && propertiesStatus.right().value() != TitanOperationStatus.OK) {
+            logger.error(FAILED_TO_FETCH_PROPERTIES_OF_RELATIONSHIP_TYPE, uniqueId);
+            return Either.right(propertiesStatus.right().value());
+        }
+
+        if (propertiesStatus.isLeft()) {
+            relationshipTypeDefinition.setProperties(propertiesStatus.left().value());
+        }
+
+        fillDerivedFrom(uniqueId, relationshipTypeDefinition);
+
+        relationshipTypeDefinitionMap.put(relationshipTypeDefinition.getType(), relationshipTypeDefinition);
+
+        return Either.left(relationshipTypeDefinition);
+    }
+
+    private void fillDerivedFrom(String uniqueId,
+                                 RelationshipTypeDefinition relationshipType) {
+        logger.debug("#fillDerivedFrom - fetching relationship type {} derived node", relationshipType.getType());
+        derivedFromOperation.getDerivedFromChild(uniqueId, NodeTypeEnum.RelationshipType, RelationshipTypeData.class)
+                .right()
+                .bind(this::handleDerivedFromNotExist)
+                .left()
+                .map(derivedFrom -> setDerivedFrom(relationshipType, derivedFrom));
+
+    }
+
+    private Either<RelationshipTypeData, StorageOperationStatus> handleDerivedFromNotExist(StorageOperationStatus err) {
+        if (err == StorageOperationStatus.NOT_FOUND) {
+            return Either.left(null);
+        }
+        return Either.right(err);
+    }
+
+    private RelationshipTypeData setDerivedFrom(RelationshipTypeDefinition relationshipTypeDefinition, RelationshipTypeData derivedFrom) {
+        if (derivedFrom != null) {
+            relationshipTypeDefinition.setDerivedFrom(derivedFrom.getRelationshipTypeDataDefinition().getType());
+        }
+        return derivedFrom;
+    }
+}
index 058e9de..aa5ca81 100644 (file)
@@ -99,6 +99,10 @@ public class UniqueIdBuilder {
         return type;
     }
 
+    static String buildRelationshipTypeUid(String type) {
+        return type;
+    }
+
     public static String buildAttributeUid(String resourceId, String attName) {
         return buildTypeUid(NodeTypeEnum.Attribute.getName(), resourceId, attName);
     }
index 298cae0..e0e02ae 100644 (file)
@@ -71,6 +71,22 @@ public class TypeCompareUtils {
                SetUtils.isEqualSet(ct1.getValidSourceTypes(), ct2.getValidSourceTypes()) &&
                propertiesEquals(ct1.getProperties(), ct2.getProperties());
     }
+
+    public static boolean isRelationshipTypesEquals(RelationshipTypeDefinition rs1, RelationshipTypeDefinition rs2) {
+        if (rs1 == rs2) {
+            return true;
+        }
+
+        if (rs1 == null || rs2 == null) {
+            return false;
+        }
+
+        return Objects.equals(rs1.getType(), rs2.getType()) &&
+                Objects.equals(rs1.getDerivedFrom(), rs2.getDerivedFrom()) &&
+                Objects.equals(rs1.getDescription(), rs2.getDescription()) &&
+                SetUtils.isEqualSet(rs1.getValidSourceTypes(), rs2.getValidSourceTypes()) &&
+                propertiesEquals(rs1.getProperties(), rs2.getProperties());
+    }
     
     private static boolean propertiesEquals(Map<String, PropertyDefinition> props1, Map<String, PropertyDefinition> props2) {
         if (props1 == props2) {
index aae9d6f..493cb74 100644 (file)
@@ -91,7 +91,7 @@ public class NodeTypeTest {
 
                // default test
                testSubject = createTestSubject();
-               result = testSubject.getCapabilties();
+               result = testSubject.getCapabilities();
        }
 
        
@@ -102,7 +102,7 @@ public class NodeTypeTest {
 
                // default test
                testSubject = createTestSubject();
-               testSubject.setCapabilties(capabilties);
+               testSubject.setCapabilities(capabilties);
        }
 
        
@@ -135,7 +135,7 @@ public class NodeTypeTest {
 
                // default test
                testSubject = createTestSubject();
-               result = testSubject.getCapabiltiesProperties();
+               result = testSubject.getCapabilitiesProperties();
        }
 
        
@@ -146,7 +146,7 @@ public class NodeTypeTest {
 
                // default test
                testSubject = createTestSubject();
-               testSubject.setCapabiltiesProperties(capabiltiesProperties);
+               testSubject.setCapabilitiesProperties(capabiltiesProperties);
        }
 
        
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperationTest.java
new file mode 100644 (file)
index 0000000..6f8c7ea
--- /dev/null
@@ -0,0 +1,474 @@
+/*-
+ * ============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.model.operations.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import fj.data.Either;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.junit.Before;
+import org.junit.BeforeClass;
+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.Spy;
+import org.openecomp.sdc.be.dao.graph.datatype.GraphRelation;
+import org.openecomp.sdc.be.dao.titan.TitanGenericDao;
+import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
+import org.openecomp.sdc.be.datatypes.elements.RelationshipInstDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
+import org.openecomp.sdc.be.model.ModelTestBase;
+import org.openecomp.sdc.be.model.PropertyConstraint;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.RelationshipTypeDefinition;
+import org.openecomp.sdc.be.model.operations.api.DerivedFromOperation;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.tosca.ToscaType;
+import org.openecomp.sdc.be.model.tosca.constraints.GreaterThanConstraint;
+import org.openecomp.sdc.be.model.tosca.constraints.InRangeConstraint;
+import org.openecomp.sdc.be.model.tosca.constraints.LessOrEqualConstraint;
+import org.openecomp.sdc.be.resources.data.RelationshipTypeData;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("classpath:application-context-test.xml")
+public class RelationshipTypeOperationTest extends ModelTestBase {
+
+    private static final String PROP = "prop";
+
+    @Mock
+    TitanGenericDao titanGenericDao;
+
+    @Mock
+    PropertyOperation propertyOperation;
+
+    @Mock
+    DerivedFromOperation derivedFromOperation;
+
+    @InjectMocks
+    @Spy
+    private RelationshipTypeOperation relationshipTypeOperation;
+
+    private RelationshipTypeDefinition relationshipTypeDefinition = new RelationshipTypeDefinition();
+
+    {
+        relationshipTypeDefinition.setDescription("desc1");
+        relationshipTypeDefinition.setType("tosca.relationships.Container1");
+        relationshipTypeDefinition.setDerivedFrom("tosca.relationships.Root");
+        relationshipTypeDefinition.setProperties(createPropertyData("prop1"));
+        relationshipTypeDefinition.setUniqueId("tosca.relationships.Container1");
+    }
+
+    @BeforeClass
+    public static void setupBeforeClass() {
+        ModelTestBase.init();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        Mockito.doReturn(TitanOperationStatus.OK).when(titanGenericDao).commit();
+        Mockito.doReturn(TitanOperationStatus.OK).when(titanGenericDao).rollback();
+    }
+
+    @Test
+    public void getRelationshipTypeByNameNotCreated() {
+        Mockito.doReturn(Either.right(TitanOperationStatus.NOT_CREATED))
+                .when(relationshipTypeOperation).getRelationshipTypeByUid(Mockito.anyString());
+
+        Either<RelationshipTypeDefinition, TitanOperationStatus> either =
+                relationshipTypeOperation.getRelationshipTypeByName("name");
+        assertTrue(either.isRight());
+    }
+
+    @Test
+    public void testDummy() {
+        assertNotNull(relationshipTypeOperation);
+    }
+
+    @Test
+    public void testAddRelationshipTypeValidationFailStatusNullInTransactionFalse() {
+        Mockito.doReturn(Either.right(TitanOperationStatus.NOT_CONNECTED))
+                .when(propertyOperation)
+                .getAllTypePropertiesFromAllDerivedFrom(Mockito.anyString(), Mockito.any(), Mockito.any());
+
+
+        Either<RelationshipTypeDefinition, StorageOperationStatus> addRelationshipType =
+                relationshipTypeOperation.addRelationshipType(relationshipTypeDefinition, false);
+
+        assertTrue(addRelationshipType.isRight());
+    }
+
+    @Test
+    public void testAddRelationshipTypeValidationFailStatusPropertiesReturnedInTransactionFalse() {
+        Mockito.doReturn(Either.left(Collections.singletonMap("prop1", new PropertyDefinition()))).when(propertyOperation)
+                .getAllTypePropertiesFromAllDerivedFrom(Mockito.anyString(), Mockito.any(), Mockito.any());
+        Mockito.doReturn(Either.right(TitanOperationStatus.NOT_FOUND)).when(propertyOperation)
+                .validatePropertiesUniqueness(Mockito.any(), Mockito.any());
+
+        Either<RelationshipTypeDefinition, StorageOperationStatus> addRelationshipType =
+                relationshipTypeOperation.addRelationshipType(relationshipTypeDefinition, false);
+
+        assertTrue(addRelationshipType.isRight());
+    }
+
+    @Test
+    public void testGetAllRelationshipTypesNotFound() {
+        Mockito.doReturn(Either.right(TitanOperationStatus.NOT_FOUND)).when(titanGenericDao).getByCriteria(NodeTypeEnum.RelationshipType, null,
+                RelationshipTypeData.class);
+        Either<Map<String, RelationshipTypeDefinition>, TitanOperationStatus> either = relationshipTypeOperation.getAllRelationshipTypes();
+
+        assertTrue(either.isLeft() && MapUtils.isEmpty(either.left().value()));
+    }
+
+    @Test
+    public void testGetAllRelationshipTypesNotConnnected() {
+        Mockito.doReturn(Either.right(TitanOperationStatus.NOT_CONNECTED)).when(titanGenericDao).getByCriteria(NodeTypeEnum.RelationshipType, null,
+                RelationshipTypeData.class);
+        Either<Map<String, RelationshipTypeDefinition>, TitanOperationStatus> either = relationshipTypeOperation.getAllRelationshipTypes();
+
+        assertTrue(either.isRight() && TitanOperationStatus.NOT_CONNECTED == either.right().value());
+    }
+
+    @Test
+    public void testGetAllRelationshipTypesSuccess() {
+        List<RelationshipTypeData> relationshipTypeDataList = new ArrayList<>();
+
+        RelationshipTypeData relationshipTypeData1 = new RelationshipTypeData();
+        RelationshipInstDataDefinition relationshipInstDataDefinition1 = new RelationshipInstDataDefinition();
+        relationshipInstDataDefinition1.setUniqueId("tosca.relationships.Root1");
+        relationshipInstDataDefinition1.setType("tosca.relationships.Root1");
+        relationshipTypeData1.setRelationshipTypeDataDefinition(relationshipInstDataDefinition1);
+
+        relationshipTypeDataList.add(relationshipTypeData1);
+
+        Mockito.doReturn(Either.left(relationshipTypeDataList))
+                .when(titanGenericDao).getByCriteria(NodeTypeEnum.RelationshipType, null,
+                RelationshipTypeData.class);
+
+        Mockito.doReturn(Either.left(relationshipTypeData1)).when(titanGenericDao)
+                .getNode(Mockito.anyString(), Mockito.anyString(), Mockito.eq(RelationshipTypeData.class));
+
+        Mockito.doReturn(Either.left(createPropertyData("prop1"))).when(propertyOperation)
+                .findPropertiesOfNode(NodeTypeEnum.RelationshipType, "tosca.relationships.Root1");
+
+        RelationshipInstDataDefinition derivedFromRelationshipTypeDefinition = new RelationshipInstDataDefinition();
+        derivedFromRelationshipTypeDefinition.setUniqueId("tosca.relationships.Root1");
+        derivedFromRelationshipTypeDefinition.setType("tosca.relationships.Parent");
+
+        Mockito.doReturn(Either.left(new RelationshipTypeData(derivedFromRelationshipTypeDefinition)))
+                .when(derivedFromOperation)
+                .getDerivedFromChild("tosca.relationships.Root1", NodeTypeEnum.RelationshipType, RelationshipTypeData.class);
+
+        Either<Map<String, RelationshipTypeDefinition>, TitanOperationStatus> either =
+                                            relationshipTypeOperation.getAllRelationshipTypes();
+
+        assertTrue(either.isLeft());
+        RelationshipTypeDefinition relationshipTypeDefinition = either.left().value().get("tosca.relationships.Root1");
+        assertEquals("tosca.relationships.Parent", relationshipTypeDefinition.getDerivedFrom());
+    }
+
+    public RelationshipTypeDefinition createRelationship(String relationshipTypeName) {
+
+        RelationshipTypeDefinition relationshipTypeDefinition = new RelationshipTypeDefinition();
+        relationshipTypeDefinition.setDescription("desc1");
+        relationshipTypeDefinition.setType(relationshipTypeName);
+
+        Map<String, PropertyDefinition> properties = new HashMap<>();
+
+        String propName1 = "disk_size";
+        String propName2 = "num_cpus";
+
+        PropertyDefinition property1 = buildProperty1();
+
+        properties.put(propName1, property1);
+
+        PropertyDefinition property2 = buildProperty2();
+
+        properties.put(propName2, property2);
+
+        relationshipTypeDefinition.setProperties(properties);
+
+        Either<RelationshipTypeDefinition, StorageOperationStatus> addRelationshipType1 =
+                relationshipTypeOperation.addRelationshipType(relationshipTypeDefinition, true);
+
+        RelationshipTypeDefinition relationshipTypeDefinitionCreated = addRelationshipType1.left().value();
+        Either<RelationshipTypeDefinition, StorageOperationStatus> relationshipType =
+                relationshipTypeOperation.getRelationshipType(relationshipTypeDefinitionCreated.getUniqueId(), true);
+        assertTrue("check relationship type fetched", relationshipType.isLeft());
+        RelationshipTypeDefinition fetchedCTD = relationshipType.left().value();
+
+        Map<String, PropertyDefinition> fetchedProps = fetchedCTD.getProperties();
+
+        compareProperties(fetchedProps, properties);
+
+        return fetchedCTD;
+
+    }
+
+    private void compareProperties(Map<String, PropertyDefinition> first, Map<String, PropertyDefinition> second) {
+
+        assertTrue("check properties are full or empty",
+                ((first == null && second == null) || (first != null && second != null)));
+        if (first != null) {
+            assertEquals("check properties size", first.size(), second.size());
+
+            for (Entry<String, PropertyDefinition> entry : first.entrySet()) {
+
+                String propName = entry.getKey();
+                PropertyDefinition secondPD = second.get(propName);
+                assertNotNull("Cannot find property " + propName + " in " + second, secondPD);
+
+                PropertyDefinition firstPD = entry.getValue();
+
+                comparePropertyDefinition(firstPD, secondPD);
+            }
+
+        }
+
+    }
+
+    private void comparePropertyDefinition(PropertyDefinition first, PropertyDefinition second) {
+
+        assertTrue("check objects are full or empty",
+                ((first == null && second == null) || (first != null && second != null)));
+        if (first != null) {
+            assertTrue("check property description", compareValue(first.getDescription(), second.getDescription()));
+            assertTrue("check property default value", compareValue((String) first.getDefaultValue(),
+                    (String) second.getDefaultValue()));
+            assertTrue("check property type", compareValue(first.getType(), second.getType()));
+            compareList(first.getConstraints(), second.getConstraints());
+        }
+
+    }
+
+    private void compareList(List<PropertyConstraint> first, List<PropertyConstraint> second) {
+
+        assertTrue("check lists are full or empty",
+                ((first == null && second == null) || (first != null && second != null)));
+        if (first != null) {
+            assertEquals("check list size", first.size(), second.size());
+        }
+    }
+
+    private PropertyDefinition buildProperty2() {
+        PropertyDefinition property2 = new PropertyDefinition();
+        property2.setDefaultValue("2");
+        property2.setDescription("Number of (actual or virtual) CPUs associated with the Compute node.");
+        property2.setType(ToscaType.INTEGER.name().toLowerCase());
+        List<PropertyConstraint> constraints3 = new ArrayList<>();
+        List<String> range = new ArrayList<>();
+        range.add("4");
+        range.add("1");
+        InRangeConstraint propertyConstraint3 = new InRangeConstraint(range);
+        constraints3.add(propertyConstraint3);
+        property2.setConstraints(constraints3);
+        return property2;
+    }
+
+    private PropertyDefinition buildProperty1() {
+        PropertyDefinition property1 = new PropertyDefinition();
+        property1.setDefaultValue("10");
+        property1.setDescription("Size of the local disk, in Gigabytes (GB), "
+                + "available to applications running on the Compute node.");
+        property1.setType(ToscaType.INTEGER.name().toLowerCase());
+        List<PropertyConstraint> constraints = new ArrayList<>();
+        GreaterThanConstraint propertyConstraint1 = new GreaterThanConstraint("0");
+        constraints.add(propertyConstraint1);
+
+        LessOrEqualConstraint propertyConstraint2 = new LessOrEqualConstraint("10");
+        constraints.add(propertyConstraint2);
+
+        property1.setConstraints(constraints);
+        return property1;
+    }
+
+    private boolean compareValue(String first, String second) {
+
+        if (first == null && second == null) {
+            return true;
+        }
+        if (first != null) {
+            return first.equals(second);
+        } else {
+            return false;
+        }
+    }
+
+    public void setOperations(RelationshipTypeOperation relationshipTypeOperation) {
+        this.relationshipTypeOperation = relationshipTypeOperation;
+    }
+
+    @Test
+    public void testAddRelationshipType() {
+
+        RelationshipTypeData relationshipTypeData = new RelationshipTypeData();
+        RelationshipInstDataDefinition relationshipInstDataDefinition1 = new RelationshipInstDataDefinition();
+        relationshipInstDataDefinition1.setUniqueId("tosca.relationships.Root");
+        relationshipInstDataDefinition1.setType("tosca.relationships.Root");
+        relationshipTypeData.setRelationshipTypeDataDefinition(relationshipInstDataDefinition1);
+
+        RelationshipTypeDefinition relationshipTypeDefinition = new RelationshipTypeDefinition(relationshipTypeData);
+        relationshipTypeDefinition.setProperties(createPropertyData("prop1"));
+        relationshipTypeDefinition.setDerivedFrom("tosca.relationships.Root");
+
+        Mockito.doReturn(Either.left(Collections.singletonMap("prop1", new PropertyDefinition()))).when(propertyOperation)
+                .getAllTypePropertiesFromAllDerivedFrom(Mockito.anyString(), Mockito.any(), Mockito.any());
+
+        Mockito.doReturn(Either.left(new ArrayList<>(relationshipTypeDefinition.getProperties().values()))).when(propertyOperation)
+                .validatePropertiesUniqueness(Mockito.any(), Mockito.any());
+
+        Mockito.doReturn(Either.left(relationshipTypeData)).when(titanGenericDao)
+                .createNode(Mockito.any(), Mockito.eq(RelationshipTypeData.class));
+
+        Mockito.doReturn(Either.left(new HashMap())).when(propertyOperation)
+                .addPropertiesToElementType(Mockito.anyString(), Mockito.any(), Mockito.anyMap());
+
+        Mockito.doReturn(Either.left(relationshipTypeDefinition))
+                .when(relationshipTypeOperation).getRelationshipTypeByUid(Mockito.anyString());
+
+        Mockito.doReturn(Either.left(new GraphRelation()))
+                .when(derivedFromOperation)
+                .addDerivedFromRelation(Mockito.anyString(), Mockito.anyString(), Mockito.any());
+
+        Mockito.doReturn(Either.left(relationshipTypeDefinition))
+                .when(relationshipTypeOperation).getRelationshipType(Mockito.anyString(), Mockito.anyBoolean());
+
+        Either<RelationshipTypeDefinition, StorageOperationStatus> either =
+                relationshipTypeOperation.addRelationshipType(relationshipTypeDefinition, true);
+
+        assertTrue(either.isLeft());
+    }
+
+    @Test
+    public void testGetRelationshipTypeNotConnected() {
+        Mockito.doReturn(Either.right(TitanOperationStatus.NOT_CONNECTED))
+                .when(relationshipTypeOperation).getRelationshipTypeByUid(Mockito.anyString());
+
+        Either<RelationshipTypeDefinition, StorageOperationStatus> either =
+                relationshipTypeOperation.getRelationshipType(Mockito.anyString(), Mockito.anyBoolean());
+
+        assertTrue(either.isRight());
+    }
+
+    @Test
+    public void testGetRelationshipTypeSuccess() {
+        Mockito.doReturn(Either.left(relationshipTypeDefinition))
+                .when(relationshipTypeOperation).getRelationshipTypeByUid(Mockito.anyString());
+
+        Either<RelationshipTypeDefinition, StorageOperationStatus> either =
+                relationshipTypeOperation.getRelationshipType(Mockito.anyString(), Mockito.anyBoolean());
+
+        assertTrue(either.isLeft());
+    }
+
+    @Test
+    public void testUpdateRelationshipType() {
+        RelationshipTypeDefinition newRelationshipTypeDefinition = new RelationshipTypeDefinition();
+        newRelationshipTypeDefinition.setUniqueId("tosca.relationships.Container2");
+        newRelationshipTypeDefinition.setDescription("desc2");
+        newRelationshipTypeDefinition.setType("tosca.relationships.Container2");
+        newRelationshipTypeDefinition.setDerivedFrom("tosca.relationships.Root");
+        newRelationshipTypeDefinition.setProperties(createPropertyData("prop1"));
+
+        Mockito.doReturn(Either.left(new RelationshipTypeData(newRelationshipTypeDefinition))).when(titanGenericDao)
+                .updateNode(Mockito.any(), Mockito.eq(RelationshipTypeData.class));
+
+        Mockito.doReturn(Either.left(newRelationshipTypeDefinition.getProperties()))
+                .when(propertyOperation).deletePropertiesAssociatedToNode(Mockito.any(), Mockito.anyString());
+
+        Mockito.doReturn(Either.left(newRelationshipTypeDefinition.getProperties()))
+                .when(propertyOperation).addPropertiesToElementType(Mockito.anyString(), Mockito.any(), Mockito.anyMap());
+
+        Mockito.doReturn(Either.left(newRelationshipTypeDefinition)).when(relationshipTypeOperation)
+                .getRelationshipTypeByUid(Mockito.anyString());
+
+        Mockito.doReturn(StorageOperationStatus.OK).when(derivedFromOperation)
+                .removeDerivedFromRelation(Mockito.anyString(), Mockito.anyString(), Mockito.any());
+
+        Mockito.doReturn(Either.left(new GraphRelation()))
+                .when(derivedFromOperation)
+                .addDerivedFromRelation(Mockito.anyString(), Mockito.anyString(), Mockito.any());
+
+        Either<RelationshipTypeDefinition, StorageOperationStatus> either =
+                relationshipTypeOperation.updateRelationshipType(relationshipTypeDefinition,
+                        newRelationshipTypeDefinition, false);
+
+        assertTrue(either.isLeft());
+    }
+
+    @Test
+    public void testGetRelationshipTypeByUid() {
+        RelationshipTypeData relationshipTypeData = new RelationshipTypeData(relationshipTypeDefinition);
+
+        Mockito.doReturn(Either.left(relationshipTypeData)).when(titanGenericDao)
+                .getNode(Mockito.anyString(), Mockito.any(), Mockito.eq(RelationshipTypeData.class));
+
+        Mockito.doReturn(Either.left(relationshipTypeDefinition.getProperties()))
+                .when(propertyOperation).findPropertiesOfNode(Mockito.any(), Mockito.anyString());
+
+        RelationshipTypeDefinition childRelationshipTypeDefinition = new RelationshipTypeDefinition();
+        childRelationshipTypeDefinition.setType("tosca.relationships.ContainerChild");
+
+        Mockito.doReturn(Either.left(new ImmutablePair(new RelationshipTypeData(childRelationshipTypeDefinition), null))).when(titanGenericDao)
+                .getChild(Mockito.anyString(), Mockito.anyString(), Mockito.any(), Mockito.any(),
+                        Mockito.eq(RelationshipTypeData.class));
+
+        Either<RelationshipTypeDefinition, TitanOperationStatus> either =
+                relationshipTypeOperation.getRelationshipTypeByUid("tosca.relationships.Container1");
+
+        assertTrue(either.isLeft()
+                && "tosca.relationships.ContainerChild".equals(either.left().value().getDerivedFrom()));
+    }
+
+    private Map<String, PropertyDefinition> createPropertyData(String value) {
+        PropertyDefinition propertyDefinition = new PropertyDefinition();
+        propertyDefinition.setDefaultValue(value);
+        propertyDefinition.setDescription(PROP + "_" + value);
+        propertyDefinition.setType(ToscaType.INTEGER.name().toLowerCase());
+        List<PropertyConstraint> constraints = new ArrayList<>();
+        List<String> range = new ArrayList<>();
+        range.add("1");
+        range.add("4");
+        InRangeConstraint propertyConstraint = new InRangeConstraint(range);
+        constraints.add(propertyConstraint);
+        propertyDefinition.setConstraints(constraints);
+        Map<String, PropertyDefinition> propertiesMap = new HashMap<>();
+        propertiesMap.put(PROP, propertyDefinition);
+        return propertiesMap;
+    }
+
+}
index 88bb514..c70e41b 100644 (file)
@@ -59,10 +59,6 @@ import org.openecomp.sdc.common.util.ValidationUtils;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
 import java.util.*;
 
 import static org.junit.Assert.assertEquals;
@@ -147,7 +143,7 @@ public class ToscaElementLifecycleOperationTest extends ModelTestBase {
         cap1.setDescription("create");
         cap1.setUniqueId(UniqueIdBuilder.buildCapabilityUid(id, "cap1"));
 
-        status = nodeTypeOperation.addToscaDataToToscaElement(id, EdgeLabelEnum.CAPABILITIES, VertexTypeEnum.CAPABILTIES, cap1, JsonPresentationFields.NAME);
+        status = nodeTypeOperation.addToscaDataToToscaElement(id, EdgeLabelEnum.CAPABILITIES, VertexTypeEnum.CAPABILITIES, cap1, JsonPresentationFields.NAME);
         assertSame(status, StorageOperationStatus.OK);
 
         res = lifecycleOperation.checkinToscaELement(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT, id, ownerVertex.getUniqueId(), ownerVertex.getUniqueId());
@@ -164,7 +160,7 @@ public class ToscaElementLifecycleOperationTest extends ModelTestBase {
 
         cap1.setDescription("update");
 
-        status = nodeTypeOperation.updateToscaDataOfToscaElement(id, EdgeLabelEnum.CAPABILITIES, VertexTypeEnum.CAPABILTIES, cap1, JsonPresentationFields.NAME);
+        status = nodeTypeOperation.updateToscaDataOfToscaElement(id, EdgeLabelEnum.CAPABILITIES, VertexTypeEnum.CAPABILITIES, cap1, JsonPresentationFields.NAME);
         assertSame(status, StorageOperationStatus.OK);
 
         PropertyDataDefinition prop66 = new PropertyDataDefinition();
index fdd1386..2612e6f 100644 (file)
@@ -32,7 +32,7 @@ import java.util.List;
  */
 public class CapabilityDataDefinition extends ToscaDataDefinition {
 
-    public static final String MIN_OCCURRENCES = "1";
+    public static final String MIN_OCCURRENCES = "0";
     public static final String MAX_OCCURRENCES = "UNBOUNDED";
 
     /**
index 72d9c36..2f995fd 100644 (file)
@@ -32,6 +32,7 @@ public class RelationshipInstDataDefinition extends ToscaDataDefinition {
                this.setDescription(cdt.getDescription());
                this.setType(cdt.getType());
                this.setValidSourceTypes(cdt.getValidSourceTypes());
+               this.setValidTargetTypes(cdt.getValidTargetTypes());
                this.setVersion(cdt.getVersion());
                this.setOriginUI(cdt.isOriginUI());
                this.setCreationTime(cdt.getCreationTime());
@@ -54,11 +55,11 @@ public class RelationshipInstDataDefinition extends ToscaDataDefinition {
                return (String) getToscaPresentationValue(JsonPresentationFields.REQUIREMENT);
        }
        public void setCapability(String capability) {
-               setToscaPresentationValue(JsonPresentationFields.CAPAPILITY, capability);
+               setToscaPresentationValue(JsonPresentationFields.CAPABILITY, capability);
        }
 
        public String getCapability() {
-               return (String) getToscaPresentationValue(JsonPresentationFields.CAPAPILITY);
+               return (String) getToscaPresentationValue(JsonPresentationFields.CAPABILITY);
        }
        public void setToId(Object toId) {
                setToscaPresentationValue(JsonPresentationFields.TO_ID, toId);
@@ -144,6 +145,14 @@ public class RelationshipInstDataDefinition extends ToscaDataDefinition {
                setToscaPresentationValue(JsonPresentationFields.VALID_SOURCE_TYPES, validSourceTypes);
        }
 
+       public List<String> getValidTargetTypes() {
+               return (List<String>) getToscaPresentationValue(JsonPresentationFields.VALID_TARGET_TYPES);
+       }
+
+       public void setValidTargetTypes(List<String> validTargetTypes) {
+               setToscaPresentationValue(JsonPresentationFields.VALID_TARGET_TYPES, validTargetTypes);
+       }
+
        public String getVersion() {
                return (String) getToscaPresentationValue(JsonPresentationFields.VERSION);
        }
index 4ede93e..0df5ba5 100644 (file)
@@ -31,7 +31,7 @@ import java.util.List;
  */
 public class RequirementDataDefinition extends ToscaDataDefinition {
 
-       public static final String MIN_OCCURRENCES = "1";
+       public static final String MIN_OCCURRENCES = "0";
        public static final String MAX_OCCURRENCES = "UNBOUNDED";
        public static final String MAX_DEFAULT_OCCURRENCES = "1";
 
@@ -107,11 +107,11 @@ public class RequirementDataDefinition extends ToscaDataDefinition {
         */
 
        public String getCapability() {
-               return (String) getToscaPresentationValue(JsonPresentationFields.CAPAPILITY);
+               return (String) getToscaPresentationValue(JsonPresentationFields.CAPABILITY);
        }
 
        public void setCapability(String capability) {
-               setToscaPresentationValue(JsonPresentationFields.CAPAPILITY, capability);
+               setToscaPresentationValue(JsonPresentationFields.CAPABILITY, capability);
        }
 
        /**
index 7a4c3d4..a72984a 100644 (file)
@@ -129,10 +129,11 @@ public enum JsonPresentationFields {
     SOURCE("source", null),
 
     //Requirement
-    CAPAPILITY("capability", null),
+    CAPABILITY("capability", null),
     NODE("node", null),
     RELATIONSHIP("relationship", null),
     VALID_SOURCE_TYPES("validSourceTypes", null),
+    VALID_TARGET_TYPES("validTargetTypes", null),
     REQUIREMENT_ID("requirementId", null),
     PARENT_NAME("parentName", null),
     PREVIOUS_NAME("previousName", null),
index ba35ac3..1f1c907 100644 (file)
@@ -408,4 +408,16 @@ public interface Urls {
        final String UPDATE_INTERFACE_OPERATIONS = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/interfaceOperations";
        final String GET_INTERFACE_OPERATIONS = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/interfaces/%s/operations/%s";
        final String DELETE_INTERFACE_OPERATIONS = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/interfaces/%s/operations/%s";
+
+       //Requirements
+       String CREATE_REQUIREMENT = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/requirements";
+       String UPDATE_REQUIREMENT = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/requirements";
+       String DELETE_REQUIREMENT = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/requirements/%s";
+       String GET_REQUIREMENT = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/requirements/%s";
+       //Capabilities
+       String CREATE_CAPABILITY = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/capabilities";
+       String UPDATE_CAPABILITY = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/capabilities";
+       String DELETE_CAPABILITY = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/capabilities/%s";
+       String GET_CAPABILITY = SDC_HTTP_METHOD + "://%s:%s/sdc2/rest/v1/catalog/%s/%s/capabilities/%s";
+
 }
diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/capability/CapabilitiesTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/capability/CapabilitiesTest.java
new file mode 100644 (file)
index 0000000..ecdb486
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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.ci.tests.capability;
+
+import org.junit.Rule;
+import org.junit.rules.TestName;
+import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.ci.tests.api.ComponentBaseTest;
+import org.openecomp.sdc.ci.tests.datatypes.CapabilityDetails;
+import org.openecomp.sdc.ci.tests.datatypes.ServiceReqDetails;
+import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum;
+import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse;
+import org.openecomp.sdc.ci.tests.utils.general.ElementFactory;
+import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils;
+import org.openecomp.sdc.ci.tests.utils.rest.CapabilityRestUtils;
+import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils.getServiceObject;
+
+public class CapabilitiesTest extends ComponentBaseTest {
+    @Rule
+    public static final TestName name = new TestName();
+
+    private  ServiceReqDetails component;
+    private  User user = null;
+
+    public CapabilitiesTest() {
+        super(name, CapabilitiesTest.class.getName());
+    }
+
+    @BeforeTest
+    public void init() throws Exception {
+        user = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER);
+        component = ElementFactory.getDefaultService();
+        component.setName("comp_cap" + Math.random());
+        ServiceRestUtils.createService(component, user);
+    }
+
+    @Test
+    public void createCapabilityTest() throws Exception {
+
+        CapabilityDetails capability = createCapability();
+        RestResponse restResponse = CapabilityRestUtils.createCapability(component.getUniqueId(),
+                Collections.singletonList(capability), user);
+        logger.info("createCapability Response Code:" + restResponse.getErrorCode());
+        Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS);
+    }
+
+
+
+    @Test(dependsOnMethods = "createCapabilityTest")
+    public void updateCapabilityTest() throws Exception {
+
+        CapabilityDetails capability = createCapability();
+        capability.setMaxOccurrences("10");
+        capability.setMinOccurrences("4");
+        RestResponse restResponse = CapabilityRestUtils.updateCapability(component.getUniqueId(),
+                Collections.singletonList(capability), user);
+        logger.info("updateCapability Response Code:" + restResponse.getErrorCode());
+        Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS);
+    }
+
+    @Test(dependsOnMethods = "updateCapabilityTest")
+    public void getCapabilityTest() throws Exception {
+        Service service = getServiceObject(component.getUniqueId());
+
+        List<org.openecomp.sdc.be.model.CapabilityDefinition> capabilityDefinitionList = service.getCapabilities().values()
+                .stream().flatMap(Collection::stream).collect(Collectors.toList());
+
+        RestResponse restResponse = CapabilityRestUtils.getCapability(component.getUniqueId(),
+                capabilityDefinitionList.get(0).getUniqueId(),  user);
+        logger.info("getCapabilityTest Response Code:" + restResponse.getErrorCode());
+        Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS);
+    }
+
+    @Test(dependsOnMethods = "getCapabilityTest")
+    public void deleteCapabilityTest() throws Exception {
+        Service service = getServiceObject(component.getUniqueId());
+
+        List<org.openecomp.sdc.be.model.CapabilityDefinition> capabilityDefinitionList = service.getCapabilities().values()
+                .stream().flatMap(Collection::stream).collect(Collectors.toList());
+
+        RestResponse restResponse = CapabilityRestUtils.deleteCapability(component.getUniqueId(),
+                capabilityDefinitionList.get(0).getUniqueId(),  user);
+        logger.info("deleteCapabilityTest Response Code:" + restResponse.getErrorCode());
+        Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS);
+    }
+
+    private  CapabilityDetails createCapability() {
+        CapabilityDetails  capabilityDetails = new CapabilityDetails();
+        capabilityDetails.setName("cap" + Math.random());
+        capabilityDetails.setType("tosca.capabilities.network.Bindable");
+
+        return capabilityDetails;
+    }
+}
diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/CapabilityDetails.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/CapabilityDetails.java
new file mode 100644 (file)
index 0000000..954a16a
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.ci.tests.datatypes;
+
+public class CapabilityDetails {
+    private String name;
+    private String type;
+    private String maxOccurrences;
+    private String minOccurrences;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getMaxOccurrences() {
+        return maxOccurrences;
+    }
+
+    public void setMaxOccurrences(String maxOccurrences) {
+        this.maxOccurrences = maxOccurrences;
+    }
+
+    public String getMinOccurrences() {
+        return minOccurrences;
+    }
+
+    public void setMinOccurrences(String minOccurrences) {
+        this.minOccurrences = minOccurrences;
+    }
+}
diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/RequirementDetails.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/datatypes/RequirementDetails.java
new file mode 100644 (file)
index 0000000..a720786
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.ci.tests.datatypes;
+
+public class RequirementDetails {
+    private String capability;
+    private String name;
+    private String node;
+    private String relationship;
+    private String maxOccurrences;
+    private String minOccurrences;
+
+    public String getCapability() {
+        return capability;
+    }
+
+    public void setCapability(String capability) {
+        this.capability = capability;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getNode() {
+        return node;
+    }
+
+    public void setNode(String node) {
+        this.node = node;
+    }
+
+    public String getRelationship() {
+        return relationship;
+    }
+
+    public void setRelationship(String relationship) {
+        this.relationship = relationship;
+    }
+
+    public String getMaxOccurrences() {
+        return maxOccurrences;
+    }
+
+    public void setMaxOccurrences(String maxOccurrences) {
+        this.maxOccurrences = maxOccurrences;
+    }
+
+    public String getMinOccurrences() {
+        return minOccurrences;
+    }
+
+    public void setMinOccurrences(String minOccurrences) {
+        this.minOccurrences = minOccurrences;
+    }
+}
diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/requirements/RequirementsTest.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/requirements/RequirementsTest.java
new file mode 100644 (file)
index 0000000..51894e7
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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.ci.tests.requirements;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+import org.openecomp.sdc.be.model.RequirementDefinition;
+import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.ci.tests.api.ComponentBaseTest;
+import org.openecomp.sdc.ci.tests.datatypes.RequirementDetails;
+import org.openecomp.sdc.ci.tests.datatypes.ServiceReqDetails;
+import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum;
+import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse;
+import org.openecomp.sdc.ci.tests.utils.general.ElementFactory;
+import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils;
+import org.openecomp.sdc.ci.tests.utils.rest.RequirementsUtils;
+import org.openecomp.sdc.ci.tests.utils.rest.ServiceRestUtils;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.openecomp.sdc.ci.tests.utils.general.AtomicOperationUtils.getServiceObject;
+
+public class RequirementsTest extends ComponentBaseTest {
+    @Rule
+    public static final TestName name = new TestName();
+
+    private  ServiceReqDetails component;
+    private  User user = null;
+
+    public RequirementsTest() {
+        super(name, RequirementsTest.class.getName());
+    }
+
+    @BeforeTest
+    public void init() throws Exception {
+        user = ElementFactory.getDefaultUser(UserRoleEnum.DESIGNER);
+        component = ElementFactory.getDefaultService();
+        component.setName("comp_req" + Math.random());
+        ServiceRestUtils.createService(component, user);
+    }
+
+    @Test
+    public void createRequirementTest() throws Exception {
+
+        RequirementDetails requirement = createRequirement();
+        RestResponse restResponse = RequirementsUtils.createRequirement(component.getUniqueId(),
+                Collections.singletonList(requirement), user);
+        logger.info("createRequirement Response Code:" + restResponse.getErrorCode());
+        Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS);
+    }
+
+    @Test(dependsOnMethods = "createRequirementTest")
+    public void updateRequirementTest() throws Exception {
+
+        RequirementDetails requirement = createRequirement();
+        requirement.setMaxOccurrences("10");
+        requirement.setMinOccurrences("4");
+        RestResponse restResponse = RequirementsUtils.updateRequirement(component.getUniqueId(),
+                Collections.singletonList(requirement), user);
+        logger.info("updateRequirement Response Code:" + restResponse.getErrorCode());
+        Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS);
+    }
+
+    @Test(dependsOnMethods = "updateRequirementTest")
+    public void getRequirementTest() throws Exception {
+        Service service = getServiceObject(component.getUniqueId());
+
+        List<RequirementDefinition> requirementDefinitionList = service.getRequirements().values()
+                .stream().flatMap(Collection::stream).collect(Collectors.toList());
+
+        RestResponse restResponse = RequirementsUtils.getRequirement(component.getUniqueId(),
+                requirementDefinitionList.get(0).getUniqueId(),  user);
+        logger.info("getRequirementTest Response Code:" + restResponse.getErrorCode());
+        Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS);
+    }
+
+    @Test(dependsOnMethods = "getRequirementTest")
+    public void deleteRequirementTest() throws Exception {
+        Service service = getServiceObject(component.getUniqueId());
+
+        List<RequirementDefinition> requirementDefinitionList = service.getRequirements().values()
+                .stream().flatMap(Collection::stream).collect(Collectors.toList());
+
+        RestResponse restResponse = RequirementsUtils.deleteRequirement(component.getUniqueId(),
+                requirementDefinitionList.get(0).getUniqueId(),  user);
+        logger.info("deleteRequirementTest Response Code:" + restResponse.getErrorCode());
+        Assert.assertEquals((int) restResponse.getErrorCode(), BaseRestUtils.STATUS_CODE_SUCCESS);
+    }
+
+    private  RequirementDetails createRequirement() {
+        RequirementDetails  requirementDetails = new RequirementDetails();
+        requirementDetails.setName("req" + Math.random());
+        requirementDetails.setCapability("tosca.capabilities.network.Bindable");
+
+        return requirementDetails;
+    }
+}
diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CapabilityRestUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/CapabilityRestUtils.java
new file mode 100644 (file)
index 0000000..1959aa8
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.ci.tests.utils.rest;
+
+import com.google.gson.Gson;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.ci.tests.api.Urls;
+import org.openecomp.sdc.ci.tests.config.Config;
+import org.openecomp.sdc.ci.tests.datatypes.CapabilityDetails;
+import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse;
+
+import java.util.List;
+
+public class CapabilityRestUtils extends BaseRestUtils {
+    private static Gson gson = new Gson();
+    private static final String COMPONENT_TYPE = "services";
+
+    public static RestResponse createCapability(String componentId,
+                                                 List<CapabilityDetails> capabilityDetailsList,
+                                                 User user) throws Exception{
+        Config config = Config.instance();
+        String url = String.format(Urls.CREATE_CAPABILITY, config.getCatalogBeHost(), config.getCatalogBePort(),
+                COMPONENT_TYPE, componentId);
+
+        String data = "{ \"capabilities\" : {" + "\"" +capabilityDetailsList.get(0).getType()+ "\"" +" : "
+                + gson.toJson(capabilityDetailsList) + "  } }";
+
+        return sendPost(url, data , user.getUserId(), acceptHeaderData);
+    }
+
+    public static RestResponse updateCapability(String componentId,
+                                                 List<CapabilityDetails> capabilityDetailsList,
+                                                 User user) throws Exception{
+        Config config = Config.instance();
+        String url = String.format(Urls.UPDATE_CAPABILITY, config.getCatalogBeHost(), config.getCatalogBePort(),
+                COMPONENT_TYPE, componentId);
+
+        String data = "{ \"capabilities\" : {" + "\"" +capabilityDetailsList.get(0).getType()+ "\"" +" : "
+                + gson.toJson(capabilityDetailsList) + "  } }";
+
+        return sendPost(url, data , user.getUserId(), acceptHeaderData);
+    }
+
+    public static RestResponse deleteCapability(String componentId,
+                                                 String requirementId,
+                                                 User user) throws Exception{
+        Config config = Config.instance();
+        String url = String.format(Urls.DELETE_CAPABILITY, config.getCatalogBeHost(), config.getCatalogBePort(),
+                COMPONENT_TYPE, componentId, requirementId);
+        return sendDelete(url, user.getUserId());
+    }
+
+    public static RestResponse getCapability(String componentId,
+                                              String requirementId,
+                                              User user) throws Exception{
+        Config config = Config.instance();
+        String url = String.format(Urls.GET_CAPABILITY, config.getCatalogBeHost(), config.getCatalogBePort(),
+                COMPONENT_TYPE, componentId, requirementId);
+        return sendDelete(url, user.getUserId());
+    }
+
+}
diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/RequirementsUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/rest/RequirementsUtils.java
new file mode 100644 (file)
index 0000000..4be1d94
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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.ci.tests.utils.rest;
+
+import com.google.gson.Gson;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.ci.tests.api.Urls;
+import org.openecomp.sdc.ci.tests.config.Config;
+import org.openecomp.sdc.ci.tests.datatypes.RequirementDetails;
+import org.openecomp.sdc.ci.tests.datatypes.http.RestResponse;
+
+import java.util.List;
+
+public class RequirementsUtils extends BaseRestUtils {
+    private static Gson gson = new Gson();
+    private static final String COMPONENT_TYPE = "services";
+
+    public static RestResponse createRequirement(String componentId,
+                                                 List<RequirementDetails> requirementDefinitionList,
+                                                 User user) throws Exception{
+        Config config = Config.instance();
+        String url = String.format(Urls.CREATE_REQUIREMENT, config.getCatalogBeHost(), config.getCatalogBePort(),
+                COMPONENT_TYPE, componentId);
+
+        String data = "{ \"requirements\" : {" + "\"" +requirementDefinitionList.get(0).getCapability()+ "\"" +" : "
+                + gson.toJson(requirementDefinitionList) + "  } }";
+
+        return sendPost(url, data , user.getUserId(), acceptHeaderData);
+    }
+
+    public static RestResponse updateRequirement(String componentId,
+                                                 List<RequirementDetails> requirementDefinitionList,
+                                                 User user) throws Exception{
+        Config config = Config.instance();
+        String url = String.format(Urls.UPDATE_REQUIREMENT, config.getCatalogBeHost(), config.getCatalogBePort(),
+                COMPONENT_TYPE, componentId);
+
+        String data = "{ \"requirements\" : {" + "\"" +requirementDefinitionList.get(0).getCapability()+ "\"" +" : "
+                + gson.toJson(requirementDefinitionList) + "  } }";
+
+        return sendPost(url, data , user.getUserId(), acceptHeaderData);
+    }
+
+    public static RestResponse deleteRequirement(String componentId,
+                                                 String requirementId,
+                                                 User user) throws Exception{
+        Config config = Config.instance();
+        String url = String.format(Urls.DELETE_REQUIREMENT, config.getCatalogBeHost(), config.getCatalogBePort(),
+                COMPONENT_TYPE, componentId, requirementId);
+        return sendDelete(url, user.getUserId());
+    }
+
+    public static RestResponse getRequirement(String componentId,
+                                                 String requirementId,
+                                                 User user) throws Exception{
+        Config config = Config.instance();
+        String url = String.format(Urls.GET_REQUIREMENT, config.getCatalogBeHost(), config.getCatalogBePort(),
+                COMPONENT_TYPE, componentId, requirementId);
+        return sendDelete(url, user.getUserId());
+    }
+}
diff --git a/test-apis-ci/src/main/resources/ci/testSuites/cap_req.xml b/test-apis-ci/src/main/resources/ci/testSuites/cap_req.xml
new file mode 100644 (file)
index 0000000..8298af2
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
+<suite name="Cap_Req" >
+       <test name="Cap_Req">
+               <classes>
+                       <class name="org.openecomp.sdc.ci.tests.requirements.RequirementsTest"/>
+                       <class name="org.openecomp.sdc.ci.tests.capability.CapabilitiesTest"/>
+               </classes>
+       </test>
+</suite> <!-- Artifacts -->