aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSindhuri.A <arcot.sindhuri@huawei.com>2018-09-07 13:53:56 +0530
committerMichael Lando <michael.lando@intl.att.com>2018-10-16 16:44:31 +0000
commit2e6a7eb218ad07a19fd1cc09b94e1f6a82e05360 (patch)
treef7fb008af54738f0771b459c92e809e2c2e70544
parente6c3c72677709af1135948b490a99d8f0c6a48bd (diff)
Single node copy paste keyboard shorcut on canvas
Keyboard Shortcut copy paste for single node on Composition page canvas for services Issue-ID: SDC-1736 Change-Id: I669a728d3641a59ba7a4d8cc18fdae1000a0377f Signed-off-by: Sindhuri.A <arcot.sindhuri@huawei.com>
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java515
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java44
-rw-r--r--catalog-be/src/main/resources/config/error-configuration.yaml6
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java222
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ComponentInstanceServletTest.java38
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java2
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java12
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java8
8 files changed, 774 insertions, 73 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
index 35493f715c..04d543c10b 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
@@ -7,9 +7,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -36,43 +36,45 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
-import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.GroupDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
import org.openecomp.sdc.be.impl.ForwardingPathUtils;
import org.openecomp.sdc.be.info.CreateAndAssotiateInfo;
-import org.openecomp.sdc.be.model.ArtifactDefinition;
-import org.openecomp.sdc.be.model.CapabilityDefinition;
import org.openecomp.sdc.be.model.Component;
-import org.openecomp.sdc.be.model.ComponentInstance;
-import org.openecomp.sdc.be.model.ComponentInstanceInput;
-import org.openecomp.sdc.be.model.ComponentInstanceProperty;
import org.openecomp.sdc.be.model.ComponentParametersView;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+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.ComponentInstancePropInput;
+import org.openecomp.sdc.be.model.LifecycleStateEnum;
+import org.openecomp.sdc.be.model.ArtifactDefinition;
import org.openecomp.sdc.be.model.DataTypeDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
import org.openecomp.sdc.be.model.GroupDefinition;
import org.openecomp.sdc.be.model.InputDefinition;
-import org.openecomp.sdc.be.model.LifecycleStateEnum;
-import org.openecomp.sdc.be.model.PropertyDefinition;
-import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames;
import org.openecomp.sdc.be.model.RelationshipInfo;
import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
-import org.openecomp.sdc.be.model.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.ComponentInstance;
+import org.openecomp.sdc.be.model.ComponentInstanceInput;
+import org.openecomp.sdc.be.model.ComponentInstanceProperty;
+import org.openecomp.sdc.be.model.PropertyDefinition.PropertyNames;
import org.openecomp.sdc.be.model.jsontitan.operations.ForwardingPathOperation;
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.IComponentInstanceOperation;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
+import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
import org.openecomp.sdc.be.resources.data.ComponentInstanceData;
@@ -132,11 +134,11 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
@Autowired
private ForwardingPathOperation forwardingPathOperation;
-
public ComponentInstanceBusinessLogic() {
}
- public Either<ComponentInstance, ResponseFormat> createComponentInstance(String containerComponentParam, String containerComponentId, String userId, ComponentInstance resourceInstance) {
+ public Either<ComponentInstance, ResponseFormat> createComponentInstance(
+ String containerComponentParam, String containerComponentId, String userId, ComponentInstance resourceInstance) {
return createComponentInstance(containerComponentParam, containerComponentId, userId, resourceInstance, false, true);
}
@@ -171,7 +173,6 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
});
}
return resList;
-
}
public List<ComponentInstanceInput> getComponentInstanceInputsByInputId(org.openecomp.sdc.be.model.Component component, String inputId){
@@ -205,10 +206,10 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
});
}
return resList;
-
}
- public Either<ComponentInstance, ResponseFormat> createComponentInstance(String containerComponentParam, String containerComponentId, String userId, ComponentInstance resourceInstance, boolean inTransaction, boolean needLock) {
+ public Either<ComponentInstance, ResponseFormat> createComponentInstance(
+ String containerComponentParam, String containerComponentId, String userId, ComponentInstance resourceInstance, boolean inTransaction, boolean needLock) {
Component origComponent = null;
Either<ComponentInstance, ResponseFormat> resultOp = null;
@@ -462,15 +463,15 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
return resultOp;
}
-/**
- * addResourceInstanceArtifacts - add artifacts (HEAT_ENV) to resource instance The instance artifacts are generated from the resource's artifacts
- * @param containerComponent
- * @param componentInstance
- * @param originComponent
- * @param user
- * @param existingEnvVersions
- * @return
- */
+ /**
+ * addResourceInstanceArtifacts - add artifacts (HEAT_ENV) to resource instance The instance artifacts are generated from the resource's artifacts
+ * @param containerComponent
+ * @param componentInstance
+ * @param originComponent
+ * @param user
+ * @param existingEnvVersions
+ * @return
+ */
protected Either<ActionStatus, ResponseFormat> addComponentInstanceArtifacts(org.openecomp.sdc.be.model.Component containerComponent, ComponentInstance componentInstance, org.openecomp.sdc.be.model.Component originComponent, User user, Map<String, String> existingEnvVersions) {
log.debug("add artifacts to resource instance");
@@ -584,7 +585,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
}
public Either<ComponentInstance, ResponseFormat> updateComponentInstanceMetadata(String containerComponentParam, String containerComponentId, String componentInstanceId, String userId, ComponentInstance componentInstance, boolean inTransaction,
- boolean needLock, boolean createNewTransaction) {
+ boolean needLock, boolean createNewTransaction) {
validateUserExists(userId, "update Component Instance", inTransaction);
@@ -682,7 +683,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
boolean validateParent = validateParent(containerComponent, componentInstance.getUniqueId());
if (!validateParent) {
resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, componentInstance.getName(), instanceType.getValue().toLowerCase(), containerComponentType.getValue().toLowerCase(),
- containerComponentId));
+ containerComponentId));
return resultOp;
}
}
@@ -761,7 +762,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
}
private Either<ComponentInstance, ResponseFormat> updateComponentInstanceMetadata(Component containerComponent, ComponentTypeEnum containerComponentType, org.openecomp.sdc.be.model.Component origComponent, String componentInstanceId,
- ComponentInstance componentInstance) {
+ ComponentInstance componentInstance) {
Either<ComponentInstance, ResponseFormat> resultOp = null;
Optional<ComponentInstance> componentInstanceOptional = null;
@@ -881,7 +882,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
return resultOp;
}
Either<ComponentInstance, ResponseFormat> deleteEither = deleteForwardingPathsRelatedTobeDeletedComponentInstance(containerComponentId,
- containerComponentType, resultOp);
+ containerComponentType, resultOp);
if (deleteEither.isRight()){
return deleteEither;
}
@@ -893,7 +894,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
}
public Either<ComponentInstance, ResponseFormat> deleteForwardingPathsRelatedTobeDeletedComponentInstance(String containerComponentId, ComponentTypeEnum containerComponentType,
- Either<ComponentInstance, ResponseFormat> resultOp) {
+ Either<ComponentInstance, ResponseFormat> resultOp) {
if(containerComponentType.equals(ComponentTypeEnum.SERVICE) && resultOp.isLeft() ){
final ComponentInstance componentInstance = resultOp.left().value();
List<String> pathIDsToBeDeleted = getForwardingPathsRelatedToComponentInstance(containerComponentId, componentInstance.getName());
@@ -917,7 +918,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
return Either.right(componentsUtils.getResponseFormat(storageStatus.right().value()));
}
Either<Set<String>, StorageOperationStatus> result = forwardingPathOperation.deleteForwardingPath(storageStatus.left().value(),
- Sets.newHashSet(pathIdsToDelete));
+ Sets.newHashSet(pathIdsToDelete));
if(result.isRight()) {
return Either.right(componentsUtils.getResponseFormat(result.right().value()));
@@ -944,7 +945,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
return pathDataDefinition.getPathElements().getListToscaDataDefinition()
.stream().anyMatch(elementDataDefinition -> elementDataDefinition.getFromNode().equalsIgnoreCase(componentInstanceId) ||
elementDataDefinition.getToNode()
- .equalsIgnoreCase(componentInstanceId));
+ .equalsIgnoreCase(componentInstanceId));
}
@@ -1021,7 +1022,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
}
public Either<RequirementCapabilityRelDef, ResponseFormat> associateRIToRI(String componentId, String userId, RequirementCapabilityRelDef requirementDef, ComponentTypeEnum componentTypeEnum, boolean inTransaction, boolean needLock,
- boolean createNewTransaction) {
+ boolean createNewTransaction) {
validateUserExists(userId, "associate Ri To RI", inTransaction);
@@ -1240,8 +1241,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
private boolean isBelongingRequirement(RelationshipInfo relationshipInfo, RequirementDataDefinition req) {
return req.getName().equals(relationshipInfo.getRequirement()) &&
- req.getUniqueId().equals(relationshipInfo.getRequirementUid()) &&
- req.getOwnerId().equals(relationshipInfo.getRequirementOwnerId());
+ req.getUniqueId().equals(relationshipInfo.getRequirementUid()) &&
+ req.getOwnerId().equals(relationshipInfo.getRequirementOwnerId());
}
private Either<RequirementCapabilityRelDef, ResponseFormat> setRelatedCapability(RequirementCapabilityRelDef foundRelation, Component containerComponent) {
@@ -1688,7 +1689,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
}
public Either<ComponentInstanceProperty, ResponseFormat> createOrUpdateGroupInstancePropertyValue(ComponentTypeEnum componentTypeEnum, String componentId, String resourceInstanceId, String groupInstanceId, ComponentInstanceProperty property,
- String userId) {
+ String userId) {
Either<ComponentInstanceProperty, ResponseFormat> resultOp = null;
@@ -1955,33 +1956,33 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
return eitherResponse;
}
- public Either<Set<String>, ResponseFormat> forwardingPathOnVersionChange(String containerComponentParam,
- String containerComponentId,
- String componentInstanceId,
- ComponentInstance newComponentInstance) {
+ public Either<Set<String>, ResponseFormat> forwardingPathOnVersionChange(String containerComponentParam,
+ String containerComponentId,
+ String componentInstanceId,
+ ComponentInstance newComponentInstance) {
Either<Set<String>, ResponseFormat> resultOp;
Either<ComponentTypeEnum, ResponseFormat> validateComponentType = validateComponentType(containerComponentParam);
if (validateComponentType.isRight()) {
- return Either.right(validateComponentType.right().value());
+ return Either.right(validateComponentType.right().value());
}
final ComponentTypeEnum containerComponentType = validateComponentType.left().value();
ComponentParametersView componentParametersView = getComponentParametersViewForForwardingPath();
//Fetch Component
Either<org.openecomp.sdc.be.model.Component, ResponseFormat> validateComponentExists =
- validateComponentExists(containerComponentId, containerComponentType, componentParametersView);
+ validateComponentExists(containerComponentId, containerComponentType, componentParametersView);
if (validateComponentExists.isRight()) {
- return Either.right(validateComponentExists.right().value());
+ return Either.right(validateComponentExists.right().value());
}
Component containerComponent = validateComponentExists.left().value();
//Fetch current component instance
Either<ComponentInstance, StorageOperationStatus> eitherResourceInstance =
- getResourceInstanceById(containerComponent, componentInstanceId);
+ getResourceInstanceById(containerComponent, componentInstanceId);
if (eitherResourceInstance.isRight()) {
- resultOp = Either.right(componentsUtils.getResponseFormat(
- ActionStatus.RESOURCE_INSTANCE_NOT_FOUND_ON_SERVICE, componentInstanceId, containerComponentId));
- return resultOp;
+ resultOp = Either.right(componentsUtils.getResponseFormat(
+ ActionStatus.RESOURCE_INSTANCE_NOT_FOUND_ON_SERVICE, componentInstanceId, containerComponentId));
+ return resultOp;
}
ComponentInstance currentResourceInstance = eitherResourceInstance.left().value();
@@ -1989,29 +1990,29 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
String resourceId = newComponentInstance.getComponentUid();
Either<Boolean, StorageOperationStatus> componentExistsRes = toscaOperationFacade.validateComponentExists(resourceId);
if (componentExistsRes.isRight()) {
- log.debug("Failed to find resource ", resourceId);
- resultOp = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse
- (componentExistsRes.right().value()), resourceId));
- return resultOp;
+ log.debug("Failed to find resource ", resourceId);
+ resultOp = Either.right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse
+ (componentExistsRes.right().value()), resourceId));
+ return resultOp;
} else if (!componentExistsRes.left().value()) {
- log.debug("The resource {} not found ", resourceId);
- resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId));
- return resultOp;
+ log.debug("The resource {} not found ", resourceId);
+ resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESOURCE_NOT_FOUND, resourceId));
+ return resultOp;
}
//Fetch component using new component instance uid
Either<Component, ResponseFormat> eitherResourceName = getOriginComponentFromComponentInstance(newComponentInstance);
if (eitherResourceName.isRight()) {
- resultOp = Either.right(eitherResourceName.right().value());
- return resultOp;
+ resultOp = Either.right(eitherResourceName.right().value());
+ return resultOp;
}
Component updatedContainerComponent=eitherResourceName.left().value();
Set<String> toDeleteForwardingPaths = getForwardingPaths(containerComponent,
- currentResourceInstance, updatedContainerComponent);
+ currentResourceInstance, updatedContainerComponent);
resultOp=Either.left(toDeleteForwardingPaths);
return resultOp;
- }
+ }
private Set<String> getForwardingPaths(Component containerComponent, ComponentInstance currentResourceInstance,
Component updatedContainerComponent) {
@@ -2022,7 +2023,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
ForwardingPathUtils forwardingPathUtils = new ForwardingPathUtils();
return forwardingPathUtils.
- getForwardingPathsToBeDeletedOnVersionChange(service,dataForMergeHolder,updatedContainerComponent);
+ getForwardingPathsToBeDeletedOnVersionChange(service,dataForMergeHolder,updatedContainerComponent);
}
private ComponentParametersView getComponentParametersViewForForwardingPath() {
@@ -2499,7 +2500,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
Component containerComponent = getResourceResult.left().value();
if (!ComponentValidationUtils.canWorkOnComponent(containerComponent, userId)) {
- log.info("Restricted operation for user: {} on component {}", userId, containerComponentId);
+ log.info("Restricted operation for user: {sourcePropList} on component {}", userId, containerComponentId);
return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
}
Either<ComponentInstance, StorageOperationStatus> resourceInstanceStatus = getResourceInstanceById(containerComponent, componentInstanceUniqueId);
@@ -2525,8 +2526,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
for (ComponentInstanceProperty property : properties) {
Either<String, ResponseFormat> newPropertyValueEither = updatePropertyObjectValue(property, false);
newPropertyValueEither.bimap(updatedValue ->
- updateCapabilityPropertyOnContainerComponent(property,updatedValue, containerComponent, foundResourceInstance, capabilityType, capabilityName, ownerId),
- responseFormat -> Either.right(responseFormat));
+ updateCapabilityPropertyOnContainerComponent(property,updatedValue, containerComponent, foundResourceInstance, capabilityType, capabilityName, ownerId),
+ responseFormat -> Either.right(responseFormat));
}
Either<Component, StorageOperationStatus> updateContainerRes = toscaOperationFacade.updateComponentInstanceMetadataOfTopologyTemplate(containerComponent);
@@ -2550,7 +2551,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
}
public Either<List<ComponentInstanceProperty>, ResponseFormat> updateInstanceCapabilityProperties(ComponentTypeEnum componentTypeEnum, String containerComponentId, String componentInstanceUniqueId, String capabilityType, String capabilityName,
- List<ComponentInstanceProperty> properties, String userId) {
+ List<ComponentInstanceProperty> properties, String userId) {
Either<List<ComponentInstanceProperty>, ResponseFormat> resultOp = null;
validateUserExists(userId, "update instance capability property", false);
@@ -2610,4 +2611,382 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
graphLockOperation.unlockComponent(containerComponentId, componentTypeEnum.getNodeType());
}
}
+
+ public Either<Map<String, ComponentInstance>, ResponseFormat> copyComponentInstance(ComponentInstance inputComponentInstance,
+ String containerComponentId,
+ String componentInstanceId,
+ String userId) {
+
+ Map<String, ComponentInstance> resultMap = new HashMap<>();
+ Either<Component, StorageOperationStatus> getOrigComponent = toscaOperationFacade.getToscaElement(containerComponentId);
+ if (getOrigComponent.isRight()) {
+ log.error("Failed to get the original component information");
+ return Either.right(componentsUtils.getResponseFormat(
+ ActionStatus.USER_DEFINED, "Failed to copy the component instance to the canvas"));
+ }
+
+ Component origComponent = getOrigComponent.left().value();
+
+ Either<Boolean, ResponseFormat> lockComponent = lockComponent(origComponent, "copyComponentInstance");
+ if (lockComponent.isRight()) {
+ log.error("destComponentInstance's data is {}", origComponent.toString());
+ return Either.right(lockComponent.right().value());
+ }
+
+
+ Either<ComponentInstance, ResponseFormat> actionResponse = null;
+ try {
+ actionResponse = createComponentInstance(
+ "services", containerComponentId, userId, inputComponentInstance, true, false);
+
+
+ }
+ finally {
+
+ // on failure of the create instance unlock the resource and rollback the transaction.
+ if (null== actionResponse || actionResponse.isRight()) {
+ titanDao.rollback();
+ log.error("Failed to copy the component instance to the canvas");
+
+ unlockComponent(actionResponse, origComponent);
+
+ return Either.right(componentsUtils.getResponseFormat(
+ ActionStatus.USER_DEFINED, "Failed to copy the component instance to the canvas"));
+ }
+
+ }
+
+ Either<String, ResponseFormat> resultOp = null;
+
+ try {
+ ComponentInstance destComponentInstance = actionResponse.left().value();
+ log.debug("destComponentInstance's data is {}", destComponentInstance.toString());
+
+
+ resultOp = deepCopyComponentInstance(
+ origComponent, containerComponentId, componentInstanceId, destComponentInstance, userId);
+
+ resultMap.put("componentInstance", destComponentInstance);
+ }
+ finally{
+ // unlock resource
+ unlockComponent(resultOp, origComponent);
+
+ if (resultOp == null || resultOp.isRight()) {
+ titanDao.rollback();
+ log.error("Failed to deep copy component instance");
+ return Either.right(componentsUtils.getResponseFormat(
+ ActionStatus.USER_DEFINED, "Failed to deep copy the component instance to the canvas"));
+ } else {
+ titanDao.commit();
+ log.debug("Success trasaction commit");
+ }
+ }
+
+ return Either.left(resultMap);
+ }
+
+ private Either<String, ResponseFormat> deepCopyComponentInstance(
+ Component sourceComponent, String containerComponentId, String sourceComponentInstanceId,
+ ComponentInstance destComponentInstance, String userId) {
+
+ Either<Component, StorageOperationStatus> getDestComponent = toscaOperationFacade.getToscaElement(containerComponentId);
+ if (getDestComponent.isRight()) {
+ log.error("Failed to get the dest component information");
+ return Either.right(componentsUtils.getResponseFormat(
+ ActionStatus.USER_DEFINED, "Failed to copy the component instance to the canvas"));
+ }
+
+ Component destComponent = getDestComponent.left().value();
+
+ Either<String, ResponseFormat> copyComponentInstanceWithPropertiesAndInputs = copyComponentInstanceWithPropertiesAndInputs(
+ sourceComponent, destComponent, sourceComponentInstanceId, destComponentInstance, userId);
+ if (copyComponentInstanceWithPropertiesAndInputs.isRight()) {
+ log.error("Failed to copy component instance with properties and inputs as part of deep copy");
+ return Either.right(componentsUtils.getResponseFormat(
+ ActionStatus.USER_DEFINED, "Failed to copy the component instance with properties and inputs as part of deep copy"));
+ }
+
+ Either<String, ResponseFormat> copyComponentInstanceWithAttributes = copyComponentInstanceWithAttributes(
+ sourceComponent, destComponent, sourceComponentInstanceId, destComponentInstance, userId);
+ if (copyComponentInstanceWithAttributes.isRight()) {
+ log.error("Failed to copy component instance with attributes as part of deep copy");
+ return Either.right(componentsUtils.getResponseFormat(
+ ActionStatus.USER_DEFINED, "Failed to copy the component instance with attributes as part of deep copy"));
+ }
+ return Either.left("Copy component Instance OK");
+ }
+
+ private Either<String, ResponseFormat> copyComponentInstanceWithPropertiesAndInputs(
+ Component sourceComponent, Component destComponent, String sourceComponentInstanceId,
+ ComponentInstance destComponentInstance, String userId) {
+ log.debug("start to copy ComponentInstance with properties and inputs");
+
+ List<ComponentInstanceProperty> sourcePropList = null;
+ if (sourceComponent.getComponentInstancesProperties() != null
+ && sourceComponent.getComponentInstancesProperties().get(sourceComponentInstanceId) != null) {
+ sourcePropList = sourceComponent.getComponentInstancesProperties().get(sourceComponentInstanceId);
+ log.debug("sourcePropList");
+ }
+
+ List<ComponentInstanceProperty> destPropList = null;
+ String destComponentInstanceId = destComponentInstance.getUniqueId();
+ log.debug("destComponentInstanceId: {}", destComponentInstance.getUniqueId());
+ if (destComponent.getComponentInstancesProperties() != null
+ && destComponent.getComponentInstancesProperties().get(destComponentInstanceId) != null) {
+ destPropList = destComponent.getComponentInstancesProperties().get(destComponentInstanceId);
+ log.debug("destPropList {}");
+ }
+
+ List<ComponentInstancePropInput> componentInstancePropInputList = new ArrayList<>();
+
+ if (null != destPropList && null != sourcePropList) {
+ log.debug("start to set property and attribute");
+ for (ComponentInstanceProperty destProp : destPropList) {
+ String destPropertyName = destProp.getName();
+ for (ComponentInstanceProperty sourceProp : sourcePropList) {
+ if (!destPropertyName.equals(sourceProp.getName())) {
+ continue;
+ }
+ log.debug("now set property");
+ if (sourceProp.getGetInputValues() == null && !StringUtils.isEmpty(sourceProp.getValue())
+ && (destProp.getValue() == null || !destProp.getValue().equals(sourceProp.getValue()))) {
+ log.debug("Now starting to copy the property {} in value {}", destPropertyName, sourceProp.getValue());
+
+ destProp.setValue(sourceProp.getValue());
+ Either<String, ResponseFormat> updatePropertyValueEither = updateComponentInstanceProperty(
+ destComponent.getUniqueId(), destComponentInstanceId, destProp);
+ if (updatePropertyValueEither.isRight()) {
+ log.error("Failed to copy the property {}", destPropertyName);
+ return Either.right(componentsUtils.getResponseFormat(
+ ActionStatus.INVALID_CONTENT_PARAM, "Failed to paste component instance to the canvas, property copy"));
+ }
+ break;
+ }
+
+ log.debug("Now start to update inputs");
+
+ if (sourceProp.getGetInputValues() != null) {
+ if (sourceProp.getGetInputValues().size() < 1) {
+ log.debug("property is return from input, set by man");
+ break;
+ }
+ log.debug("Now starting to copy the {} property", destPropertyName);
+
+ Either<String, ResponseFormat> getSourceInputDefaultValue = getInputListDefaultValue(
+ sourceComponent, sourceProp.getGetInputValues().get(0).getInputId());
+ if (getSourceInputDefaultValue.isRight()) {
+ return Either.right(getSourceInputDefaultValue.right().value());
+ }
+ componentInstancePropInputList.add(new ComponentInstancePropInput(destProp));
+ }
+ }
+ }
+ }
+ return Either.left("Copy component Instance OK");
+ }
+
+ private Either<String, ResponseFormat> copyComponentInstanceWithAttributes(Component sourceComponent,
+ Component destComponent,
+ String sourceComponentInstanceId,
+ ComponentInstance destComponentInstance,
+ String userId) {
+ String destComponentInstanceId = destComponentInstance.getUniqueId();
+
+ log.info("start to copy component instance with attributes");
+
+ List<ComponentInstanceProperty> sourceAttributeList = null;
+ if (sourceComponent.getComponentInstancesAttributes() != null
+ && sourceComponent.getComponentInstancesAttributes().get(sourceComponentInstanceId) != null) {
+ sourceAttributeList = sourceComponent.getComponentInstancesAttributes().get(sourceComponentInstanceId);
+ log.info("sourceAttributes {}");
+ }
+
+ List<ComponentInstanceProperty> destAttributeList = null;
+ if (destComponent.getComponentInstancesAttributes() != null
+ && destComponent.getComponentInstancesAttributes().get(destComponentInstanceId) != null) {
+ destAttributeList = destComponent.getComponentInstancesAttributes().get(destComponentInstanceId);
+ log.info("destAttributeList {}");
+ }
+ if (null != sourceAttributeList && null != destAttributeList) {
+ log.info("set attribute");
+
+ for (ComponentInstanceProperty sourceAttribute : sourceAttributeList) {
+ String sourceAttributeName = sourceAttribute.getName();
+ for (ComponentInstanceProperty destAttribute : destAttributeList) {
+ if (sourceAttributeName.equals(destAttribute.getName())) {
+ if (sourceAttribute.getValue() != null && !sourceAttribute.getValue().isEmpty()) {
+ log.debug("Start to copy the attribute exists {}", sourceAttributeName);
+
+ sourceAttribute.setUniqueId(
+ UniqueIdBuilder.buildResourceInstanceUniuqeId(
+ "attribute" , destComponentInstanceId.split("\\.")[1] , sourceAttributeName));
+
+ Either<ComponentInstanceProperty, ResponseFormat> updateAttributeValueEither =
+ createOrUpdateAttributeValueForCopyPaste(ComponentTypeEnum.SERVICE,
+ destComponent.getUniqueId(), destComponentInstanceId, sourceAttribute,
+ userId);
+ if (updateAttributeValueEither.isRight()) {
+ log.error("Failed to copy the attribute");
+ return Either.right(componentsUtils
+ .getResponseFormat(ActionStatus.INVALID_CONTENT_PARAM,
+ "Failed to paste component instance to the canvas, attribute copy"));
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return Either.left("Copy component Instance OK");
+ }
+
+ private Either<ComponentInstanceProperty, ResponseFormat> createOrUpdateAttributeValueForCopyPaste(ComponentTypeEnum componentTypeEnum,
+ String componentId,
+ String resourceInstanceId,
+ ComponentInstanceProperty attribute,
+ String userId) {
+
+ Either<ComponentInstanceProperty, ResponseFormat> resultOp = null;
+
+ validateUserExists(userId, "Create or Update attribute value", false);
+
+ if (componentTypeEnum == null) {
+ BeEcompErrorManager.getInstance().logInvalidInputError(
+ "createOrUpdateAttributeValue", "invalid component type", ErrorSeverity.INFO);
+ resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.NOT_ALLOWED));
+ return resultOp;
+ }
+
+ Either<Component, StorageOperationStatus> getResourceResult = toscaOperationFacade.getToscaElement(componentId, JsonParseFlagEnum.ParseAll);
+
+ if (getResourceResult.isRight()) {
+ log.info("Failed to retrieve component id {}", componentId);
+ resultOp = Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
+ return resultOp;
+ }
+
+ Component containerComponent = getResourceResult.left().value();
+
+ Either<ComponentInstance, StorageOperationStatus> resourceInstanceStatus = getResourceInstanceById(containerComponent, resourceInstanceId);
+
+ if (resourceInstanceStatus.isRight()) {
+ resultOp = Either.right(componentsUtils.getResponseFormat(
+ ActionStatus.RESOURCE_INSTANCE_NOT_FOUND_ON_SERVICE, resourceInstanceId, componentId));
+ return resultOp;
+ }
+
+ ComponentInstance foundResourceInstance = resourceInstanceStatus.left().value();
+
+
+ String propertyType = attribute.getType();
+ ToscaPropertyType type = ToscaPropertyType.isValidType(propertyType);
+ log.info("The type of attribute id{},is {} ", attribute.getUniqueId(), propertyType);
+
+ if (type == ToscaPropertyType.LIST || type == ToscaPropertyType.MAP) {
+ SchemaDefinition def = attribute.getSchema();
+ if (def == null) {
+ log.info("Schema doesn't exists for attribute of type {}", type);
+ return Either.right(componentsUtils.getResponseFormat(
+ componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE)));
+ }
+ PropertyDataDefinition propDef = def.getProperty();
+ if (propDef == null) {
+ log.info("Attribute in Schema Definition inside attribute of type {} doesn't exist", type);
+ return Either.right(componentsUtils.getResponseFormat(
+ componentsUtils.convertFromStorageResponse(StorageOperationStatus.INVALID_VALUE)));
+ }
+ }
+
+ List<ComponentInstanceProperty> instanceAttributes = containerComponent.
+ getComponentInstancesAttributes().get(resourceInstanceId);
+ Optional<ComponentInstanceProperty> instanceAttribute =
+ instanceAttributes.stream().filter(p -> p.getUniqueId().equals(attribute.getUniqueId())).findAny();
+ StorageOperationStatus status;
+
+ if (instanceAttribute.isPresent()) {
+ log.info("updateComponentInstanceAttribute");
+ status = toscaOperationFacade.updateComponentInstanceAttribute(containerComponent, foundResourceInstance.getUniqueId(), attribute);
+ } else {
+ log.info("addComponentInstanceAttribute");
+ status = toscaOperationFacade.addComponentInstanceAttribute(containerComponent, foundResourceInstance.getUniqueId(), attribute);
+ }
+ if (status != StorageOperationStatus.OK) {
+ ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForResourceInstanceProperty(status);
+ resultOp = Either.right(componentsUtils.getResponseFormatForResourceInstanceProperty(actionStatus, ""));
+ return resultOp;
+ }
+ List<String> path = new ArrayList<>();
+ path.add(foundResourceInstance.getUniqueId());
+ attribute.setPath(path);
+
+ foundResourceInstance.setCustomizationUUID(UUID.randomUUID().toString());
+ Either<Component, StorageOperationStatus> updateContainerRes = toscaOperationFacade.
+ updateComponentInstanceMetadataOfTopologyTemplate(containerComponent);
+
+ if (updateContainerRes.isRight()) {
+ ActionStatus actionStatus = componentsUtils.
+ convertFromStorageResponseForResourceInstanceProperty(updateContainerRes.right().value());
+ resultOp = Either.right(componentsUtils.
+ getResponseFormatForResourceInstanceProperty(actionStatus, ""));
+ return resultOp;
+ }
+ resultOp = Either.left(attribute);
+ return resultOp;
+
+
+
+ }
+
+ private Either<String, ResponseFormat> updateComponentInstanceProperty(String containerComponentId,
+ String componentInstanceId,
+ ComponentInstanceProperty property) {
+ Either<String, ResponseFormat> resultOp;
+ Either<Component, StorageOperationStatus> getComponent = toscaOperationFacade.getToscaElement(containerComponentId);
+
+ if (getComponent.isRight()) {
+ log.error("Failed to get the component information");
+ return Either.right(componentsUtils.getResponseFormatForResourceInstanceProperty(
+ ActionStatus.INVALID_CONTENT_PARAM, "Failed to get the component information"));
+ }
+
+ Component containerComponent = getComponent.left().value();
+
+ StorageOperationStatus status = toscaOperationFacade.updateComponentInstanceProperty(
+ containerComponent, componentInstanceId, property);
+ if (status != StorageOperationStatus.OK) {
+ ActionStatus actionStatus = componentsUtils.convertFromStorageResponseForResourceInstanceProperty(status);
+ resultOp = Either.right(componentsUtils.getResponseFormatForResourceInstanceProperty(actionStatus, ""));
+ return resultOp;
+ }
+
+ Either<Component, StorageOperationStatus> updateContainerRes = toscaOperationFacade.
+ updateComponentInstanceMetadataOfTopologyTemplate(containerComponent);
+
+ if (updateContainerRes.isRight()) {
+ ActionStatus actionStatus = componentsUtils.
+ convertFromStorageResponseForResourceInstanceProperty(updateContainerRes.right().value());
+ resultOp = Either.right(componentsUtils.getResponseFormatForResourceInstanceProperty(actionStatus, ""));
+ return resultOp;
+ }
+
+ return Either.left("Update OK");
+ }
+
+ private Either<String, ResponseFormat> getInputListDefaultValue(Component component, String inputId) {
+ List<InputDefinition> inputList = component.getInputs();
+ for (InputDefinition input : inputList) {
+ if (input.getUniqueId().equals(inputId)) {
+ if (input.getDefaultValue() == null) {
+ log.debug("The input's default value is null");
+ return Either.left(null);
+ }
+ return Either.left(input.getDefaultValue());
+ }
+ }
+ log.error("The input's default value with id {} is not found", inputId);
+ return Either.right(componentsUtils.getResponseFormat(
+ ActionStatus.USER_DEFINED, "Failed to paste component instance to the canvas"));
+ }
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java
index dec12d770f..3195727a68 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java
@@ -58,6 +58,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
+import java.util.Map;
/**
* Root resource (exposed at "/" path) .json
@@ -1205,4 +1206,47 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet {
}
+ @POST
+ @Path("/services/{componentId}/copyComponentInstance/{componentInstanceId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces((MediaType.APPLICATION_JSON))
+ @ApiOperation(value = "Copy Component Instance", httpMethod = "POST", notes = "Returns updated service information", response = Service.class)
+ @ApiResponses(value = {
+ @ApiResponse(code = 201, message = "Copy and Paste Success"),
+ @ApiResponse(code = 403, message = "Restricted Operation"),
+ @ApiResponse(code = 400, message = "Invalid Content / Missing content")})
+ public Response copyComponentInstance(
+ @ApiParam(value = "service unique id in pasted canvas") @PathParam("componentId") final String containerComponentId,
+ @ApiParam(value = "Data for copying", required = true) String data, @PathParam("componentInstanceId") final String componentInstanceId,
+ @Context final HttpServletRequest request) {
+ log.info("Start to copy component instance");
+ ServletContext context = request.getSession().getServletContext();
+ String userId = request.getHeader(Constants.USER_ID_HEADER);
+ final String CNTAINER_CMPT_TYPE = "services";
+
+ try {
+ ComponentInstance inputComponentInstance = RepresentationUtils.fromRepresentation(data, ComponentInstance.class);
+ inputComponentInstance.setInvariantName(null);
+ ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(CNTAINER_CMPT_TYPE);
+ ComponentInstanceBusinessLogic componentInstanceLogic = getComponentInstanceBL(context);
+ if (componentInstanceLogic == null) {
+ log.debug(UNSUPPORTED_COMPONENT_TYPE, componentTypeEnum);
+ return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, "services"));
+ }
+ Either<Map<String, ComponentInstance>, ResponseFormat> copyComponentInstance = componentInstanceLogic.copyComponentInstance(
+ inputComponentInstance, containerComponentId, componentInstanceId, userId);
+
+ if (copyComponentInstance.isRight()) {
+ log.error("Failed to copy ComponentInstance {}", copyComponentInstance.right().value());
+ return buildErrorResponse(copyComponentInstance.right().value());
+ }
+
+ return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
+ copyComponentInstance.left().value());
+ } catch (Exception e) {
+ log.error("Failed to convert json to Map { }, error: { }", data, e);
+ return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.USER_DEFINED,
+ "Failed to get the copied component instance information"));
+ }
+ }
}
diff --git a/catalog-be/src/main/resources/config/error-configuration.yaml b/catalog-be/src/main/resources/config/error-configuration.yaml
index 6156090df3..aa000f14a7 100644
--- a/catalog-be/src/main/resources/config/error-configuration.yaml
+++ b/catalog-be/src/main/resources/config/error-configuration.yaml
@@ -105,6 +105,12 @@ errors:
message: "Error: Invalid userId '%1'.",
messageId: "SVC4008"
}
+#---------SVC4009-----------------------------
+ USER_DEFINED: {
+ code: 400,
+ message: "Error: User Defined '%1'.",
+ messageId: "SVC4009"
+ }
#---------SVC4049------------------------------
# %1 - service/resource
COMPONENT_MISSING_CONTACT: {
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java
index 1a6483009d..929bb97281 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java
@@ -1,6 +1,5 @@
package org.openecomp.sdc.be.components.impl;
-import static org.junit.Assert.assertSame;
import static org.assertj.core.api.Assertions.assertThat;
import fj.data.Either;
@@ -16,14 +15,18 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
import org.openecomp.sdc.be.components.validation.UserValidations;
import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
+import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
import org.openecomp.sdc.be.datatypes.elements.*;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.impl.ComponentsUtils;
import org.openecomp.sdc.be.impl.ServletUtils;
import org.openecomp.sdc.be.info.CreateAndAssotiateInfo;
@@ -32,19 +35,22 @@ import org.openecomp.sdc.be.model.LifecycleStateEnum;
import org.openecomp.sdc.be.model.jsontitan.operations.ForwardingPathOperation;
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.UserBusinessLogic;
+import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
import org.openecomp.sdc.exception.ResponseFormat;
import java.util.function.BiPredicate;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
-import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.when;
@@ -86,6 +92,13 @@ public class ComponentInstanceBusinessLogicTest {
private User user;
@Mock
private UserValidations userValidations;
+ @Mock
+ private TitanDao titanDao;
+ @Mock
+ private ArtifactsBusinessLogic artifactBusinessLogic;
+ @Mock
+ private GraphLockOperation graphLockOperation;
+
private Component service;
private Component resource;
private ComponentInstance toInstance;
@@ -158,8 +171,8 @@ public class ComponentInstanceBusinessLogicTest {
Either<Set<String>, ResponseFormat> resultOp = componentInstanceBusinessLogic.forwardingPathOnVersionChange
(containerComponentParam,containerComponentID,componentInstanceID,newComponentInstance);
- Assert.assertEquals(1,resultOp.left().value().size());
- Assert.assertEquals("FP-ID-1",resultOp.left().value().iterator().next());
+ assertEquals(1,resultOp.left().value().size());
+ assertEquals("FP-ID-1",resultOp.left().value().iterator().next());
}
@@ -1067,4 +1080,205 @@ public class ComponentInstanceBusinessLogicTest {
when(toscaOperationFacade.getToscaFullElement(containerComponentId)).thenReturn(Either.left(resource));
result=testSubject.updateInstanceCapabilityProperties(componentTypeEnum, containerComponentId, componentInstanceUniqueId, capabilityType, capabilityName, properties, userId);
}
+
+ @Test
+ public void testCopyComponentInstanceWrongUserId() {
+
+ Either<Map<String, ComponentInstance>, ResponseFormat> result;
+ ComponentInstance inputComponentInstance = createComponetInstanceFromComponent(resource);
+ String containerComponentId = service.getUniqueId();
+ String componentInstanceId = resource.getUniqueId();
+ String oldLastUpdatedUserId = service.getLastUpdaterUserId();
+ service.setLastUpdaterUserId("wrong user id");
+
+ Either<Component, StorageOperationStatus> leftServiceOp = Either.left(service);
+ when(toscaOperationFacade.getToscaElement(containerComponentId)).thenReturn(leftServiceOp);
+ when(toscaOperationFacade.getToscaElement(eq(containerComponentId), any(ComponentParametersView.class)))
+ .thenReturn(leftServiceOp);
+ when(titanDao.rollback()).thenReturn(TitanOperationStatus.OK);
+ when(graphLockOperation.unlockComponent(Mockito.anyString(), eq(NodeTypeEnum.Service)))
+ .thenReturn(StorageOperationStatus.OK);
+ when(graphLockOperation.lockComponent(Mockito.anyString(), eq(NodeTypeEnum.Service)))
+ .thenReturn(StorageOperationStatus.OK);
+
+ result = componentInstanceBusinessLogic
+ .copyComponentInstance(inputComponentInstance, containerComponentId, componentInstanceId, USER_ID);
+
+ service.setLastUpdaterUserId(oldLastUpdatedUserId);
+
+ assertThat(result.isRight());
+ }
+
+ @Test
+ public void testCopyComponentInstanceComponentWrongState() {
+ Either<Map<String, ComponentInstance>, ResponseFormat> result;
+ ComponentInstance inputComponentInstance = createComponetInstanceFromComponent(resource);
+ String containerComponentId = service.getUniqueId();
+ String componentInstanceId = resource.getUniqueId();
+ String oldServiceLastUpdatedUserId = service.getLastUpdaterUserId();
+ service.setLastUpdaterUserId(USER_ID);
+
+ Either<Component, StorageOperationStatus> leftServiceOp = Either.left(service);
+ when(toscaOperationFacade.getToscaElement(containerComponentId)).thenReturn(leftServiceOp);
+ when(toscaOperationFacade.getToscaElement(eq(containerComponentId), any(ComponentParametersView.class)))
+ .thenReturn(leftServiceOp);
+ when(titanDao.rollback()).thenReturn(TitanOperationStatus.OK);
+ when(graphLockOperation.unlockComponent(Mockito.anyString(), eq(NodeTypeEnum.Service)))
+ .thenReturn(StorageOperationStatus.OK);
+ when(graphLockOperation.lockComponent(Mockito.anyString(), eq(NodeTypeEnum.Service)))
+ .thenReturn(StorageOperationStatus.OK);
+ Either<Component, StorageOperationStatus> getComponentRes = Either.left(resource);
+ when(toscaOperationFacade.getToscaFullElement(inputComponentInstance.getComponentUid()))
+ .thenReturn(getComponentRes);
+
+ result = componentInstanceBusinessLogic
+ .copyComponentInstance(inputComponentInstance, containerComponentId, componentInstanceId, USER_ID);
+
+ service.setLastUpdaterUserId(oldServiceLastUpdatedUserId);
+
+ assertThat(result.isRight());
+ }
+
+ @Test
+ public void testCopyComponentInstance() {
+ Either<Map<String, ComponentInstance>, ResponseFormat> result;
+ ComponentInstance inputComponentInstance = createComponetInstanceFromComponent(resource);
+ String containerComponentId = service.getUniqueId();
+ String componentInstanceId = resource.getUniqueId();
+ String oldServiceLastUpdatedUserId = service.getLastUpdaterUserId();
+ service.setLastUpdaterUserId(USER_ID);
+ LifecycleStateEnum oldResourceLifeCycle = resource.getLifecycleState();
+ resource.setLifecycleState(LifecycleStateEnum.CERTIFIED);
+
+ Either<Component, StorageOperationStatus> leftServiceOp = Either.left(service);
+ when(toscaOperationFacade.getToscaElement(containerComponentId)).thenReturn(leftServiceOp);
+ when(toscaOperationFacade.getToscaElement(eq(containerComponentId), any(ComponentParametersView.class)))
+ .thenReturn(leftServiceOp);
+ when(graphLockOperation.unlockComponent(Mockito.anyString(), eq(NodeTypeEnum.Service)))
+ .thenReturn(StorageOperationStatus.OK);
+ when(graphLockOperation.lockComponent(Mockito.anyString(), eq(NodeTypeEnum.Service)))
+ .thenReturn(StorageOperationStatus.OK);
+ Either<Component, StorageOperationStatus> getComponentRes = Either.left(resource);
+ when(toscaOperationFacade.getToscaFullElement(inputComponentInstance.getComponentUid()))
+ .thenReturn(getComponentRes);
+ ImmutablePair<Component, String> pair = new ImmutablePair<>(resource, TO_INSTANCE_ID);
+ Either<ImmutablePair<Component, String>, StorageOperationStatus> result2 = Either.left(pair);
+ when(toscaOperationFacade
+ .addComponentInstanceToTopologyTemplate(eq(service), eq(resource), eq(inputComponentInstance), eq(false),
+ isNull(User.class))).thenReturn(result2);
+ Either<Map<String, ArtifactDefinition>, StorageOperationStatus> getResourceDeploymentArtifacts = Either
+ .left(new HashMap<String, ArtifactDefinition>());
+ when(artifactBusinessLogic.getArtifacts(eq(inputComponentInstance.getComponentUid()), eq(NodeTypeEnum.Resource),
+ eq(ArtifactGroupTypeEnum.DEPLOYMENT), isNull(String.class))).thenReturn(getResourceDeploymentArtifacts);
+ StorageOperationStatus artStatus = StorageOperationStatus.OK;
+ when(toscaOperationFacade
+ .addInformationalArtifactsToInstance(eq(resource.getUniqueId()), eq(inputComponentInstance),
+ isNull(Map.class))).thenReturn(artStatus);
+
+ result = componentInstanceBusinessLogic
+ .copyComponentInstance(inputComponentInstance, containerComponentId, componentInstanceId, USER_ID);
+
+ service.setLastUpdaterUserId(oldServiceLastUpdatedUserId);
+ resource.setLifecycleState(oldResourceLifeCycle);
+
+ assertThat(result.isLeft());
+ }
+
+ @Test
+ public void testCreateOrUpdateAttributeValueForCopyPaste() {
+ ComponentInstance serviceComponentInstance = createComponetInstanceFromComponent(service);
+ ComponentInstanceProperty attribute = new ComponentInstanceProperty();
+ attribute.setType("string");
+ attribute.setUniqueId("testCreateOrUpdateAttributeValueForCopyPaste");
+ SchemaDefinition def = Mockito.mock(SchemaDefinition.class);
+ attribute.setSchema(def);
+ LifecycleStateEnum oldLifeCycleState = service.getLifecycleState();
+ String oldLastUpdatedUserId = service.getLastUpdaterUserId();
+ service.setLastUpdaterUserId(USER_ID);
+ service.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
+
+ Map<String, List<ComponentInstanceProperty>> instAttrsMap = new HashMap<String, List<ComponentInstanceProperty>>();
+ List<ComponentInstanceProperty> instAttrsList = new ArrayList<ComponentInstanceProperty>();
+ ComponentInstanceProperty prop = new ComponentInstanceProperty();
+ prop.setUniqueId(attribute.getUniqueId());
+ instAttrsList.add(prop);
+ instAttrsMap.put(toInstance.getUniqueId(), instAttrsList);
+ service.setComponentInstancesAttributes(instAttrsMap);
+
+ Either<Component, StorageOperationStatus> serviceEitherLeft = Either.left(service);
+ when(toscaOperationFacade.getToscaElement(serviceComponentInstance.getUniqueId(), JsonParseFlagEnum.ParseAll)).thenReturn(serviceEitherLeft);
+ when(toscaOperationFacade.updateComponentInstanceAttribute(service, toInstance.getUniqueId(), attribute)).thenReturn(StorageOperationStatus.OK);
+ when(toscaOperationFacade.updateComponentInstanceMetadataOfTopologyTemplate(service)).thenReturn(serviceEitherLeft);
+
+ Either<ComponentInstanceProperty, ResponseFormat> result = Deencapsulation.invoke(componentInstanceBusinessLogic, "createOrUpdateAttributeValueForCopyPaste", ComponentTypeEnum.SERVICE,
+ serviceComponentInstance.getUniqueId(),
+ toInstance.getUniqueId(),
+ attribute,
+ USER_ID);
+
+ service.setLastUpdaterUserId(oldLastUpdatedUserId);
+ service.setLifecycleState(oldLifeCycleState);
+
+ assertTrue(result.isLeft());
+ ComponentInstanceProperty resultProp = result.left().value();
+ assertEquals(resultProp.getPath().size(), 1);
+ assertEquals(resultProp.getPath().get(0), toInstance.getUniqueId());
+ }
+
+ @Test
+ public void testUpdateComponentInstanceProperty() {
+
+ String containerComponentId = service.getUniqueId();
+ String componentInstanceId = "dummy_id";
+ ComponentInstanceProperty property = Mockito.mock(ComponentInstanceProperty.class);
+
+ Either<Component, StorageOperationStatus> getComponent = Either.left(service);
+ when(toscaOperationFacade.getToscaElement(containerComponentId)).thenReturn(getComponent);
+ StorageOperationStatus status = StorageOperationStatus.OK;
+ when(toscaOperationFacade.updateComponentInstanceProperty(service, componentInstanceId, property))
+ .thenReturn(status);
+ Either<Component, StorageOperationStatus> updateContainerRes = Either.left(service);
+ when(toscaOperationFacade.updateComponentInstanceMetadataOfTopologyTemplate(service))
+ .thenReturn(updateContainerRes);
+
+ Either<String, ResponseFormat> result = Deencapsulation
+ .invoke(componentInstanceBusinessLogic, "updateComponentInstanceProperty", containerComponentId,
+ componentInstanceId, property);
+
+ assertTrue(result.isLeft());
+ }
+
+ @Test
+ public void testGetInputListDefaultValue() {
+ Component component = service;
+ String inputId = "dummy_id";
+ String defaultValue = "dummy_default_value";
+ List<InputDefinition> newInputs = new ArrayList<InputDefinition>();
+ InputDefinition in = new InputDefinition();
+ in.setUniqueId(inputId);
+ in.setDefaultValue(defaultValue);
+ newInputs.add(in);
+ List<InputDefinition> oldInputs = service.getInputs();
+ service.setInputs(newInputs);
+
+ Either<String, ResponseFormat> result = Deencapsulation
+ .invoke(componentInstanceBusinessLogic, "getInputListDefaultValue", component, inputId);
+
+ service.setInputs(oldInputs);
+
+ assertEquals(result.left().value(), defaultValue);
+ }
+
+ private ComponentInstance createComponetInstanceFromComponent(Component component) {
+ ComponentInstance componentInst = new ComponentInstance();
+ componentInst.setUniqueId(component.getUniqueId());
+ componentInst.setComponentUid(component.getUniqueId() + "_test");
+ componentInst.setPosX("10");
+ componentInst.setPosY("10");
+ componentInst.setCapabilities(component.getCapabilities());
+ componentInst.setRequirements(component.getRequirements());
+ componentInst.setArtifacts(component.getArtifacts());
+ componentInst.setDeploymentArtifacts(component.getDeploymentArtifacts());
+ return componentInst;
+ }
}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ComponentInstanceServletTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ComponentInstanceServletTest.java
index 0c91b49fee..d8e7896d71 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ComponentInstanceServletTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ComponentInstanceServletTest.java
@@ -1,6 +1,10 @@
package org.openecomp.sdc.be.servlets;
import fj.data.Either;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.client.Entity;
import org.eclipse.jetty.http.HttpStatus;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
@@ -16,7 +20,10 @@ import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.impl.ComponentsUtils;
import org.openecomp.sdc.be.impl.ServletUtils;
import org.openecomp.sdc.be.impl.WebAppContextWrapper;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.ComponentInstance;
import org.openecomp.sdc.be.model.RequirementCapabilityRelDef;
+import org.openecomp.sdc.be.model.RequirementDefinition;
import org.openecomp.sdc.common.api.Constants;
import org.openecomp.sdc.exception.ResponseFormat;
import org.springframework.context.ApplicationContext;
@@ -31,6 +38,7 @@ import javax.ws.rs.core.Response;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@@ -94,6 +102,36 @@ public class ComponentInstanceServletTest extends JerseyTest {
assertEquals(response.getStatus(), HttpStatus.BAD_REQUEST_400);
}
+ @Test
+ public void testCopyComponentInstanceSuccess(){
+
+ String componentId = "componentId";
+ String componentInstanceId = "componentInstanceId";
+ String path = "/v1/catalog/services/" + componentId + "/copyComponentInstance/" + componentInstanceId;
+
+ Either<Map<String, ComponentInstance>, ResponseFormat> successResponse = Either.left(new HashMap<String, ComponentInstance>());
+ when(componentInstanceBusinessLogic.copyComponentInstance(any(ComponentInstance.class), eq(componentId), eq(componentInstanceId), eq(USER_ID))).thenReturn(successResponse);
+ when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
+ when(componentsUtils.getResponseFormat(ActionStatus.OK)).thenReturn(responseFormat);
+
+ ComponentInstance c = new ComponentInstance();
+ c.setName("comp1");
+ c.setUniqueId("comp1");
+ c.setComponentUid("comp1");
+ c.setPosX("10");
+ c.setPosY("10");
+ c.setCapabilities(new HashMap<String, List<CapabilityDefinition>>());
+ c.setRequirements(new HashMap<String, List<RequirementDefinition>>());
+
+ Response response = target()
+ .path(path)
+ .request(MediaType.APPLICATION_JSON)
+ .header("USER_ID", USER_ID)
+ .post(Entity.json(c));
+
+ assertEquals(response.getStatus(), HttpStatus.OK_200);
+ }
+
@Override
protected ResourceConfig configure() {
forceSet(TestProperties.CONTAINER_PORT, "0");
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
index 7acd65fbbb..e5caee5f01 100644
--- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
@@ -23,7 +23,7 @@ package org.openecomp.sdc.be.dao.api;
public enum ActionStatus {
OK, ACCEPTED, CREATED, NO_CONTENT, GENERAL_ERROR, NOT_ALLOWED, MISSING_INFORMATION, RESTRICTED_OPERATION, RESTRICTED_ACCESS, INVALID_CONTENT,
// User related
- USER_ALREADY_EXIST, USER_INACTIVE, USER_NOT_FOUND, USER_HAS_ACTIVE_ELEMENTS, INVALID_EMAIL_ADDRESS, INVALID_ROLE, DELETE_USER_ADMIN_CONFLICT, UPDATE_USER_ADMIN_CONFLICT, CANNOT_DELETE_USER_WITH_ACTIVE_ELEMENTS, CANNOT_UPDATE_USER_WITH_ACTIVE_ELEMENTS, INVALID_USER_ID,
+ USER_ALREADY_EXIST, USER_INACTIVE, USER_NOT_FOUND, USER_HAS_ACTIVE_ELEMENTS, INVALID_EMAIL_ADDRESS, INVALID_ROLE, DELETE_USER_ADMIN_CONFLICT, UPDATE_USER_ADMIN_CONFLICT, CANNOT_DELETE_USER_WITH_ACTIVE_ELEMENTS, CANNOT_UPDATE_USER_WITH_ACTIVE_ELEMENTS, INVALID_USER_ID, USER_DEFINED,
// CapabilityType related
CAPABILITY_TYPE_ALREADY_EXIST, MISSING_CAPABILITY_TYPE, MISSING_CAPABILITIES, REQ_CAP_NOT_SATISFIED_BEFORE_CERTIFICATION, IMPORT_DUPLICATE_REQ_CAP_NAME, IMPORT_REQ_CAP_NAME_EXISTS_IN_DERIVED,
CAPABILITY_OF_INSTANCE_NOT_FOUND_ON_CONTAINER, REQUIREMENT_OF_INSTANCE_NOT_FOUND_ON_CONTAINER, RELATION_NOT_FOUND,
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java
index eb41232ad0..fda20c1a12 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTemplateOperation.java
@@ -1972,6 +1972,18 @@ public class NodeTemplateOperation extends BaseOperation {
return updateToscaDataDeepElementsOfToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_PROPERTIES, VertexTypeEnum.INST_PROPERTIES, properties, pathKeys, JsonPresentationFields.NAME);
}
+ public StorageOperationStatus updateComponentInstanceAttribute(Component containerComponent, String componentInstanceId, ComponentInstanceProperty property){
+ List<String> pathKeys = new ArrayList<>();
+ pathKeys.add(componentInstanceId);
+ return updateToscaDataDeepElementOfToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_ATTRIBUTES, VertexTypeEnum.INST_ATTRIBUTES, property, pathKeys, JsonPresentationFields.NAME);
+ }
+
+ public StorageOperationStatus addComponentInstanceAttribute(Component containerComponent, String componentInstanceId, ComponentInstanceProperty property){
+ List<String> pathKeys = new ArrayList<>();
+ pathKeys.add(componentInstanceId);
+ return addToscaDataDeepElementToToscaElement(containerComponent.getUniqueId(), EdgeLabelEnum.INST_ATTRIBUTES, VertexTypeEnum.INST_ATTRIBUTES, property, pathKeys, JsonPresentationFields.NAME);
+ }
+
public StorageOperationStatus updateComponentInstanceInput(Component containerComponent, String componentInstanceId, ComponentInstanceInput property) {
List<String> pathKeys = new ArrayList<>();
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java
index aae73841a1..a1d08a6eed 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/ToscaOperationFacade.java
@@ -2222,6 +2222,14 @@ public class ToscaOperationFacade {
return nodeTemplateOperation.addComponentInstanceProperty(containerComponent, componentInstanceId, property);
}
+ public StorageOperationStatus updateComponentInstanceAttribute(Component containerComponent, String componentInstanceId, ComponentInstanceProperty property){
+ return nodeTemplateOperation.updateComponentInstanceAttribute(containerComponent, componentInstanceId, property);
+ }
+
+ public StorageOperationStatus addComponentInstanceAttribute(Component containerComponent, String componentInstanceId, ComponentInstanceProperty property){
+ return nodeTemplateOperation.addComponentInstanceAttribute(containerComponent, componentInstanceId, property);
+ }
+
public StorageOperationStatus updateComponentInstanceInput(Component containerComponent, String componentInstanceId, ComponentInstanceInput property) {
return nodeTemplateOperation.updateComponentInstanceInput(containerComponent, componentInstanceId, property);
}