summaryrefslogtreecommitdiffstats
path: root/catalog-model/src/main/java
diff options
context:
space:
mode:
authoraribeiro <anderson.ribeiro@est.tech>2020-06-24 08:34:22 +0100
committerOfir Sonsino <ofir.sonsino@intl.att.com>2020-07-09 09:34:30 +0000
commitbdeb28f273da2494d7eeabbb5329222dfd168e3b (patch)
tree2cf9e54e83db704ee7215b033a2abde9ab8adee7 /catalog-model/src/main/java
parent0132d3637a889f84897d6a08688b20ff6f606041 (diff)
Add support for substitution_filter business logic
Tosca simple YAML profile allows for substitution_filter to be specified for a topology template to provide processing instructions to the orchestrator. Issue-ID: SDC-3147 Signed-off-by: aribeiro <anderson.ribeiro@est.tech> Change-Id: Ia94b8c447d3157e614f9d1524ad4520b3980ba4d
Diffstat (limited to 'catalog-model/src/main/java')
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java2
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java104
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java31
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/datamodel/TopologyTemplate.java10
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/BaseOperation.java34
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeFilterOperation.java49
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/SubstitutionFilterOperation.java139
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/TopologyTemplateOperation.java48
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java37
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java3
10 files changed, 302 insertions, 155 deletions
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java
index 477d903652..dc0fb51d7c 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/Component.java
@@ -48,6 +48,7 @@ import org.openecomp.sdc.be.datatypes.elements.PolicyDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType;
import org.openecomp.sdc.be.datatypes.elements.PropertiesOwner;
import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.model.category.CategoryDefinition;
import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
@@ -83,6 +84,7 @@ public abstract class Component implements PropertiesOwner {
private String derivedFromGenericVersion;
private String toscaType;
private Map<String, CINodeFilterDataDefinition> nodeFilterComponents;
+ private Map<String, SubstitutionFilterDataDefinition> substitutionFilterComponents;
private Map<String, InterfaceDefinition> interfaces;
private List<DataTypeDefinition> dataTypes;
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java
index 3eefcc1505..5b99f99bd2 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentInstance.java
@@ -20,20 +20,24 @@
package org.openecomp.sdc.be.model;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.commons.collections.MapUtils;
+import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.PropertiesOwner;
+import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.CreatedFrom;
import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
import org.openecomp.sdc.common.log.api.ILogConfiguration;
-import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ComponentInstance extends ComponentInstanceDataDefinition implements PropertiesOwner{
+@Getter
+@Setter
+public class ComponentInstance extends ComponentInstanceDataDefinition implements PropertiesOwner {
private Map<String, List<CapabilityDefinition>> capabilities;
private Map<String, List<RequirementDefinition>> requirements;
@@ -43,6 +47,7 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement
private Map<String, Object> interfaces;
private List<PropertyDefinition> properties;
private CINodeFilterDataDefinition nodeFilter;
+ private SubstitutionFilterDataDefinition substitutionFilter;
private List<InputDefinition> inputs;
public ComponentInstance() {
@@ -53,26 +58,6 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement
super(r);
}
- public Map<String, List<CapabilityDefinition>> getCapabilities() {
- return capabilities;
- }
-
- public void setCapabilities(Map<String, List<CapabilityDefinition>> capabilities) {
- this.capabilities = capabilities;
- }
-
- public Map<String, List<RequirementDefinition>> getRequirements() {
- return requirements;
- }
-
- public void setRequirements(Map<String, List<RequirementDefinition>> requirements) {
- this.requirements = requirements;
- }
-
- public Map<String, ArtifactDefinition> getDeploymentArtifacts() {
- return deploymentArtifacts;
- }
-
public Map<String, ArtifactDefinition> safeGetDeploymentArtifacts() {
return deploymentArtifacts == null ? Collections.emptyMap() : deploymentArtifacts;
}
@@ -81,30 +66,10 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement
return artifacts == null ? Collections.emptyMap() : deploymentArtifacts;
}
- public void setDeploymentArtifacts(Map<String, ArtifactDefinition> deploymentArtifacts) {
- this.deploymentArtifacts = deploymentArtifacts;
- }
-
- public Map<String, ArtifactDefinition> getArtifacts() {
- return artifacts;
- }
-
public Map<String, ArtifactDefinition> safeGetArtifacts() {
return artifacts == null ? Collections.emptyMap() : artifacts;
}
- public void setArtifacts(Map<String, ArtifactDefinition> artifacts) {
- this.artifacts = artifacts;
- }
-
- public List<GroupInstance> getGroupInstances() {
- return groupInstances;
- }
-
- public void setGroupInstances(List<GroupInstance> groupInstances) {
- this.groupInstances = groupInstances;
- }
-
public String getActualComponentUid() {
return getIsProxy() ? getSourceModelUid() : getComponentUid();
}
@@ -116,57 +81,24 @@ public class ComponentInstance extends ComponentInstanceDataDefinition implement
return safeGetInformationalArtifacts().get(artifactLabel) != null;
}
- public Map<String, Object> getInterfaces() {
- return interfaces;
- }
-
- public void setInterfaces(Map<String, Object> interfaces) {
- this.interfaces = interfaces;
- }
-
public void addInterface(String interfaceName, Object interfaceDefinition) {
- if(MapUtils.isEmpty(this.interfaces)) {
+ if (MapUtils.isEmpty(this.interfaces)) {
this.interfaces = new HashMap<>();
}
-
this.interfaces.put(interfaceName, interfaceDefinition);
}
- public List<PropertyDefinition> getProperties() {
- return properties;
- }
-
- public void setProperties(List<PropertyDefinition> properties) {
- this.properties = properties;
- }
-
- public CINodeFilterDataDefinition getNodeFilter() {
- return nodeFilter;
- }
-
- public void setNodeFilter(CINodeFilterDataDefinition nodeFilter) {
- this.nodeFilter = nodeFilter;
- }
-
//supportability log method return map of component metadata teddy.h
- public Map<String,String> getComponentMetadataForSupportLog(){
- Map<String,String>componentMetadata=new HashMap<>();
- componentMetadata.put(ILogConfiguration.MDC_SUPPORTABLITY_COMPONENT_NAME,getName());
- componentMetadata.put(ILogConfiguration.MDC_SUPPORTABLITY_COMPONENT_VERSION,getVersion());
+ public Map<String, String> getComponentMetadataForSupportLog() {
+ Map<String, String> componentMetadata = new HashMap<>();
+ componentMetadata.put(ILogConfiguration.MDC_SUPPORTABLITY_COMPONENT_NAME, getName());
+ componentMetadata.put(ILogConfiguration.MDC_SUPPORTABLITY_COMPONENT_VERSION, getVersion());
componentMetadata.put(ILogConfiguration.MDC_SUPPORTABLITY_COMPONENT_UUID, getSourceModelUuid());
return componentMetadata;
}
- public boolean isCreatedFromCsar(){
+ public boolean isCreatedFromCsar() {
return CreatedFrom.CSAR.equals(this.getCreatedFrom());
}
- public List<InputDefinition> getInputs() {
- return inputs;
- }
-
- public void setInputs(List<InputDefinition> inputs) {
- this.inputs = inputs;
- }
-
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java
index 4e7903a890..f1785c76f8 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ComponentParametersView.java
@@ -50,7 +50,9 @@ public class ComponentParametersView {
private boolean ignoreServicePath = true;
private boolean ignorePolicies = false;
private boolean ignoreNodeFilterRequirements = false;
+ private boolean ignoreSubstitutionFilterRequirements = false;
private boolean ignoreNodeFilter = false;
+ private boolean ignoreSubstitutionFilter = false;
private boolean ignoreDataType = false;
public ComponentParametersView() {
@@ -95,6 +97,7 @@ public class ComponentParametersView {
this.setIgnoreCapabilities(false);
this.setIgnoreRequirements(false);
this.setIgnoreNodeFilter(false);
+ this.setIgnoreSubstitutionFilter(false);
this.setIgnoreCapabiltyProperties(false);
break;
case COMPONENT_INSTANCES_PROPERTIES:
@@ -153,6 +156,10 @@ public class ComponentParametersView {
this.setIgnoreNodeFilterRequirements(false);
this.setIgnoreNodeFilter(false);
break;
+ case SUBSTITUTION_FILTER:
+ this.setIgnoreSubstitutionFilterRequirements(false);
+ this.setIgnoreSubstitutionFilter(false);
+ break;
case COMPONENT_INSTANCES_INTERFACES:
this.setIgnoreComponentInstances(false);
this.setIgnoreComponentInstancesInterfaces(false);
@@ -216,6 +223,9 @@ public class ComponentParametersView {
if (ignoreNodeFilterRequirements){
component.setNodeFilterComponents(null);
}
+ if (ignoreSubstitutionFilterRequirements){
+ component.setSubstitutionFilterComponents(null);
+ }
if (ignoreInterfaces && ignoreInterfaceInstances &&
componentType == ComponentTypeEnum.RESOURCE) {
component.setInterfaces(null);
@@ -241,6 +251,9 @@ public class ComponentParametersView {
if (ignoreNodeFilter){
component.setNodeFilterComponents(null);
}
+ if (ignoreSubstitutionFilter){
+ component.setSubstitutionFilterComponents(null);
+ }
if (ignoreDataType) {
component.setDataTypes(null);
}
@@ -255,6 +268,14 @@ public class ComponentParametersView {
this.ignoreNodeFilterRequirements = ignoreNodeFilter;
}
+ public boolean isIgnoreSubstitutionFilterRequirements() {
+ return ignoreSubstitutionFilterRequirements;
+ }
+
+ public void setIgnoreSubstitutionFilterRequirements(boolean ignoreSubstitutionFilterRequirements) {
+ this.ignoreSubstitutionFilterRequirements = ignoreSubstitutionFilterRequirements;
+ }
+
public void disableAll() {
ignoreUsers = true;
ignoreGroups = true;
@@ -278,7 +299,9 @@ public class ComponentParametersView {
ignoreCapabiltyProperties = true;
ignoreServicePath = true;
ignoreNodeFilterRequirements = true;
+ ignoreSubstitutionFilterRequirements = true;
ignoreNodeFilter = true;
+ ignoreSubstitutionFilter = true;
ignoreDataType = true;
}
@@ -462,6 +485,14 @@ public class ComponentParametersView {
this.ignoreNodeFilter = ignoreNodeFilter;
}
+ public boolean isIgnoreSubstitutionFilter() {
+ return ignoreSubstitutionFilter;
+ }
+
+ public void setIgnoreSubstitutionFilter(boolean ignoreSubstitutionFilter) {
+ this.ignoreSubstitutionFilter = ignoreSubstitutionFilter;
+ }
+
public boolean isIgnoreDataType() {
return ignoreDataType;
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/datamodel/TopologyTemplate.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/datamodel/TopologyTemplate.java
index a02b07df15..db330e9b19 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/datamodel/TopologyTemplate.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/datamodel/TopologyTemplate.java
@@ -60,6 +60,7 @@ public class TopologyTemplate extends ToscaElement{
private Map<String, DataTypeDataDefinition> dataTypes;
private Map<String, CINodeFilterDataDefinition> nodeFilterComponents;
+ private Map<String, SubstitutionFilterDataDefinition> substitutionFilterDataDefinitionMap;
//Component Instances External References (instanceId -> ExternalRefsMap)
//-----------------------------------------------------------------------
private Map<String, MapComponentInstanceExternalRefs> mapComponentInstancesExternalRefs;
@@ -240,6 +241,15 @@ public class TopologyTemplate extends ToscaElement{
this.nodeFilterComponents = nodeFilters;
}
+ public Map<String, SubstitutionFilterDataDefinition> getSubstitutionFilterDataDefinitionMap() {
+ return substitutionFilterDataDefinitionMap;
+ }
+
+ public void setSubstitutionFilterDataDefinitionMap(
+ Map<String, SubstitutionFilterDataDefinition> substitutionFilterDataDefinitionMap) {
+ this.substitutionFilterDataDefinitionMap = substitutionFilterDataDefinitionMap;
+ }
+
/**
* Gets data types.
* @return Current data types.
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/BaseOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/BaseOperation.java
index 14ce6be609..9e12e6e67d 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/BaseOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/BaseOperation.java
@@ -882,7 +882,12 @@ public abstract class BaseOperation {
}
@SuppressWarnings("unchecked")
- private <T extends ToscaDataDefinition> StorageOperationStatus updateOrAddToscaData(GraphVertex toscaElement, EdgeLabelEnum edgeLabel, VertexTypeEnum vertexLabel, List<T> toscaDataList, JsonPresentationFields mapKeyField, boolean isUpdate) {
+ private <T extends ToscaDataDefinition> StorageOperationStatus updateOrAddToscaData(GraphVertex toscaElement,
+ EdgeLabelEnum edgeLabel,
+ VertexTypeEnum vertexLabel,
+ List<T> toscaDataList,
+ JsonPresentationFields mapKeyField,
+ boolean isUpdate) {
StorageOperationStatus result = null;
GraphVertex toscaDataVertex = null;
Map<String, T> existingToscaDataMap = null;
@@ -892,7 +897,9 @@ public abstract class BaseOperation {
.getChildVertex(toscaElement, edgeLabel, JsonParseFlagEnum.ParseJson);
if (toscaDataVertexRes.isRight() && toscaDataVertexRes.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
JanusGraphOperationStatus status = toscaDataVertexRes.right().value();
- CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG, FAILED_TO_GET_CHILD_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS, toscaElement.getUniqueId(), edgeLabel, status);
+ CommonUtility.addRecordToLog(log, LogLevelEnum.DEBUG,
+ FAILED_TO_GET_CHILD_VERTEX_OF_THE_TOSCA_ELEMENT_BY_LABEL_STATUS_IS, toscaElement.getUniqueId(),
+ edgeLabel, status);
result = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(toscaDataVertexRes.right().value());
}
if (result == null) {
@@ -1423,14 +1430,6 @@ public abstract class BaseOperation {
return status;
}
-// public StorageOperationStatus updateDataOnGraph(GraphVertex dataVertex) {
-// Either<GraphVertex, JanusGraphOperationStatus> updateVertex = janusGraphDao.updateVertex(dataVertex);
-// if (updateVertex.isRight()) {
-// return DaoStatusConverter.convertJanusGraphStatusToStorageStatus(updateVertex.right().value());
-// }
-// return StorageOperationStatus.OK;
-// }
-
protected GroupInstanceDataDefinition buildGroupInstanceDataDefinition(GroupDataDefinition group, ComponentInstanceDataDefinition componentInstance, Map<String, ArtifactDataDefinition> instDeplArtifMap) {
String componentInstanceName = componentInstance.getName();
@@ -1449,21 +1448,6 @@ public abstract class BaseOperation {
groupInstance.setUniqueId(UniqueIdBuilder.buildResourceInstanceUniuqeId(componentInstance.getUniqueId(), groupUid, groupInstance.getNormalizedName()));
groupInstance.setArtifacts(group.getArtifacts());
-// List<String> fixedArtifactsUuid;
-// List<String> artifactsUuid = group.getArtifactsUuid();
-// if (instDeplArtifMap != null) {
-// fixedArtifactsUuid = new ArrayList<>();
-// artifactsUuid.forEach(u -> {
-// Optional<ArtifactDataDefinition> findFirst = instDeplArtifMap.values().stream().filter(a -> u.equals(a.getUniqueId())).findFirst();
-// if (findFirst.isPresent()) {
-// fixedArtifactsUuid.add(findFirst.get().getArtifactUUID());
-// } else {
-// fixedArtifactsUuid.add(u);
-// }
-// });
-// } else {
-// fixedArtifactsUuid = artifactsUuid;
-// }
groupInstance.setArtifactsUuid(group.getArtifactsUuid());
groupInstance.setProperties(group.getProperties());
convertPropertiesToInstanceProperties(groupInstance.getProperties());
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeFilterOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeFilterOperation.java
index 5f0284a159..69c9f4e59d 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeFilterOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeFilterOperation.java
@@ -41,7 +41,7 @@ import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
import org.openecomp.sdc.common.log.wrappers.Logger;
-@org.springframework.stereotype.Component("service-filter-operations")
+@org.springframework.stereotype.Component("node-filter-operations")
public class NodeFilterOperation extends BaseOperation {
private static Logger logger = Logger.getLogger(NodeFilterOperation.class);
@@ -82,14 +82,16 @@ public class NodeFilterOperation extends BaseOperation {
}
- public Either<CINodeFilterDataDefinition, StorageOperationStatus> createNodeFilter(String serviceId,
- String componentInstanceId) {
+ public Either<CINodeFilterDataDefinition, StorageOperationStatus> createNodeFilter(final String componentId,
+ final String componentInstanceId) {
CINodeFilterDataDefinition nodeFilterDataDefinition = new CINodeFilterDataDefinition();
- return addOrUpdateNodeFilter(false, serviceId, componentInstanceId, nodeFilterDataDefinition);
+ return addOrUpdateNodeFilter(false, componentId, componentInstanceId, nodeFilterDataDefinition);
}
- public Either<CINodeFilterDataDefinition, StorageOperationStatus> deleteConstraint(String serviceId,
- String componentInstanceId, CINodeFilterDataDefinition nodeFilterDataDefinition, int propertyIndex) {
+ public Either<CINodeFilterDataDefinition, StorageOperationStatus> deleteConstraint(final String serviceId,
+ final String componentInstanceId,
+ final CINodeFilterDataDefinition nodeFilterDataDefinition,
+ final int propertyIndex) {
ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> properties =
nodeFilterDataDefinition.getProperties();
properties.getListToscaDataDefinition().remove(propertyIndex);
@@ -113,9 +115,11 @@ public class NodeFilterOperation extends BaseOperation {
return addOrUpdateNodeFilter(true, componentId, componentInstanceId, nodeFilterDataDefinition);
}
- public Either<CINodeFilterDataDefinition, StorageOperationStatus> updateProperties(String serviceId,
- String componentInstanceId, CINodeFilterDataDefinition nodeFilterDataDefinition,
- List<RequirementNodeFilterPropertyDataDefinition> requirementNodeFilterPropertyDataDefinition) {
+ public Either<CINodeFilterDataDefinition, StorageOperationStatus> updateProperties(
+ final String serviceId, final String componentInstanceId,
+ final CINodeFilterDataDefinition nodeFilterDataDefinition,
+ final List<RequirementNodeFilterPropertyDataDefinition> requirementNodeFilterPropertyDataDefinition) {
+
ListDataDefinition<RequirementNodeFilterPropertyDataDefinition> properties =
nodeFilterDataDefinition.getProperties();
properties.getListToscaDataDefinition().clear();
@@ -124,22 +128,24 @@ public class NodeFilterOperation extends BaseOperation {
return addOrUpdateNodeFilter(true, serviceId, componentInstanceId, nodeFilterDataDefinition);
}
- public Either<CINodeFilterDataDefinition, StorageOperationStatus> updateNodeFilter(String serviceId,
- String componentInstanceId, CINodeFilterDataDefinition ciNodeFilterDataDefinition) {
+ public Either<CINodeFilterDataDefinition, StorageOperationStatus> updateNodeFilter(final String serviceId,
+ final String componentInstanceId,
+ final CINodeFilterDataDefinition ciNodeFilterDataDefinition) {
return addOrUpdateNodeFilter(true, serviceId, componentInstanceId, ciNodeFilterDataDefinition);
}
- private Either<CINodeFilterDataDefinition, StorageOperationStatus> addOrUpdateNodeFilter(boolean isUpdateAction,
- String serviceId, String componentInstanceId, CINodeFilterDataDefinition ciNodeFilterDataDefinition) {
+ private Either<CINodeFilterDataDefinition, StorageOperationStatus> addOrUpdateNodeFilter(
+ final boolean isUpdateAction, final String componentId, final String componentInstanceId,
+ final CINodeFilterDataDefinition ciNodeFilterDataDefinition) {
StorageOperationStatus statusRes;
Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
- getToscaElementRes = janusGraphDao.getVertexById(serviceId, JsonParseFlagEnum.NoParse);
+ getToscaElementRes = janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.NoParse);
if (getToscaElementRes.isRight()) {
JanusGraphOperationStatus status = getToscaElementRes.right().value();
CommonUtility.addRecordToLog(logger, CommonUtility.LogLevelEnum.DEBUG,
- "Failed to get tosca element {} upon adding the properties. Status is {}. ", serviceId, status);
+ "Failed to get tosca element {} upon adding the properties. Status is {}. ", componentId, status);
statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
return Either.right(statusRes);
}
@@ -150,23 +156,22 @@ public class NodeFilterOperation extends BaseOperation {
janusGraphDao.rollback();
logger.error(
" Failed to perform tosca update for node filter in service {} , component instance {}. status is {}",
- serviceId, componentInstanceId, statusRes);
+ componentId, componentInstanceId, statusRes);
return Either.right(statusRes);
}
janusGraphDao.commit();
return Either.left(ciNodeFilterDataDefinition);
-
}
-
- private StorageOperationStatus performUpdateToscaAction(boolean isUpdate, GraphVertex graphVertex,
- List<CINodeFilterDataDefinition> toscaDataList) {
+ private StorageOperationStatus performUpdateToscaAction(final boolean isUpdate,
+ final GraphVertex graphVertex,
+ final List<CINodeFilterDataDefinition> toscaDataList) {
if (isUpdate) {
return updateToscaDataOfToscaElement(graphVertex, EdgeLabelEnum.NODE_FILTER_TEMPLATE,
- VertexTypeEnum.NODE_FILTER_TEMPLATE, toscaDataList, JsonPresentationFields.UNIQUE_ID);
+ VertexTypeEnum.NODE_FILTER_TEMPLATE, toscaDataList, JsonPresentationFields.UNIQUE_ID);
} else {
return addToscaDataToToscaElement(graphVertex, EdgeLabelEnum.NODE_FILTER_TEMPLATE,
- VertexTypeEnum.NODE_FILTER_TEMPLATE, toscaDataList, JsonPresentationFields.UNIQUE_ID);
+ VertexTypeEnum.NODE_FILTER_TEMPLATE, toscaDataList, JsonPresentationFields.UNIQUE_ID);
}
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/SubstitutionFilterOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/SubstitutionFilterOperation.java
new file mode 100644
index 0000000000..9007e20998
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/SubstitutionFilterOperation.java
@@ -0,0 +1,139 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.model.jsonjanusgraph.operations;
+
+import com.google.common.collect.ImmutableList;
+import fj.data.Either;
+import java.util.List;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
+import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
+import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
+import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
+import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
+import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
+import org.openecomp.sdc.common.log.enums.EcompErrorSeverity;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+
+@org.springframework.stereotype.Component("substitution-filter-operations")
+public class SubstitutionFilterOperation extends BaseOperation {
+
+ private static final Logger LOGGER = Logger.getLogger(SubstitutionFilterOperation.class);
+
+ public Either<SubstitutionFilterDataDefinition, StorageOperationStatus> createSubstitutionFilter(
+ final String componentId, final String componentInstanceId) {
+
+ return addOrUpdateSubstitutionFilter(false, componentId, componentInstanceId,
+ new SubstitutionFilterDataDefinition());
+ }
+
+ public Either<SubstitutionFilterDataDefinition, StorageOperationStatus> deleteConstraint(
+ final String serviceId, final String componentInstanceId,
+ final SubstitutionFilterDataDefinition substitutionFilterDataDefinition, final int propertyIndex) {
+
+ final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> properties =
+ substitutionFilterDataDefinition.getProperties();
+ properties.getListToscaDataDefinition().remove(propertyIndex);
+ substitutionFilterDataDefinition.setProperties(properties);
+ return addOrUpdateSubstitutionFilter(true, serviceId, componentInstanceId, substitutionFilterDataDefinition);
+ }
+
+ public Either<SubstitutionFilterDataDefinition, StorageOperationStatus> addNewProperty(
+ final String componentId, final String componentInstanceId,
+ final SubstitutionFilterDataDefinition substitutionFilterDataDefinition,
+ final RequirementSubstitutionFilterPropertyDataDefinition requirementSubstitutionFilterPropertyDataDefinition) {
+
+ ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> properties =
+ substitutionFilterDataDefinition.getProperties();
+ if (properties == null) {
+ properties = new ListDataDefinition<>();
+ substitutionFilterDataDefinition.setProperties(properties);
+ }
+ properties.getListToscaDataDefinition().add(requirementSubstitutionFilterPropertyDataDefinition);
+ substitutionFilterDataDefinition.setProperties(properties);
+ return addOrUpdateSubstitutionFilter(true, componentId, componentInstanceId, substitutionFilterDataDefinition);
+ }
+
+ public Either<SubstitutionFilterDataDefinition, StorageOperationStatus> updateSubstitutionFilter(
+ final String serviceId, final String componentInstanceId,
+ final SubstitutionFilterDataDefinition substitutionFilterDataDefinition,
+ final List<RequirementSubstitutionFilterPropertyDataDefinition> requirementSubstitutionFilterPropertyDataDefinitions) {
+
+ final ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> properties =
+ substitutionFilterDataDefinition.getProperties();
+ properties.getListToscaDataDefinition().clear();
+ properties.getListToscaDataDefinition().addAll(requirementSubstitutionFilterPropertyDataDefinitions);
+ substitutionFilterDataDefinition.setProperties(properties);
+ return addOrUpdateSubstitutionFilter(true, serviceId, componentInstanceId,
+ substitutionFilterDataDefinition);
+ }
+
+ private Either<SubstitutionFilterDataDefinition, StorageOperationStatus> addOrUpdateSubstitutionFilter(
+ final boolean isUpdateAction, final String componentId, final String componentInstanceId,
+ final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
+
+ StorageOperationStatus statusRes;
+ Either<GraphVertex, JanusGraphOperationStatus> getToscaElementRes;
+
+ getToscaElementRes = janusGraphDao.getVertexById(componentId, JsonParseFlagEnum.NoParse);
+ if (getToscaElementRes.isRight()) {
+ final JanusGraphOperationStatus status = getToscaElementRes.right().value();
+ CommonUtility.addRecordToLog(LOGGER, CommonUtility.LogLevelEnum.DEBUG,
+ "Failed to get tosca element {} upon adding the properties. Status is {}. ", componentId, status);
+ statusRes = DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status);
+ return Either.right(statusRes);
+ }
+ final GraphVertex serviceVertex = getToscaElementRes.left().value();
+ substitutionFilterDataDefinition.setID(componentInstanceId);
+ statusRes = performUpdateToscaAction(isUpdateAction, serviceVertex,
+ ImmutableList.of(substitutionFilterDataDefinition));
+ if (!statusRes.equals(StorageOperationStatus.OK)) {
+ janusGraphDao.rollback();
+ LOGGER.error(EcompErrorSeverity.ERROR, EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR,
+ " Failed to perform tosca update for substitution filter in service {} , component instance {}. status is {}",
+ componentId, componentInstanceId, statusRes);
+ return Either.right(statusRes);
+ }
+ janusGraphDao.commit();
+ return Either.left(substitutionFilterDataDefinition);
+ }
+
+ private StorageOperationStatus performUpdateToscaAction(final boolean isUpdate,
+ final GraphVertex graphVertex,
+ final List<SubstitutionFilterDataDefinition> toscaDataList) {
+ if (isUpdate) {
+ return updateToscaDataOfToscaElement(graphVertex, EdgeLabelEnum.SUBSTITUTION_FILTER_TEMPLATE,
+ VertexTypeEnum.SUBSTITUTION_FILTER_TEMPLATE, toscaDataList, JsonPresentationFields.UNIQUE_ID);
+ } else {
+ return addToscaDataToToscaElement(graphVertex, EdgeLabelEnum.SUBSTITUTION_FILTER_TEMPLATE,
+ VertexTypeEnum.SUBSTITUTION_FILTER_TEMPLATE, toscaDataList, JsonPresentationFields.UNIQUE_ID);
+ }
+ }
+
+}
+
+
+
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/TopologyTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/TopologyTemplateOperation.java
index 3f28d72ef4..cc6cd1d430 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/TopologyTemplateOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/TopologyTemplateOperation.java
@@ -31,15 +31,6 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.stream.Collectors;
import org.apache.commons.collections.MapUtils;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -48,8 +39,6 @@ import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum;
-import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
-import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.AdditionalInfoParameterDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
@@ -62,13 +51,16 @@ 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;
import org.openecomp.sdc.be.datatypes.elements.MapGroupsDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.MapInterfaceDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.MapListRequirementDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.MapPropertiesDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.PolicyDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
@@ -791,6 +783,14 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
}
}
+ if (!componentParametersView.isIgnoreSubstitutionFilter()) {
+ status = setSubstitutionFilterComponentFromGraph(componentV, toscaElement);
+ if (status != JanusGraphOperationStatus.OK) {
+ return Either.right(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
+
+ }
+ }
+
if (!componentParametersView.isIgnoreInterfaces()) {
JanusGraphOperationStatus storageStatus = setInterfacesFromGraph(componentV, toscaElement);
if (storageStatus != JanusGraphOperationStatus.OK) {
@@ -996,11 +996,11 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
return JanusGraphOperationStatus.OK;
}
- private JanusGraphOperationStatus setNodeFilterComponentFromGraph(GraphVertex componentV,
- TopologyTemplate topologyTemplate) {
- Either<Map<String, CINodeFilterDataDefinition>, JanusGraphOperationStatus> result =
- getDataFromGraph(componentV,
- EdgeLabelEnum.NODE_FILTER_TEMPLATE);
+ private JanusGraphOperationStatus setNodeFilterComponentFromGraph(final GraphVertex componentV,
+ final TopologyTemplate topologyTemplate) {
+
+ final Either<Map<String, CINodeFilterDataDefinition>, JanusGraphOperationStatus> result =
+ getDataFromGraph(componentV, EdgeLabelEnum.NODE_FILTER_TEMPLATE);
if (result.isLeft()) {
topologyTemplate.setNodeFilterComponents(result.left().value());
} else {
@@ -1011,6 +1011,22 @@ public class TopologyTemplateOperation extends ToscaElementOperation {
return JanusGraphOperationStatus.OK;
}
+ private JanusGraphOperationStatus setSubstitutionFilterComponentFromGraph(final GraphVertex componentV,
+ final TopologyTemplate topologyTemplate) {
+
+ final Either<Map<String, SubstitutionFilterDataDefinition>, JanusGraphOperationStatus> result =
+ getDataFromGraph(componentV, EdgeLabelEnum.SUBSTITUTION_FILTER_TEMPLATE);
+ if (result.isLeft()) {
+ topologyTemplate.setSubstitutionFilterDataDefinitionMap(result.left().value());
+ } else {
+ if (result.right().value() != JanusGraphOperationStatus.NOT_FOUND) {
+ return result.right().value();
+ }
+ }
+ return JanusGraphOperationStatus.OK;
+ }
+
+
@Override
protected <T extends ToscaElement> JanusGraphOperationStatus setRequirementsFromGraph(GraphVertex componentV, T toscaElement) {
Either<Map<String, MapListRequirementDataDefinition>, JanusGraphOperationStatus> result = getDataFromGraph(componentV, EdgeLabelEnum.CALCULATED_REQUIREMENTS);
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java
index ae854254c2..272d664b8e 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java
@@ -71,6 +71,7 @@ import org.openecomp.sdc.be.datatypes.elements.ProductMetadataDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.RelationshipInstDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.CreatedFrom;
import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
@@ -217,6 +218,9 @@ public class ModelConverter {
convertDataTypes(topologyTemplate, service);
convertNodeFiltersComponents(topologyTemplate, service);
+
+ convertSubstitutionFiltersComponents(topologyTemplate, service);
+
setCapabilitiesToComponent(topologyTemplate, service);
setRequirementsToComponent(topologyTemplate, service);
return service;
@@ -879,17 +883,33 @@ public class ModelConverter {
component.setDeploymentArtifacts(copy);
}
- private static void convertNodeFiltersComponents(TopologyTemplate topologyTemplate, Component component) {
- Map<String, CINodeFilterDataDefinition> filters = topologyTemplate.getNodeFilterComponents();
- Map<String, CINodeFilterDataDefinition> copy;
- if (filters != null) {
- copy = filters.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new CINodeFilterDataDefinition(e.getValue())));
+ private static void convertNodeFiltersComponents(final TopologyTemplate topologyTemplate,
+ final Component component) {
+ final Map<String, CINodeFilterDataDefinition> filters = topologyTemplate.getNodeFilterComponents();
+ final Map<String, CINodeFilterDataDefinition> copy;
+ if (MapUtils.isNotEmpty(filters)) {
+ copy = filters.entrySet().stream()
+ .collect(Collectors.toMap(Map.Entry::getKey, e -> new CINodeFilterDataDefinition(e.getValue())));
} else {
copy = new HashMap<>();
}
component.setNodeFilterComponents(copy);
}
+ private static void convertSubstitutionFiltersComponents(final TopologyTemplate topologyTemplate,
+ final Component component) {
+ final Map<String, SubstitutionFilterDataDefinition> filters = topologyTemplate
+ .getSubstitutionFilterDataDefinitionMap();
+ final Map<String, SubstitutionFilterDataDefinition> copy;
+ if (MapUtils.isNotEmpty(filters)) {
+ copy = filters.entrySet().stream()
+ .collect(Collectors.toMap(Map.Entry::getKey, e -> new SubstitutionFilterDataDefinition(e.getValue())));
+ } else {
+ copy = new HashMap<>();
+ }
+ component.setSubstitutionFilterComponents(copy);
+ }
+
private static void convertServiceApiArtifacts(TopologyTemplate topologyTemplate, Service service) {
Map<String, ArtifactDataDefinition> serviceApiArtifacts = topologyTemplate.getServiceApiArtifacts();
Map<String, ArtifactDefinition> copy;
@@ -1328,6 +1348,8 @@ public class ModelConverter {
List<ComponentInstance> componentInstances = new ArrayList<>();
ComponentInstance currComponentInstance;
Map<String, CINodeFilterDataDefinition> nodeFilterComponents = topologyTemplate.getNodeFilterComponents();
+ Map<String, SubstitutionFilterDataDefinition> substitutionFilterDataDefinitionMap = topologyTemplate
+ .getSubstitutionFilterDataDefinitionMap();
for (Map.Entry<String, ComponentInstanceDataDefinition> entry : topologyTemplate.getComponentInstances().entrySet()) {
String key = entry.getKey();
@@ -1337,9 +1359,12 @@ public class ModelConverter {
currComponentInstance.setGroupInstances(groupInstances);
}
setComponentInstanceSource(currComponentInstance, component);
- if(nodeFilterComponents != null && nodeFilterComponents.containsKey(key)){
+ if(MapUtils.isNotEmpty(nodeFilterComponents) && nodeFilterComponents.containsKey(key)){
currComponentInstance.setNodeFilter(nodeFilterComponents.get(key));
}
+ if(MapUtils.isNotEmpty(substitutionFilterDataDefinitionMap) && substitutionFilterDataDefinitionMap.containsKey(key)) {
+ currComponentInstance.setSubstitutionFilter(substitutionFilterDataDefinitionMap.get(key));
+ }
if(topologyTemplate.getInstProperties() != null && topologyTemplate.getInstProperties().containsKey(key) && topologyTemplate.getInstProperties().get(key) != null ){
List<PropertyDefinition> instanceProps = topologyTemplate.getInstProperties().get(key).getMapToscaDataDefinition().entrySet().stream().map(e -> new PropertyDefinition(e.getValue())).collect(Collectors.toList());
currComponentInstance.setProperties(instanceProps);
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java
index 38d5a90742..f03a5e724f 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/ui/model/UiComponentDataTransfer.java
@@ -26,6 +26,7 @@ import java.util.Map;
import lombok.Getter;
import lombok.Setter;
import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.model.AdditionalInformationDefinition;
import org.openecomp.sdc.be.model.ArtifactDefinition;
@@ -71,8 +72,10 @@ public class UiComponentDataTransfer {
private Map<String, InterfaceDefinition> interfaces;
private Map<String, CINodeFilterDataDefinition> nodeFilter;
+ private Map<String, SubstitutionFilterDataDefinition> substitutionFilter;
private Map<String, UINodeFilter> nodeFilterforNode;
+ private Map<String, UINodeFilter> substitutionFilterForTopologyTemplate;
private List<PropertyDefinition> properties;
private Map<String, List<ComponentInstanceInterface>> componentInstancesInterfaces;