diff options
Diffstat (limited to 'catalog-model/src/main/java')
17 files changed, 1363 insertions, 151 deletions
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 index 0000000000..5b03d0ce1b --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/RelationshipTypeDefinition.java @@ -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 + " ]"; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeType.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeType.java index 7ac941e5e2..4babd5d4a8 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeType.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/NodeType.java @@ -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; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/ToscaElement.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/ToscaElement.java index 0f0c63f7fb..a18c75bca7 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/ToscaElement.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/datamodel/ToscaElement.java @@ -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) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java index 52801751cc..b18fb96e8e 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/BaseOperation.java @@ -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 index 0000000000..a8337b6c4f --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/CapabilitiesOperation.java @@ -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); + } + } +} 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 95f518aace..7bd36eacd1 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 @@ -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()) { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java index d9ced8c249..967fc16c49 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/NodeTypeOperation.java @@ -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 index 0000000000..1fd37500bf --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/RequirementOperation.java @@ -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); + } + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java index 38c6b5d16e..095425748a 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/operations/TopologyTemplateOperation.java @@ -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)); + } + } } 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 d8a4fc4af1..a69c80cd36 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 @@ -2546,5 +2546,8 @@ public class ToscaOperationFacade { } return Either.left(parentComponents); } - + public void updateCapReqOwnerId(String componentId) { + topologyTemplateOperation + .updateCapReqOwnerId(componentId, getTopologyTemplate(componentId)); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java index 5e40bd57e7..6fbd7adc98 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsontitan/utils/ModelConverter.java @@ -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(); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/ICapabilityTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/ICapabilityTypeOperation.java index 7f8e07e2c3..4316f733a7 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/ICapabilityTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/ICapabilityTypeOperation.java @@ -21,8 +21,11 @@ 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(); } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java index 97f3e80e2a..3a4a2725e2 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CapabilityTypeOperation.java @@ -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); + } } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OperationUtils.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OperationUtils.java index dcaafe55ac..a06d342d26 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OperationUtils.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OperationUtils.java @@ -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 index 0000000000..13ad7a798c --- /dev/null +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/RelationshipTypeOperation.java @@ -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; + } +} diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/UniqueIdBuilder.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/UniqueIdBuilder.java index 058e9de163..aa5ca81a31 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/UniqueIdBuilder.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/UniqueIdBuilder.java @@ -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); } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/utils/TypeCompareUtils.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/utils/TypeCompareUtils.java index 298cae0da5..e0e02ae121 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/utils/TypeCompareUtils.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/utils/TypeCompareUtils.java @@ -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) { |