summaryrefslogtreecommitdiffstats
path: root/winery/org.eclipse.winery.topologymodeler/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'winery/org.eclipse.winery.topologymodeler/src/main/java')
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/WineryUtil.java87
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/DeferredAnalyzer.java60
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/PlaceHolderAnalyzer.java52
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/RequirementAnalyzer.java117
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/TOSCAAnalyzer.java146
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/package-info.java17
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Constants.java89
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java374
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/NodeTemplateConnector.java86
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/RESTHelper.java97
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Utils.java127
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/package-info.java17
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/package-info.java16
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/placeholderhandling/PlaceHolderHandler.java74
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionInterface.java257
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionManager.java358
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/DeferredCompleter.java218
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/PlaceHolderCompleter.java188
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/RequirementCompleter.java108
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/StepByStepCompleter.java203
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/package-info.java17
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/package-info.java17
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/TopologyCompletionResource.java136
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/package-info.java4
24 files changed, 2865 insertions, 0 deletions
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/WineryUtil.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/WineryUtil.java
new file mode 100644
index 0000000..2dc7e27
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/WineryUtil.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 University of Stuttgart.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Oliver Kopp - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.winery.topologymodeler;
+
+import java.util.List;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.eclipse.winery.common.interfaces.QNameWithName;
+
+public class WineryUtil {
+
+ /**
+ * LocalName is the ID of the element, whereas Name is the speaking name
+ */
+ public static class LocalNameNamePair implements Comparable<LocalNameNamePair> {
+
+ String localName;
+ String name;
+
+
+ public LocalNameNamePair(String localName, String name) {
+ this.localName = localName;
+ this.name = name;
+ }
+
+ public String getLocalName() {
+ return this.localName;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Ordering according to name
+ */
+ @Override
+ public int compareTo(LocalNameNamePair otherPair) {
+ return this.name.compareTo(otherPair.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.localName.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof LocalNameNamePair) {
+ return this.localName.equals(((LocalNameNamePair) o).getLocalName());
+ } else {
+ return false;
+ }
+ }
+ }
+
+
+ public static SortedMap<String, SortedSet<LocalNameNamePair>> convertQNameWithNameListToNamespaceToLocalNameNamePairList(List<QNameWithName> list) {
+ if (list == null) {
+ throw new IllegalArgumentException("list may not be null");
+ }
+ SortedMap<String, SortedSet<LocalNameNamePair>> res = new TreeMap<>();
+ for (QNameWithName qnameWithName : list) {
+ SortedSet<LocalNameNamePair> localNameNamePairSet = res.get(qnameWithName.qname.getNamespaceURI());
+ if (localNameNamePairSet == null) {
+ localNameNamePairSet = new TreeSet<>();
+ res.put(qnameWithName.qname.getNamespaceURI(), localNameNamePairSet);
+ }
+ LocalNameNamePair pair = new LocalNameNamePair(qnameWithName.qname.getLocalPart(), qnameWithName.name);
+ localNameNamePairSet.add(pair);
+ }
+ return res;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/DeferredAnalyzer.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/DeferredAnalyzer.java
new file mode 100644
index 0000000..c4db9bb
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/DeferredAnalyzer.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Constants;
+
+/**
+ * This class contains a method to analyze a TOSCA {@link TTopologyTemplate} for
+ * the occurrence of "Deferred"-{@link TRelationshipTemplate}s.
+ *
+ * A "Deferred"-{@link TRelationshipTemplate} serves as place holder for any number of Node or Relationship
+ * Templates.
+ */
+public class DeferredAnalyzer {
+
+ /**
+ * Iterates over all {@link TRelationshipTemplate} and checks if its type is "deferred".
+ *
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ *
+ * @return a list of found deferred {@link TRelationshipTemplate}s
+ */
+ public static List<TRelationshipTemplate> analyzeDeferredRelations(TOSCAAnalyzer toscaAnalyzer) {
+
+ List<TRelationshipTemplate> foundDeferredRelations = new ArrayList<TRelationshipTemplate>();
+
+ for (TRelationshipTemplate relationshipTemplate : toscaAnalyzer.getRelationshipTemplates()) {
+ if (relationshipTemplate.getType() != null && relationshipTemplate.getType().getLocalPart().equals(Constants.DEFERRED_QNAME.getLocalPart()) &&
+ relationshipTemplate.getType().getNamespaceURI().equals(Constants.DEFERRED_QNAME.getNamespaceURI())) {
+
+ // TODO: This step has to be done until the "Provisioning-API"
+ // is implemented. The Deferred RelationshipTemplate can only be
+ // completed if Requirements exist at the source template.
+ TNodeTemplate source = (TNodeTemplate) relationshipTemplate.getSourceElement().getRef();
+
+ if (source.getRequirements() != null) {
+ foundDeferredRelations.add(relationshipTemplate);
+ }
+ }
+ }
+ return foundDeferredRelations;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/PlaceHolderAnalyzer.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/PlaceHolderAnalyzer.java
new file mode 100644
index 0000000..ddf0e91
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/PlaceHolderAnalyzer.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Constants;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Utils;
+
+/**
+ * This class analyzes the occurrence of place holders in a topology and writes them to an {@link ArrayList}.
+ */
+public class PlaceHolderAnalyzer {
+
+ /**
+ * This method searches {@link TNodeTemplate}s that are derived from the abstract "PlaceHolder" type and adds them to a list.
+ *
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ *
+ * @return the found place holders of the topology as a list.
+ */
+ public static List<TNodeTemplate> analyzePlaceHolders(TOSCAAnalyzer toscaAnalyzer) {
+
+ List<TNodeTemplate> foundPlaceHolders = new ArrayList<TNodeTemplate>();
+
+ // Check the type of the NodeTemplates, write them to a list if the type is derived from the common place holder type.
+ for (TNodeTemplate nodeTemplate : toscaAnalyzer.getNodeTemplates()) {
+
+ TNodeType nodeType = Utils.getNodeTypeForId(toscaAnalyzer.getNodeTypes(), nodeTemplate.getType());
+
+ if (nodeType != null && nodeType.getDerivedFrom() != null && nodeType.getDerivedFrom().getTypeRef().getLocalPart().equals(Constants.PLACE_HOLDER_QNAME.getLocalPart()) &&
+ nodeType.getDerivedFrom().getTypeRef().getNamespaceURI().equals(Constants.PLACE_HOLDER_QNAME.getNamespaceURI())) {
+ foundPlaceHolders.add(nodeTemplate);
+ }
+ }
+ return foundPlaceHolders;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/RequirementAnalyzer.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/RequirementAnalyzer.java
new file mode 100644
index 0000000..71f3961
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/RequirementAnalyzer.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.winery.model.tosca.TCapability;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TRequirement;
+import org.eclipse.winery.model.tosca.TRequirementDefinition;
+import org.eclipse.winery.model.tosca.TRequirementType;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Utils;
+
+/**
+ * This class analyzes the occurrence of TOSCA {@link TRequirement}s in a {@link TTopologyTemplate} and checks whether they
+ * are already fulfilled or not.
+ */
+public class RequirementAnalyzer {
+
+ /**
+ * This method checks if {@link TNodeTemplate}s contain {@link TRequirement}s and adds them to a {@link Map}.
+ *
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ *
+ * @return a map containing {@link TNodeTemplate}s and their {@link TRequirement}s
+ */
+ public static Map<TRequirement, TNodeTemplate> analyzeRequirements(TOSCAAnalyzer toscaAnalyzer) {
+
+ // map containing entries for a Requirement and its corresponding NodeTemplate
+ Map<TRequirement, TNodeTemplate> unfulfilledRequirements = new HashMap<TRequirement, TNodeTemplate>();
+
+ for (TNodeTemplate nodeTemplate : toscaAnalyzer.getNodeTemplates()) {
+
+ List<TRequirement> requirements = new ArrayList<>();
+
+ TNodeType nodeType = Utils.getNodeTypeForId(toscaAnalyzer.getNodeTypes(), nodeTemplate.getType());
+
+ if (nodeType.getRequirementDefinitions() != null && !nodeType.getRequirementDefinitions().getRequirementDefinition().isEmpty()) {
+
+ List<TRequirementDefinition> requirementDefinitions = nodeType.getRequirementDefinitions().getRequirementDefinition();
+
+ // check the requirements of the type of the used NodeTemplate
+ for (TRequirementDefinition requirementDefinition: requirementDefinitions) {
+ TRequirement requirement = new TRequirement();
+ requirement.setType(requirementDefinition.getRequirementType());
+ requirement.setName(requirementDefinition.getName());
+ requirement.setId(Utils.createRandomID());
+ }
+ }
+
+ if (nodeTemplate.getRequirements() != null && !nodeTemplate.getRequirements().getRequirement().isEmpty()) {
+ requirements.addAll(nodeTemplate.getRequirements().getRequirement());
+ }
+
+ if (!requirements.isEmpty()) {
+ // list containing the RelationshipTemplates connecting to the NodeTemplate
+ List<TRelationshipTemplate> connectors = new ArrayList<TRelationshipTemplate>();
+
+ // add the connected RelationshipTemplates
+ for (TRelationshipTemplate connector : toscaAnalyzer.getRelationshipTemplates()) {
+ if (connector.getSourceElement().getRef().equals(nodeTemplate)) {
+ connectors.add(connector);
+ }
+ }
+
+ // add requirements of unconnected NodeTemplates to the map because they can't be fulfilled
+ if (connectors.size() == 0) {
+ for (TRequirement requirement : requirements) {
+ unfulfilledRequirements.put(requirement, nodeTemplate);
+ }
+ } else {
+ boolean fulfilled = false;
+
+ // check if one of the connected NodeTemplates already fulfill the requirement
+ for (TRequirement requirement : requirements) {
+ for (TRelationshipTemplate connector : connectors) {
+ TNodeTemplate connectedNodeTemplate = (TNodeTemplate) connector.getTargetElement().getRef();
+ if (connectedNodeTemplate.getCapabilities() != null) {
+ for (TCapability capa : connectedNodeTemplate.getCapabilities().getCapability()) {
+ for (TRequirementType reqType : toscaAnalyzer.getRequirementTypes()) {
+ if (requirement.getType().getLocalPart().equals(reqType.getName())) {
+ if (reqType.getRequiredCapabilityType().getLocalPart().equals(capa.getType().getLocalPart())
+ && reqType.getRequiredCapabilityType().getNamespaceURI().equals(capa.getType().getNamespaceURI())) {
+ fulfilled = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!fulfilled) {
+ unfulfilledRequirements.put(requirement, nodeTemplate);
+ }
+ }
+ }
+ }
+ }
+ return unfulfilledRequirements;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/TOSCAAnalyzer.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/TOSCAAnalyzer.java
new file mode 100644
index 0000000..45131a7
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/TOSCAAnalyzer.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipType;
+import org.eclipse.winery.model.tosca.TRequirement;
+import org.eclipse.winery.model.tosca.TRequirementType;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+
+/**
+ * This class contains several methods to analyze the content of a TOSCA {@link TTopologyTemplate} and to fill a data model
+ * with the analyzed information. This class serves the access to all types and templates of a topology.
+ */
+public class TOSCAAnalyzer {
+
+ // lists containing the elements of a topology
+ List<TNodeTemplate> nodeTemplates = new ArrayList<TNodeTemplate>();
+ List<TRelationshipTemplate> relationshipTemplates = new ArrayList<TRelationshipTemplate>();
+ List<TRequirement> requirements = new ArrayList<TRequirement>();
+
+ List<TNodeType> nodeTypes;
+ List<TRelationshipType> relationshipTypes;
+ List<TRequirementType> requirementTypes;
+
+ /**
+ * This method analyzes the TOSCA {@link TTopologyTemplate} for {@link TNodeTemplate}s, {@link TRelationshipTemplate}s
+ * and existing {@link TRequirement}s and adds them to a list.
+ *
+ * @param topology
+ * the TOSCA {@link TTopologyTemplate}
+ */
+ public void analyzeTOSCATopology(TTopologyTemplate topology) {
+
+ // fill the data model with content of the topology
+ List<TEntityTemplate> templateNodes = topology.getNodeTemplateOrRelationshipTemplate();
+
+ for (TEntityTemplate entityTemplate : templateNodes) {
+ if (entityTemplate instanceof TNodeTemplate) {
+ // add the node templates and their requirements to the data model
+ nodeTemplates.add((TNodeTemplate) entityTemplate);
+ if (((TNodeTemplate) entityTemplate).getRequirements() != null) {
+ requirements.addAll(((TNodeTemplate) entityTemplate).getRequirements().getRequirement());
+ }
+ } else if (entityTemplate instanceof TRelationshipTemplate) {
+ // add RelationshipTemplates
+ relationshipTemplates.add((TRelationshipTemplate) entityTemplate);
+ }
+ }
+ }
+
+ /**
+ * Setter for the types received from the Winery repository.
+ *
+ * @param nodeTypeXMLStrings
+ * a list of {@link TNodeType}s from the Winery repository
+ * @param relationshipTypeXMLStrings
+ * a list of {@link TRelationshipType}s from the Winery repository
+ * @param requirementTypeList
+ * a list of {@link TRequirementType}s from the Winery repository
+ */
+ public void setTypes(List<TNodeType> nodeTypes, List<TRelationshipType> relationshipTypes, List<TRequirementType> requirementTypes) {
+ this.nodeTypes = nodeTypes;
+ this.relationshipTypes = relationshipTypes;
+ this.requirementTypes = requirementTypes;
+ }
+
+ /**
+ * Returns the {@link TNodeTemplate}s of the topology.
+ *
+ * @return the {@link TNodeTemplate}s as a list
+ */
+ public List<TNodeTemplate> getNodeTemplates() {
+ return nodeTemplates;
+ }
+
+ /**
+ * Returns the {@link TRelationshipTemplate}s of the topology.
+ *
+ * @return the {@link TRelationshipTemplate}s as a list
+ */
+ public List<TRelationshipTemplate> getRelationshipTemplates() {
+ return relationshipTemplates;
+ }
+
+ /**
+ * Returns the {@link TRequirement}s of the topology.
+ *
+ * @return the {@link TRequirement}s as a list
+ */
+ public List<TRequirement> getRequirements() {
+ return requirements;
+ }
+
+ /**
+ * Returns the {@link TRelationshipType}s of the topology.
+ *
+ * @return the {@link TRelationshipType}s as a list
+ */
+ public List<TRelationshipType> getRelationshipTypes() {
+ return relationshipTypes;
+ }
+
+ /**
+ * Returns the {@link TNodeType}s of the topology.
+ *
+ * @return the {@link TNodeType}s as a list
+ */
+ public List<TNodeType> getNodeTypes() {
+ return nodeTypes;
+ }
+
+ /**
+ * Returns the {@link TRequirementType}s of the topology.
+ *
+ * @return the {@link TRequirementType}s as a list
+ */
+ public List<TRequirementType> getRequirementTypes() {
+ return requirementTypes;
+ }
+
+ /**
+ * Clears all the templates from the data model before the analysis of a topology is restarted.
+ */
+ public void clear() {
+ nodeTemplates.clear();
+ relationshipTemplates.clear();
+ requirements.clear();
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/package-info.java
new file mode 100644
index 0000000..5333b5e
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/analyzer/package-info.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+/**
+ * This package contains classes and methods to analyze a TOSCA {@link org.opentosca.model.tosca.TTopologyTemplate} for its content.
+ */
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer;
+
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Constants.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Constants.java
new file mode 100644
index 0000000..e45c11a
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Constants.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper;
+
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.CompletionInterface;
+
+/**
+ * This class contains several constants used by the completion add-on.
+ */
+public class Constants {
+
+ /**
+ * Constant for the QName of the "deferred" type.
+ */
+ public static final QName DEFERRED_QNAME = new QName("http://www.opentosca.org", "deferred");
+
+ /**
+ * Constant for the QName of the "PlaceHolder" type.
+ */
+ public static final QName PLACE_HOLDER_QNAME = new QName("http://www.opentosca.org", "PlaceHolder");
+
+ /**
+ * Contains possible types of expandable place holders.
+ */
+ public enum PlaceHolders {
+ WEBSERVER, DATABASE, OPERATINGSYSTEM, CLOUDPROVIDER;
+
+ /**
+ * Overwritten toString() method to return formatted strings.
+ */
+ public String toString() {
+
+ switch (this) {
+ case WEBSERVER:
+ return "Webserver";
+ case DATABASE:
+ return "Database";
+ case OPERATINGSYSTEM:
+ return "OperatingSystem";
+ case CLOUDPROVIDER:
+ return "CloudProvider";
+ default:
+ return null;
+ }
+ }
+ }
+
+ /**
+ * The messages returned by the {@link CompletionInterface}
+ */
+ public enum CompletionMessages {
+ TOPOLOGYCOMPLETE, USERINTERACTION, STEPBYSTEP, SUCCESS, USERTOPOLOGYSELECTION, FAILURE;
+
+ /**
+ * Overwritten toString() method to return formatted strings.
+ */
+ public String toString() {
+
+ switch (this) {
+ case TOPOLOGYCOMPLETE:
+ return "topologyComplete";
+ case USERINTERACTION:
+ return "userInteraction";
+ case STEPBYSTEP:
+ return "stepByStep";
+ case SUCCESS:
+ return "success";
+ case USERTOPOLOGYSELECTION:
+ return "userTopologySelection";
+ case FAILURE:
+ return "failure";
+ default:
+ return null;
+ }
+ }
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java
new file mode 100644
index 0000000..84a3e28
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java
@@ -0,0 +1,374 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.model.tosca.Definitions;
+import org.eclipse.winery.model.tosca.TDefinitions;
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate.SourceElement;
+import org.eclipse.winery.model.tosca.TServiceTemplate;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+/**
+ * This class contains methods for marshalling and unmarshalling a topology XML string via JAXB.
+ *
+ */
+public class JAXBHelper {
+
+ private static final org.slf4j.Logger logger = LoggerFactory.getLogger(JAXBHelper.class.getName());
+
+ /**
+ * This constant is used in the buildXML method which add coordinates to Node Templates so they
+ * are arranged properly in the Winery topology modeler.
+ *
+ * The x coordinate is constant because it is assumed that a stack of NodeTemplates is displayed.
+ */
+ private static final String NODETEMPLATE_X_COORDINATE = "500";
+
+ /**
+ * This method creates an JAXB Unmarshaller used by the methods contained in this class.
+ *
+ * @return the JAXB unmarshaller object
+ *
+ * @throws JAXBException
+ * this exception can occur when the JAXBContext is created
+ */
+ private static Unmarshaller createUnmarshaller() throws JAXBException {
+ // initiate JaxB context
+ JAXBContext context;
+ context = JAXBContext.newInstance(Definitions.class);
+
+ return context.createUnmarshaller();
+ }
+
+ /**
+ * This method returns a {@link TTopologyTemplate} given as XML string as JaxBObject.
+ *
+ * @param xmlString
+ * the {@link TTopologyTemplate} to be unmarshalled
+ *
+ * @return the unmarshalled {@link TTopologyTemplate}
+ */
+ public static TTopologyTemplate getTopologyAsJaxBObject(String xmlString) {
+ try {
+
+ logger.info("Getting Definitions Document...");
+
+ StringReader reader = new StringReader(xmlString);
+
+ // unmarshall the XML string
+ Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader);
+ TServiceTemplate serviceTemplate = (TServiceTemplate) jaxBDefinitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+
+ logger.info("Unmarshalling successful! ");
+
+ return serviceTemplate.getTopologyTemplate();
+
+ } catch (JAXBException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ return null;
+ }
+
+ /**
+ * This method returns {@link TRelationshipTemplate}s as a JaxBObject.
+ *
+ * @param xmlString
+ * the {@link TRelationshipTemplate} to be unmarshalled
+ *
+ * @return the unmarshalled {@link TRelationshipTemplate}
+ */
+ public static List<TRelationshipTemplate> getRelationshipTemplatesAsJaxBObject(String xmlString) {
+ try {
+ StringReader reader = new StringReader(xmlString);
+
+ // unmarshall
+ Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader);
+ TServiceTemplate serviceTemplate = (TServiceTemplate) jaxBDefinitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+
+ List<TRelationshipTemplate> foundRTs = new ArrayList<>();
+ for (TEntityTemplate entity : serviceTemplate.getTopologyTemplate().getNodeTemplateOrRelationshipTemplate()) {
+ if (entity instanceof TRelationshipTemplate) {
+ foundRTs.add((TRelationshipTemplate) entity);
+ }
+ }
+
+ return foundRTs;
+
+ } catch (JAXBException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ return null;
+
+ }
+
+ /**
+ * Turns XML Strings into {@link TEntityTemplate} objects using JaxB.
+ *
+ * @param xmlString
+ * the XMLString to be parsed
+ * @return the parsed XMLString as {@link TEntityTemplate}
+ */
+ public static List<TEntityTemplate> getEntityTemplatesAsJaxBObject(String xmlString) {
+ try {
+ StringReader reader = new StringReader(xmlString);
+
+ Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader);
+ TServiceTemplate serviceTemplate = (TServiceTemplate) jaxBDefinitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+
+ return serviceTemplate.getTopologyTemplate().getNodeTemplateOrRelationshipTemplate();
+
+ } catch (JAXBException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ return null;
+
+ }
+
+ /**
+ * Converts any object of the TOSCA data model to a JaxBObject.
+ *
+ * @param xmlString
+ * the {@link Definitions} object to be converted
+ *
+ * @return the unmarshalled {@link Definitions} object
+ */
+ public static Definitions getXasJaxBObject(String xmlString) {
+ try {
+ StringReader reader = new StringReader(xmlString);
+ Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader);
+
+ return jaxBDefinitions;
+
+ } catch (JAXBException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ return null;
+
+ }
+
+ /**
+ * This method adds a selection of {@link TNodeTemplate}- and {@link TRelationshipTemplate}-XML-Strings to a {@link TTopologyTemplate}-XML-String using JAXB.
+ * After the templates have been added, the {@link TTopologyTemplate} object is re-marshalled to an XML-String.
+ *
+ * This method is called by the selectionHandler.jsp after several Node or RelationshipTemplates have been chosen in a dialog.
+ *
+ * @param topology
+ * the topology as XML string
+ * @param allTemplateChoicesAsXML
+ * all possible template choices as TOSCA-XML strings containing the complete templates
+ * @param selectedNodeTemplatesAsJSON
+ * the names of the selected NodeTemplates as JSONArray
+ * @param selectedRelationshipTemplatesAsJSON
+ * the names of the selected RelationshipTemplates as JSONArray
+ *
+ * @return the complete topology XML string
+ */
+ public static String addTemplatesToTopology(String topology, String allTemplateChoicesAsXML, String selectedNodeTemplatesAsJSON, String selectedRelationshipTemplatesAsJSON) {
+ try {
+
+ // initialization code for the jackson types used to convert JSON string arrays to a java.util.List
+ ObjectMapper mapper = new ObjectMapper();
+ TypeFactory factory = mapper.getTypeFactory();
+
+ // convert the JSON array containing the names of the selected RelationshipTemplates to a java.util.List
+ List<String> selectedRelationshipTemplates = mapper.readValue(selectedRelationshipTemplatesAsJSON, factory.constructCollectionType(List.class, String.class));
+
+ // convert the topology and the choices to objects using JAXB
+ TTopologyTemplate topologyTemplate = getTopologyAsJaxBObject(topology);
+ List<TEntityTemplate> allTemplateChoices = getEntityTemplatesAsJaxBObject(allTemplateChoicesAsXML);
+
+ // this distinction of cases is necessary because it is possible that only RelationshipTemplates have been selected
+ if (selectedNodeTemplatesAsJSON != null) {
+
+ // convert the JSON string array containing the names of the selected NodeTemplates to a java.util.List
+ List<String> selectedNodeTemplates = mapper.readValue(selectedNodeTemplatesAsJSON, factory.constructCollectionType(List.class, String.class));
+
+ // search the selected NodeTemplate in the List of all choices by its name to receive its object which will ne added to the topology
+ for (String nodeTemplateName : selectedNodeTemplates) {
+ for (TEntityTemplate choice : allTemplateChoices) {
+ if (choice instanceof TNodeTemplate) {
+ TNodeTemplate nodeTemplate = (TNodeTemplate) choice;
+ // matching a name is usually unsafe because the uniqueness cannot be assured,
+ // however similar names are not possible at this location due to the implementation of the selection dialogs
+ if (nodeTemplateName.equals(nodeTemplate.getName())) {
+ // add the selected NodeTemplate to the topology
+ topologyTemplate.getNodeTemplateOrRelationshipTemplate().add(nodeTemplate);
+
+ // due to the mapping of IDs in the selection dialog, the corresponding Relationship Template of the inserted Node Template misses its SourceElement.
+ // Re-add it to avoid errors.
+ for (TEntityTemplate entity: topologyTemplate.getNodeTemplateOrRelationshipTemplate()) {
+ if (entity instanceof TRelationshipTemplate) {
+ TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) entity;
+ if (relationshipTemplate.getSourceElement().getRef() == null) {
+ // connect to the added NodeTemplate
+ SourceElement sourceElement = new SourceElement();
+ sourceElement.setRef(nodeTemplate);
+ relationshipTemplate.setSourceElement(sourceElement);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // now search and add the selected RelationshipTemplate object connecting to the inserted NodeTemplate
+ for (String relationshipTemplateName : selectedRelationshipTemplates) {
+ for (TEntityTemplate toBeAdded : allTemplateChoices) {
+ if (toBeAdded instanceof TRelationshipTemplate) {
+ TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) toBeAdded;
+ if (relationshipTemplateName.equals(relationshipTemplate.getName())) {
+ topologyTemplate.getNodeTemplateOrRelationshipTemplate().add(relationshipTemplate);
+ }
+ }
+ }
+ }
+
+ } else {
+ // in this case only Relationship Templates have been selected
+ List<TRelationshipTemplate> allRelationshipTemplateChoices = JAXBHelper.getRelationshipTemplatesAsJaxBObject(allTemplateChoicesAsXML);
+
+ // add the target Node Template to the topology which is unique due to the implementation of the selection dialog
+ topologyTemplate.getNodeTemplateOrRelationshipTemplate().add((TNodeTemplate) ((TRelationshipTemplate) allRelationshipTemplateChoices.get(0)).getTargetElement().getRef());
+
+ // search the JAXB object of the selected RelationshipTemplate and add it to the topology
+ for (String relationshipTemplateName : selectedRelationshipTemplates) {
+ for (TRelationshipTemplate choice : allRelationshipTemplateChoices) {
+ if (relationshipTemplateName.equals(choice.getName())) {
+ topologyTemplate.getNodeTemplateOrRelationshipTemplate().add(choice);
+ }
+ }
+ }
+
+ for (TEntityTemplate entityTemplate : topologyTemplate.getNodeTemplateOrRelationshipTemplate()) {
+ if (entityTemplate instanceof TRelationshipTemplate) {
+ TRelationshipTemplate relationship = (TRelationshipTemplate) entityTemplate;
+
+ // due to the mapping of IDs in the selection dialog, the corresponding Relationship Template of the inserted Node Template misses its SourceElement.
+ // Re-add it to avoid errors.
+ if (relationship.getSourceElement().getRef() == null) {
+ relationship.getSourceElement().setRef((TNodeTemplate) ((TRelationshipTemplate) allRelationshipTemplateChoices.get(0)).getTargetElement().getRef());
+ }
+ }
+ }
+ }
+
+ // re-convert the topology from a JAXB object to an XML string and return it
+ Definitions definitions = new Definitions();
+ TServiceTemplate st = new TServiceTemplate();
+ st.setTopologyTemplate(topologyTemplate);
+ definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().add(st);
+ JAXBContext context = JAXBContext.newInstance(Definitions.class);
+ Marshaller m = context.createMarshaller();
+ StringWriter stringWriter = new StringWriter();
+
+ m.marshal(definitions, stringWriter);
+
+ return stringWriter.toString();
+
+ } catch (JAXBException | IOException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Marshalls a JAXB object of the TOSCA model to an XML string.
+ *
+ * @param clazz
+ * the class of the object
+ * @param obj
+ * the object to be marshalled
+ *
+ * @return
+ */
+ public static String getXMLAsString(@SuppressWarnings("rawtypes") Class clazz, Object obj) {
+ try {
+ @SuppressWarnings("rawtypes")
+ JAXBElement rootElement = Util.getJAXBElement(clazz, obj);
+ JAXBContext context = JAXBContext.newInstance(TDefinitions.class);
+ Marshaller m;
+
+ m = context.createMarshaller();
+
+ StringWriter w = new StringWriter();
+ m.marshal(rootElement, w);
+ String res = w.toString();
+
+ return res;
+ } catch (JAXBException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ return null;
+ }
+
+ /**
+ * This methods alters the XML with JAXB so it can be imported in Winery. This is necessary because Winery needs additional information for the position of the templates in the
+ * Winery-Modeler-UI.
+ *
+ * This code is adapted from the org.eclipse.winery.repository.Utils.getXMLAsString() method.
+ *
+ * @param topology
+ * the {@link TTopologyTemplate} to be altered
+ *
+ * @return the altered {@link TTopologyTemplate}
+ */
+ public static TTopologyTemplate buildXML(TTopologyTemplate topology) {
+
+ // the coordinate of the NodeTemplate in Winery. Begin 100 pixel from the top to improve arrangement.
+ int yCoordinates = 100;
+
+ for (TEntityTemplate template : topology.getNodeTemplateOrRelationshipTemplate()) {
+ // add node templates
+ if (template instanceof TNodeTemplate) {
+
+ TNodeTemplate nodeTemplate = (TNodeTemplate) template;
+
+ // remove the Requirements tag if necessary
+ if (nodeTemplate.getRequirements() != null && nodeTemplate.getRequirements().getRequirement() == null) {
+ nodeTemplate.setRequirements(null);
+ }
+
+ ModelUtilities.setLeft(nodeTemplate, NODETEMPLATE_X_COORDINATE);
+ ModelUtilities.setTop(nodeTemplate, Integer.toString(yCoordinates));
+
+ yCoordinates += 150;
+ }
+ }
+
+ return topology;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/NodeTemplateConnector.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/NodeTemplateConnector.java
new file mode 100644
index 0000000..f1d4b6b
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/NodeTemplateConnector.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TCapability;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipType;
+import org.eclipse.winery.model.tosca.TRequirement;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer;
+
+/**
+ * This class searches a {@link TRelationshipType} which is able to connect two given {@link TNodeTemplate}s.
+ *
+ */
+public class NodeTemplateConnector {
+
+ /**
+ * Searches a compatible {@link TRelationshipType} to connect two {@link TNodeTemplate}s.
+ *
+ * @param source
+ * the source {@link TNodeTemplate}
+ * @param target
+ * the target {@link TNodeTemplate}
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ * @param requirement
+ * the {@link TRequirement} of the source {@link TNodeTemplate}
+ *
+ * @return a list of suitable {@link TRelationshipType}s
+ */
+ public static List<TRelationshipType> findRelationshipType(TNodeTemplate source, TNodeTemplate target, TOSCAAnalyzer toscaAnalyzer, TRequirement requirement) {
+
+ List<TRelationshipType> suitableRelationshipTypes = new ArrayList<TRelationshipType>();
+ List<TRelationshipType> allRelationshipTypes = toscaAnalyzer.getRelationshipTypes();
+
+ // in case the connection to a placeholder is searched, no requirement exists
+ if (requirement != null) {
+
+ List<TCapability> capabilities = target.getCapabilities().getCapability();
+
+ // check if a RelationshipType can connect a requirement of the source NodeTemplate to a capability of the target NodeTemplate
+ for (TRelationshipType relationshipType : allRelationshipTypes) {
+ if (relationshipType.getValidSource() != null && relationshipType.getValidTarget() != null) {
+ for (TCapability capability : capabilities) {
+ if ((relationshipType.getValidSource().getTypeRef().equals(requirement.getType()) && relationshipType.getValidTarget().getTypeRef().equals(capability.getType()))) {
+ suitableRelationshipTypes.add(relationshipType);
+ }
+ }
+ }
+ }
+ }
+
+ // to extend the selection check if a RelationshipType can connect the type of the source NodeTemplate to the type of the target NodeTemplate
+ for (TRelationshipType rt : allRelationshipTypes) {
+ if (rt.getValidSource() != null && rt.getValidTarget() != null) {
+ if ((rt.getValidSource().getTypeRef().equals(source.getType()) && rt.getValidTarget().getTypeRef().equals(target.getType()))) {
+ suitableRelationshipTypes.add(rt);
+ }
+ }
+ }
+
+ // in case no suitable relationship type could be found, search for generic types without the optional ValidSource / ValidTarget elements.
+ if (suitableRelationshipTypes.isEmpty()) {
+ for (TRelationshipType rt : allRelationshipTypes) {
+ if (rt.getValidSource() == null && rt.getValidTarget() == null) {
+ suitableRelationshipTypes.add(rt);
+ }
+ }
+ }
+
+ return suitableRelationshipTypes;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/RESTHelper.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/RESTHelper.java
new file mode 100644
index 0000000..789d529
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/RESTHelper.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class contains helper methods to call the REST API and PUT/POST information to it.
+ */
+public class RESTHelper {
+
+ private static final org.slf4j.Logger logger = LoggerFactory.getLogger(RESTHelper.class.getName());
+
+ /**
+ * This method uses a REST call to save the completed {@link TTopologyTemplate} to the repository.
+ *
+ * @param topology
+ * the {@link TTopologyTemplate} to be saved
+ * @param topologyTemplateURL
+ * the URL the {@link TTopologyTemplate} is saved to
+ * @param overwriteTopology
+ * whether the topology is overwritten or a new topology shall be created
+ * @param topologyName
+ * the name of the newly created topology to build the URL if a new topology shall be created
+ * @param topologyNamespace
+ * the name space of the newly created topology to build the URL if a new topology shall be created
+ * @param repositoryURL
+ * the URL to the repository to build the URL if a new topology shall be created
+ */
+ public static void saveCompleteTopology(TTopologyTemplate topology, String topologyTemplateURL, boolean overwriteTopology, String topologyName, String topologyNamespace, String repositoryURL) {
+ try {
+
+ URL url = null;
+
+ if (overwriteTopology) {
+ url = new URL(topologyTemplateURL);
+ } else {
+ // this is necessary to avoid encoding issues
+ topologyNamespace = Util.DoubleURLencode(topologyNamespace);
+ // build the URL with the repositoryURL, the topology namespace and the topology name
+ url = new URL(repositoryURL + "/servicetemplates/" + topologyNamespace + "/" + topologyName + "/topologytemplate/");
+
+ logger.info("The URL the topology is saved to: " + url);
+ }
+
+ // using SSL
+ System.setProperty("javax.net.ssl.trustStore", "jssecacerts.cert");
+
+ // configure message
+ HttpURLConnection urlConn;
+ urlConn = (HttpURLConnection) url.openConnection();
+
+ logger.info("Sending HTTP request...");
+
+ urlConn.setDoOutput(true);
+ urlConn.setRequestMethod("PUT");
+ urlConn.setRequestProperty("Content-type", "text/xml");
+ OutputStreamWriter out = new OutputStreamWriter(urlConn.getOutputStream());
+
+ // build the XML string to be saved
+ TTopologyTemplate outputTopology = JAXBHelper.buildXML(topology);
+ String outputString = JAXBHelper.getXMLAsString(outputTopology.getClass(), outputTopology);
+
+ logger.info(outputString);
+ logger.info("Sending output to Winery.");
+
+ out.write(outputString);
+ out.close();
+ urlConn.getOutputStream().close();
+ logger.info("Output sent, waiting for response...");
+ urlConn.getInputStream();
+
+ logger.info("HTTP Response Code is: " + urlConn.getResponseCode());
+
+ } catch (IOException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Utils.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Utils.java
new file mode 100644
index 0000000..5f9826b
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/Utils.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.xml.namespace.QName;
+
+import org.eclipse.winery.model.tosca.TCapabilityDefinition;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.model.tosca.TRequirement;
+import org.eclipse.winery.model.tosca.TRequirementType;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Contains methods to match requirements and capabilities and find elements in the {@link TTopologyTemplate}
+ */
+public class Utils {
+
+ private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Utils.class.getName());
+
+ /**
+ * This method searches {@link TNodeType}s in the repository that match a requirement.
+ *
+ * @param requirement
+ * the requirement to be matched
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ *
+ * @return a list of the matched {@link TNodeType}s
+ */
+ public static List<TNodeType> matchRequirementAndCapability(TRequirement requirement, TOSCAAnalyzer toscaAnalyzer) {
+
+ List<TNodeType> possibleNodeTypes = new ArrayList<TNodeType>();
+
+ // find all matching Node Types for a requirement by the "requiredCapabilityType" attribute of its type
+ for (TRequirementType requirementType : toscaAnalyzer.getRequirementTypes()) {
+ if (requirementType.getName().equals(requirement.getType().getLocalPart())) {
+
+ QName requiredCapabilityType = requirementType.getRequiredCapabilityType();
+ for (TNodeType nodeType : toscaAnalyzer.getNodeTypes()) {
+ if (nodeType.getCapabilityDefinitions() != null) {
+ for (TCapabilityDefinition cd : nodeType.getCapabilityDefinitions().getCapabilityDefinition()) {
+ if (cd.getCapabilityType().getLocalPart().equals(requiredCapabilityType.getLocalPart())) {
+ possibleNodeTypes.add(nodeType);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return possibleNodeTypes;
+ }
+
+ /**
+ * Generates a random {@link UUID} exclusively used by the {@link TemplateBuilder}.
+ *
+ * @return the generated {@link UUID} id
+ */
+ public static String createRandomID() {
+ return UUID.randomUUID().toString();
+ }
+
+ /**
+ * Returns a {@link TNodeTemplate} for a given Id.
+ *
+ * @param nodeTemplates
+ * all the {@link TNodeTemplate} in the {@link TTopologyTemplate}
+ * @param id
+ * the id of the {@link TNodeTemplate} to be found
+ *
+ * @return the found {@link TNodeTemplate} or null if not found
+ */
+ public static TNodeTemplate getNodeTemplateForId(List<TNodeTemplate> nodeTemplates, String id) {
+
+ for (TNodeTemplate nt : nodeTemplates) {
+
+ if (nt.getId().equals(id)) {
+ return nt;
+ }
+ }
+
+ logger.error("No NodeTemplate with " + id + " exists");
+
+ return null;
+
+ }
+
+ /**
+ * Returns a {@link TNodeType} for a given Id.
+ *
+ * @param nodeTypes
+ * All the {@link TNodeType} in the {@link TTopologyTemplate}
+ * @param Id
+ * The id of the {@link TNodeType} to be searched
+ * @return the {@link TNodeType} or null if not found
+ */
+ public static TNodeType getNodeTypeForId(List<TNodeType> nodeTypes, QName id) {
+
+ for (TNodeType nodeType : nodeTypes) {
+ if (nodeType.getName().equals(id.getLocalPart()) && nodeType.getTargetNamespace().equals(id.getNamespaceURI())) {
+ return nodeType;
+ }
+ }
+
+ logger.error("No NodeType with " + id + " exists");
+
+ // no type could be found for the given ID, this case cannot occur if the topology was modelled in the Winery Topology Modeler
+ return null;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/package-info.java
new file mode 100644
index 0000000..5d42210
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/package-info.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+/**
+ * This package contains helper classes and methods to assist the completion.
+ */
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper;
+
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/package-info.java
new file mode 100644
index 0000000..19e334e
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/package-info.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+/**
+ * this package contains classes to complete a topology template
+ */
+package org.eclipse.winery.topologymodeler.addons.topologycompleter; \ No newline at end of file
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/placeholderhandling/PlaceHolderHandler.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/placeholderhandling/PlaceHolderHandler.java
new file mode 100644
index 0000000..a384e91
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/placeholderhandling/PlaceHolderHandler.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.placeholderhandling;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Constants;
+
+/**
+ * This class finds suitable replacement types for a place holder.
+ */
+public class PlaceHolderHandler {
+
+ /**
+ * This method returns a suitable {@link TNodeType} to replace a given {@link TNodeTemplate} placeholder.
+ * A suitable Node Type to replace a placeholder is matched by its type. If the type of a NodeType equals the identifier of a placeholder
+ * it can be used to replace it.
+ *
+ * @param nodeTemplate
+ * the placeholder to be replaced
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ *
+ * @return a list of {@link TNodeType}s to replace the placeholder
+ */
+ public static List<TNodeType> getSuitableNodeTypes(TNodeTemplate nodeTemplate, TOSCAAnalyzer toscaAnalyzer) {
+
+ List<TNodeType> suitableNodeTypes = new ArrayList<>();
+
+ // TODO: matching the name without a name space is unsafe and only works assuming that no one creates generic NodeTemplates with the same name as the place holders.
+ // However a NodeTemplate name does not have a name space.
+ if (nodeTemplate.getName().equals(Constants.PlaceHolders.WEBSERVER.toString())) {
+ for (TNodeType nodeType : toscaAnalyzer.getNodeTypes()) {
+ if (nodeType.getDerivedFrom() != null && nodeType.getDerivedFrom().getTypeRef().getLocalPart().equals(Constants.PlaceHolders.WEBSERVER.toString())) {
+ suitableNodeTypes.add(nodeType);
+ }
+ }
+ } else if (nodeTemplate.getName().equals(Constants.PlaceHolders.DATABASE.toString())) {
+ for (TNodeType nodeType : toscaAnalyzer.getNodeTypes()) {
+ if (nodeType.getDerivedFrom() != null && nodeType.getDerivedFrom().getTypeRef().getLocalPart().equals(Constants.PlaceHolders.DATABASE.toString())) {
+ suitableNodeTypes.add(nodeType);
+ }
+ }
+ } else if (nodeTemplate.getName().equals(Constants.PlaceHolders.OPERATINGSYSTEM.toString())) {
+ for (TNodeType nodeType : toscaAnalyzer.getNodeTypes()) {
+ if (nodeType.getDerivedFrom() != null && nodeType.getDerivedFrom().getTypeRef().getLocalPart().equals(Constants.PlaceHolders.OPERATINGSYSTEM.toString())) {
+ suitableNodeTypes.add(nodeType);
+ }
+ }
+ } else if (nodeTemplate.getName().equals(Constants.PlaceHolders.CLOUDPROVIDER.toString())) {
+ for (TNodeType nodeType : toscaAnalyzer.getNodeTypes()) {
+ if (nodeType.getDerivedFrom() != null && nodeType.getDerivedFrom().getTypeRef().getLocalPart().equals(Constants.PlaceHolders.CLOUDPROVIDER.toString())) {
+ suitableNodeTypes.add(nodeType);
+ }
+ }
+ }
+
+ return suitableNodeTypes;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionInterface.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionInterface.java
new file mode 100644
index 0000000..e46d3b1
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionInterface.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion;
+
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipType;
+import org.eclipse.winery.model.tosca.TRequirementType;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.repository.client.IWineryRepositoryClient;
+import org.eclipse.winery.repository.client.WineryRepositoryClientFactory;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.DeferredAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.PlaceHolderAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.RequirementAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Constants;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.JAXBHelper;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.RESTHelper;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class is the entry point of the TOSCA topology completion which is called by the Winery Topology Modeler.
+ * It receives an incomplete {@link TTopologyTemplate} from Winery.
+ * The completion of the incomplete {@link TTopologyTemplate} is managed by this class.
+ */
+public class CompletionInterface {
+
+ /**
+ * Logger for debug reasons.
+ */
+ private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CompletionInterface.class.getName());
+
+ /**
+ * This global variable is returned to the Winery Topology Modelerer via getCurrentTopology() to display intermediate results when an user interaction is necessary.
+ */
+ private TTopologyTemplate currentTopology;
+
+ /**
+ * This list contains {@link TTopologyTemplate}s to be chosen by the user when the topology solution isn't unique.
+ */
+ private List<TTopologyTemplate> topologyTemplateChoices;
+
+ /**
+ * This List contains {@link TRelationshipTemplate}s to be chosen by the user.
+ */
+ private List<TEntityTemplate> relationshipTemplateChoices;
+
+ /**
+ * This Map contains {@link TNodeTemplate}s and {@link TRelationshipTemplate}s to be chosen by the user during the step-by-step approach.
+ */
+ private Map<TNodeTemplate, Map<TNodeTemplate, List<TEntityTemplate>>> nodeTemplateChoices;
+
+ /**
+ * String containing an error message to be displayed in Winery if necessary.
+ */
+ private String errorMessage = "";
+
+ /**
+ * This method receives an incomplete {@link TTopologyTemplate} and the repository content from Winery. After analyzing the {@link TTopologyTemplate}, the topology is completed. This method will
+ * return a message after the completion whether the completion was successful, has failed or the user has to interact.
+ *
+ * @param topology
+ * (XMLString) the {@link TTopologyTemplate} to be completed as XMLString
+ * @param serviceTemplateName
+ * the name of the ServiceTemplate for REST calls
+ * @param topologyTemplateURL
+ * the URL where the template is saved to
+ * @param overwriteTopology
+ * determines in which way the {@link TTopologyTemplate} is saved. The current {@link TTopologyTemplate} can either be overwritten or a new topology can be created.
+ * @param topologyName
+ * the name of the {@link TTopologyTemplate} when a new {@link TTopologyTemplate} shall be created
+ * @param topologyNamespace
+ * the namespace of the {@link TTopologyTemplate} when a new {@link TTopologyTemplate} shall be created
+ * @param repositoryURL
+ * the URL to the repository to receive and write TOSCA specific information
+ * @param stepByStep
+ * whether the topology completion is processed step-by-step or not
+ * @param restarted
+ * whether the topology completion is restarted or started for the first time
+ *
+ * @return a message to Winery that contains information whether the topology is complete, the user has to interact or an error occurred.
+ */
+ public String complete(String topology, String serviceTemplateName, String topologyTemplateURL, Boolean overwriteTopology,
+ String topologyName, String topologyNamespace, String repositoryURL, boolean stepByStep, boolean restarted) {
+
+ logger.info("Starting completion...");
+
+ ////////////////////////////////////////
+ // STEP 1: Receive topology from Winery
+ ////////////////////////////////////////
+
+ logger.info("Saving to: " + topologyTemplateURL);
+
+ logger.info("The service template to be completed is: " + serviceTemplateName);
+
+ // receive types from repository
+ IWineryRepositoryClient client = WineryRepositoryClientFactory.getWineryRepositoryClient();
+ client.addRepository(repositoryURL);
+
+ List<TNodeType> nodeTypeList = (List<TNodeType>) client.getAllTypes(TNodeType.class);
+ List<TRelationshipType> relationshipTypeList = (List<TRelationshipType>) client.getAllTypes(TRelationshipType.class);
+ List<TRequirementType> requirementTypeList = (List<TRequirementType>) client.getAllTypes(TRequirementType.class);
+
+ /////////////////////////////////////
+ // Step 2: Analyze topology content
+ /////////////////////////////////////
+
+ logger.info("The modelled topology as XML: " + topology);
+
+ TTopologyTemplate topologyTemplate = JAXBHelper.getTopologyAsJaxBObject(topology);
+
+ logger.info("Analyzing topology...");
+
+ // analyze the received topology
+ TOSCAAnalyzer toscaAnalyzer = new TOSCAAnalyzer();
+ toscaAnalyzer.analyzeTOSCATopology(topologyTemplate);
+ toscaAnalyzer.setTypes(nodeTypeList, relationshipTypeList, requirementTypeList);
+
+ // if the topology is already complete, a message is displayed
+ if (checkCompletnessOfTopology(toscaAnalyzer) && !restarted) {
+ return Constants.CompletionMessages.TOPOLOGYCOMPLETE.toString();
+ } else {
+
+ /////////////////////////////////////////
+ // Step 3: Invoke the topology completion
+ /////////////////////////////////////////
+ logger.info("Invoking Topology Completion...");
+
+ CompletionManager completionManager = new CompletionManager(toscaAnalyzer, stepByStep);
+ List<TTopologyTemplate> completedTopology = completionManager.manageCompletion(topologyTemplate);
+
+ // the user has to interact by choosing a RelationshipTemplate, send message to Winery which will display a dialog
+ if (completionManager.getUserInteraction() && !stepByStep) {
+ currentTopology = completedTopology.get(0);
+ relationshipTemplateChoices = completionManager.getChoices();
+
+ return Constants.CompletionMessages.USERINTERACTION.toString();
+
+ } else if (completionManager.getNodeTemplateUserInteraction() && stepByStep) {
+ // the topology completion is processed Step-by-Step, the user has to choose Node and RelationshipTemplates to be inserted
+ currentTopology = completedTopology.get(0);
+ nodeTemplateChoices = completionManager.getTemplateChoices();
+
+ for (TNodeTemplate nodeTemplate : nodeTemplateChoices.keySet()) {
+ Map<TNodeTemplate, List<TEntityTemplate>> entityTemplates = nodeTemplateChoices.get(nodeTemplate);
+
+ for (TNodeTemplate entity : entityTemplates.keySet()) {
+ for (TEntityTemplate relationshipTemplate : entityTemplates.get(entity)) {
+ // remove entity that has to be chosen next
+ if (currentTopology.getNodeTemplateOrRelationshipTemplate().contains(relationshipTemplate)) {
+ currentTopology.getNodeTemplateOrRelationshipTemplate().remove(relationshipTemplate);
+ } else if (currentTopology.getNodeTemplateOrRelationshipTemplate().contains(entity)) {
+ currentTopology.getNodeTemplateOrRelationshipTemplate().remove(entity);
+ }
+ }
+ }
+ }
+
+ return Constants.CompletionMessages.STEPBYSTEP.toString();
+ }
+
+ logger.info("Completion successful!");
+
+ if (completedTopology.size() == 1) {
+ // solution is unique, save the topology
+ RESTHelper.saveCompleteTopology(completedTopology.get(0), topologyTemplateURL, overwriteTopology, topologyName, topologyNamespace, repositoryURL);
+ return Constants.CompletionMessages.SUCCESS.toString();
+ } else if (completedTopology.size() > 1) {
+ // if there are several topology solutions, let the user choose
+ this.topologyTemplateChoices = completedTopology;
+ return Constants.CompletionMessages.USERTOPOLOGYSELECTION.toString();
+ } else {
+ // an error occurred
+ errorMessage = "Error: No suitable NodeTemplate could be found for a Requirement or PlaceHolder.";
+ return Constants.CompletionMessages.FAILURE.toString();
+ }
+ }
+ }
+
+ /**
+ * This method checks if the topology is already complete. It will be called before executing the topology completion but
+ * only in case the topology completion isn't restarted after a user selection.
+ *
+ * @param toscaAnalyzer
+ * the topology to be checked
+ * @return whether the topology is complete or not
+ */
+ public boolean checkCompletnessOfTopology(TOSCAAnalyzer toscaAnalyzer) {
+
+ if (RequirementAnalyzer.analyzeRequirements(toscaAnalyzer).isEmpty() && PlaceHolderAnalyzer.analyzePlaceHolders(toscaAnalyzer).isEmpty()
+ && DeferredAnalyzer.analyzeDeferredRelations(toscaAnalyzer).isEmpty()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the current state of the completion.
+ *
+ * @return the current {@link TTopologyTemplate}
+ */
+ public TTopologyTemplate getCurrentTopology() {
+ return currentTopology;
+ }
+
+ /**
+ * Returns the choices whenever there are several possible complete {@link TTopologyTemplate}s. They will be displayed in Winery and chosen by the user.
+ *
+ * @return the possible {@link TTopologyTemplate} choices as a list.
+ */
+ public List<TTopologyTemplate> getTopologyTemplateChoices() {
+ return topologyTemplateChoices;
+ }
+
+ /**
+ * Returns the {@link TRelationshipTemplate} choices
+ *
+ * @return the {@link TRelationshipTemplate}s to be chosen
+ */
+ public List<TEntityTemplate> getRelationshipTemplateChoices() {
+ return relationshipTemplateChoices;
+ }
+
+ /**
+ * Returns several {@link TNodeTemplate} and {@link TRelationshipTemplate} choices when the user selected the step-by-step approach.
+ *
+ * @return the {@link TNodeTemplate} choices
+ */
+ public Map<TNodeTemplate, Map<TNodeTemplate, List<TEntityTemplate>>> getNodeTemplateChoices() {
+ return nodeTemplateChoices;
+ }
+
+ /**
+ * Returns a message when an error occurred during the completion.
+ *
+ * @return the error message
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionManager.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionManager.java
new file mode 100644
index 0000000..1f47cf5
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/CompletionManager.java
@@ -0,0 +1,358 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TRequirement;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.DeferredAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.PlaceHolderAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.RequirementAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer.DeferredCompleter;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer.PlaceHolderCompleter;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer.RequirementCompleter;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer.StepByStepCompleter;
+
+/**
+ * This class manages the completion of a TOSCA {@link TTopologyTemplate}.
+ */
+public class CompletionManager {
+
+ private static final Logger logger = Logger.getLogger(CompletionManager.class.getName());
+
+ /**
+ * {@link TOSCAAnalyzer} object to access the JAXB data model
+ */
+ TOSCAAnalyzer toscaAnalyzer;
+
+ /**
+ * Map containing the topology solutions.
+ *
+ * The first parameter of the map is an index used to traverse the map easily. The second parameter of the solutions map
+ * is another map containing a possible topology solution and a boolean value that determines if the topology is complete.
+ * When all topologies of the solution map are complete, it will be returned to Winery.
+ */
+ Map<Integer, Map<TTopologyTemplate, Boolean>> solutions;
+
+ /**
+ * Whether a step-by-step or an one-step approach is conducted
+ */
+ boolean stepByStep;
+
+ /**
+ * Map containing {@link TNodeTemplate}s and {@link TRelationshipTemplate}s to be chosen by the user in the step-by-step approach.
+ */
+ private Map<TNodeTemplate, Map<TNodeTemplate, List<TEntityTemplate>>> templateChoices;
+
+ /**
+ * Whether a user interaction for choosing inserted {@link TNodeTemplate}s and {@link TRelationshipTemplate}s is necessary or not.
+ */
+ private boolean nodeTemplateUserInteraction = false;
+
+ /**
+ * List containing {@link TRelationshipTemplate} to be chosen by the user.
+ */
+ private List<TEntityTemplate> choices;
+
+ /**
+ * Whether a user interaction for choosing inserted {@link TRelationshipTemplate}s is necessary or not.
+ */
+ boolean userInteraction = false;
+
+ /**
+ * The index of the topology solutions map.
+ */
+ int index;
+
+ /**
+ * The class constructor.
+ *
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ * @param stepByStep
+ * whether the topology completion is processed step-by-step or not
+ */
+ public CompletionManager(TOSCAAnalyzer toscaAnalyzer, boolean stepByStep) {
+ this.toscaAnalyzer = toscaAnalyzer;
+ this.stepByStep = stepByStep;
+ this.index = 0;
+
+ // instantiate the solution map
+ solutions = new HashMap<Integer, Map<TTopologyTemplate, Boolean>>();
+ }
+
+ /**
+ * This recursive method analyzes and completes a TOSCA {@link TTopologyTemplate}.
+ *
+ * @param topology
+ * the TOSCA {@link TTopologyTemplate} to be completed
+ *
+ * @return the complete TOSCA {@link TTopologyTemplate} object
+ */
+ public List<TTopologyTemplate> manageCompletion(TTopologyTemplate topology) {
+
+ // -------------------------
+ // Analyze topology template
+ // -------------------------
+
+ // the data model must be cleared before analyzing the topology
+ toscaAnalyzer.clear();
+
+ // analyze the content of the topology template
+ toscaAnalyzer.analyzeTOSCATopology(topology);
+
+ // Note: The TOSCAAnalyzer object is used for the analysis to access the NodeTemplates or RelationshipTemplates directly,
+ // so no cast from the parent type TEntityTemplate is required
+
+ // --------------------------------
+ // Analyze unfulfilled requirements
+ // --------------------------------
+ Map<TRequirement, TNodeTemplate> unfulfilledRequirements = RequirementAnalyzer.analyzeRequirements(toscaAnalyzer);
+
+ // ---------------------------------------
+ // Analyze the occurrence of place holders
+ // ---------------------------------------
+ List<TNodeTemplate> placeHolders = PlaceHolderAnalyzer.analyzePlaceHolders(toscaAnalyzer);
+
+ // --------------------------------------------------------
+ // Analyze the occurrence of deferred RelationshipTemplates
+ // --------------------------------------------------------
+ List<TRelationshipTemplate> deferredRelations = DeferredAnalyzer.analyzeDeferredRelations(toscaAnalyzer);
+
+ // ---------------------
+ // Complete the topology
+ // ---------------------
+
+ // with the step by step approach, a user interaction is always necessary. So the topology and
+ // the choices will be returned in every step. A combination of the step-by-step approach and a deferred topology is not
+ // possible because every path of the depth search can lead to a dead end.
+ if (stepByStep && deferredRelations.isEmpty()) {
+ logger.info("Completing topology step by step.");
+
+ List<TTopologyTemplate> solutionList = new ArrayList<TTopologyTemplate>();
+
+ if (!unfulfilledRequirements.isEmpty() && placeHolders.isEmpty()) {
+
+ // complete a topology containing requirements step by step using the StepByStepCompleter class
+ StepByStepCompleter stepByStepCompleter = new StepByStepCompleter(topology);
+ stepByStepCompleter.completeTopologyStepByStep(unfulfilledRequirements, toscaAnalyzer);
+
+ // get the NodeTemplate choices for the user
+ templateChoices = stepByStepCompleter.getTemplateChoices();
+ nodeTemplateUserInteraction = true;
+
+ solutionList.add(topology);
+
+ logger.info("Returning topology for user interaction");
+
+ return solutionList;
+
+ } else if (unfulfilledRequirements.isEmpty() && !placeHolders.isEmpty()) {
+
+ // complete a topology containing place holders step by step using the StepByStepCompleter class
+ StepByStepCompleter stepByStepCompleter = new StepByStepCompleter(topology);
+ TRelationshipTemplate genericRelationship = stepByStepCompleter.completeWildcardTopologyStepByStep(placeHolders, toscaAnalyzer);
+
+ // get the NodeTemplate selection for the user to choose
+ templateChoices = stepByStepCompleter.getTemplateChoices();
+ nodeTemplateUserInteraction = true;
+
+ TNodeTemplate toBeRemoved = stepByStepCompleter.getPlaceHolder();
+ topology.getNodeTemplateOrRelationshipTemplate().remove(toBeRemoved);
+ topology.getNodeTemplateOrRelationshipTemplate().remove(genericRelationship);
+
+ solutionList.add(topology);
+ logger.info("Returning topology for user interaction");
+
+ return solutionList;
+ } else if (unfulfilledRequirements.isEmpty() && placeHolders.isEmpty() && deferredRelations.isEmpty()) {
+
+ // the topology is complete, return it to Winery
+
+ logger.info("The topology is complete.");
+
+ nodeTemplateUserInteraction = false;
+ solutionList.add(topology);
+ return solutionList;
+ }
+ } else {
+ // the one-step approach is chosen or the topology contains deferred-RelationshipTemplates
+ if (unfulfilledRequirements.isEmpty() && placeHolders.isEmpty() && deferredRelations.isEmpty()) {
+ // the topology does not contain any elements that have to completed, it can be defined as complete
+ if (solutions.isEmpty()) {
+ // no topology solutions found, topology could not be completed due to missing types.
+ // Return an empty list, an error message will be shown in Winery.
+ return new ArrayList<TTopologyTemplate>();
+ } else {
+ // this topology is complete, set its boolean value in the map to true
+ for (Integer i : solutions.keySet()) {
+ for (TTopologyTemplate t : solutions.get(i).keySet()) {
+ if (t.equals(topology)) {
+ solutions.get(i).put(topology, true);
+ }
+ }
+ }
+
+ // check if the map still contains any incomplete topologies. If this is the case, the recursion will continue.
+ // Otherwise the solutions map is returned.
+ if (!solutions.values().contains(false)) {
+ logger.info("The topology is complete.");
+ List<TTopologyTemplate> sol = new ArrayList<TTopologyTemplate>();
+
+ for (Integer i : solutions.keySet()) {
+ sol.addAll(solutions.get(i).keySet());
+ }
+ return sol;
+ }
+ }
+ } else if (!unfulfilledRequirements.isEmpty() && placeHolders.isEmpty() && deferredRelations.isEmpty()) {
+
+ logger.info("The topology contains Requirements, but no Place Holders.");
+
+ // complete a topology containing Requirements in one step using the RequirementCompleter class
+ RequirementCompleter requirementCompleter = new RequirementCompleter(topology);
+
+ List<TTopologyTemplate> completeTopology = requirementCompleter.completeRequirementTopology(unfulfilledRequirements, toscaAnalyzer);
+
+ for (TTopologyTemplate topologySolution : completeTopology) {
+ Map<TTopologyTemplate, Boolean> topologyMap = new HashMap<TTopologyTemplate, Boolean>();
+ topologyMap.put(topologySolution, false);
+ solutions.put(index, topologyMap);
+ }
+
+ // complete all topology solutions recursively
+ for (TTopologyTemplate topologySolution : completeTopology) {
+ manageCompletion(topologySolution);
+ index++;
+ }
+
+ } else if (unfulfilledRequirements.isEmpty() && !placeHolders.isEmpty() || !unfulfilledRequirements.isEmpty() && !placeHolders.isEmpty()) {
+
+ logger.info("The topology contains one or more PlaceHolders.");
+
+ // complete a topology containing place holders in one step using the PlaceHolderCompleter class
+ PlaceHolderCompleter placeHolderCompleter = new PlaceHolderCompleter(topology);
+
+ List<TTopologyTemplate> completeTopology = placeHolderCompleter.completePlaceholderTopology(placeHolders, toscaAnalyzer);
+
+ if (placeHolderCompleter.getUserInteraction()) {
+ choices = placeHolderCompleter.getChoices();
+ userInteraction = true;
+
+ // user interaction is necessary to choose a inserted Relationship Template, return the topology to winery
+ List<TTopologyTemplate> intermediateSolutions = new ArrayList<>();
+ TRelationshipTemplate toBeRemoved = null;
+ for (TEntityTemplate entityTemplate : topology.getNodeTemplateOrRelationshipTemplate()) {
+ if (entityTemplate instanceof TRelationshipTemplate) {
+ TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) entityTemplate;
+ if (relationshipTemplate.getTargetElement().getRef().equals(placeHolderCompleter.getPlaceHolder())) {
+ toBeRemoved = relationshipTemplate;
+ }
+ }
+ }
+
+ topology.getNodeTemplateOrRelationshipTemplate().remove(toBeRemoved);
+ topology.getNodeTemplateOrRelationshipTemplate().remove(placeHolderCompleter.getPlaceHolder());
+
+ intermediateSolutions.add(topology);
+ return intermediateSolutions;
+ }
+
+ int i = 0;
+
+ for (TTopologyTemplate topologySolution : completeTopology) {
+ Map<TTopologyTemplate, Boolean> topologyMap = new HashMap<TTopologyTemplate, Boolean>();
+ topologyMap.put(topologySolution, false);
+ solutions.put(i, topologyMap);
+ i++;
+ }
+
+ for (TTopologyTemplate topologySolution : completeTopology) {
+ manageCompletion(topologySolution);
+ }
+ } else if (!deferredRelations.isEmpty()) {
+
+ logger.info("The topology contains deferred RelationshipTemplates.");
+
+ // complete a topology containing deferred Relationship Templates in one step using the DeferredCompleter class
+ DeferredCompleter deferredCompleter = new DeferredCompleter(topology);
+ List<TTopologyTemplate> completeTopology = deferredCompleter.completeDeferredTopology(deferredRelations.get(0), toscaAnalyzer);
+
+ int i = 0;
+ for (TTopologyTemplate solutionTemplate : completeTopology) {
+ Map<TTopologyTemplate, Boolean> topologyMap = new HashMap<TTopologyTemplate, Boolean>();
+ topologyMap.put(solutionTemplate, false);
+ solutions.put(i, topologyMap);
+ i++;
+ }
+
+ for (TTopologyTemplate topologySolution : completeTopology) {
+ manageCompletion(topologySolution);
+ }
+ }
+ List<TTopologyTemplate> sol = new ArrayList<TTopologyTemplate>();
+ for (Integer i : solutions.keySet()) {
+ sol.addAll(solutions.get(i).keySet());
+ }
+ return sol;
+ }
+
+ return new ArrayList<TTopologyTemplate>();
+ }
+
+ /**
+ * Returns whether an user interaction is necessary or not
+ *
+ * @return the field userInteraction
+ */
+ public boolean getUserInteraction() {
+ return userInteraction;
+ }
+
+ /**
+ * The possible {@link TRelationshipTemplate} choices
+ *
+ * @return the field choices
+ */
+ public List<TEntityTemplate> getChoices() {
+ return choices;
+ }
+
+ /**
+ * A map of {@link TNodeTemplate}s and {@link TRelationshipTemplate}s when completing a topology step by step
+ *
+ * @return the field nodeTemplateChoices
+ */
+ public Map<TNodeTemplate, Map<TNodeTemplate, List<TEntityTemplate>>> getTemplateChoices() {
+ return templateChoices;
+ }
+
+ /**
+ * Returns whether user interaction by choosing {@link TNodeTemplate}s and {@link TRelationshipTemplate}s is necessary or not
+ *
+ * @return the field nodeTemplateUserInteraction
+ */
+ public boolean getNodeTemplateUserInteraction() {
+ return nodeTemplateUserInteraction;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/DeferredCompleter.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/DeferredCompleter.java
new file mode 100644
index 0000000..8bdf01e
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/DeferredCompleter.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.model.tosca.TCapability;
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipType;
+import org.eclipse.winery.model.tosca.TRequirement;
+import org.eclipse.winery.model.tosca.TRequirementType;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.NodeTemplateConnector;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Utils;
+
+/**
+ * This class serves the completion of a topology containing Deferred {@link TRelationshipTemplate}s.
+ */
+public class DeferredCompleter {
+
+ /**
+ * The TOSCA {@link TTopologyTemplate} document
+ */
+ TTopologyTemplate topology;
+
+ /**
+ * A Map containing the requirements removed during the algorithm and their corresponding {@link TNodeTemplate}.
+ */
+ Map<TRequirement, TNodeTemplate> removedRequirements;
+
+ /**
+ * Constructor of the class.
+ *
+ * @param topology
+ * the {@link TTopologyTemplate} to be completed
+ */
+ public DeferredCompleter(TTopologyTemplate topology) {
+ this.topology = topology;
+ removedRequirements = new HashMap<TRequirement, TNodeTemplate>();
+ }
+
+ /**
+ * Completes a {@link TTopologyTemplate} that contains deferred {@link TRelationshipTemplate}s with a depth search algorithm. A deferred {@link TRelationshipTemplate} serves as place holder for a
+ * number of {@link TNodeTemplate}s and {@link TRelationshipTemplate}s.
+ *
+ * @param deferredRelation
+ * all found deferred {@link TRelationshipTemplate}s in the topology
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ *
+ * @return the completed topology
+ */
+ public List<TTopologyTemplate> completeDeferredTopology(TRelationshipTemplate deferredRelation, TOSCAAnalyzer toscaAnalyzer) {
+
+ List<TTopologyTemplate> solutions = new ArrayList<TTopologyTemplate>();
+
+ TNodeTemplate source = (TNodeTemplate) deferredRelation.getSourceElement().getRef();
+ TNodeTemplate target = (TNodeTemplate) deferredRelation.getTargetElement().getRef();
+
+ // TODO Remove this "if clause" after the Provisioning-API is implemented. At the moment Deferred RelationshipTemplates can't be completed
+ // without the existence of Requirements
+ if (source.getRequirements() != null && !source.getRequirements().getRequirement().isEmpty()) {
+ topology.getNodeTemplateOrRelationshipTemplate().remove(deferredRelation);
+ runDepthFirstSearch(source, target, new ArrayList<TEntityTemplate>(), solutions, toscaAnalyzer);
+ }
+
+ /**
+ * Note: This code adds Requirements to NodeTemplates that has been removed during the algorithm but could not
+ * be used to replace the Deferred-RelationshipTemplates. If this step is not done, requirements could get lost.
+ *
+ * Therefore all removed Requirements are checked for fulfillment in the topology. If they have not been fulfilled
+ * they are re-added to the topology.
+ */
+ Set<TRequirement> keySet = removedRequirements.keySet();
+
+ for (TTopologyTemplate topologyTemplate: solutions) {
+ boolean fulfilled = false;
+ for (TRequirement requirement: keySet) {
+ for (TEntityTemplate entity: topologyTemplate.getNodeTemplateOrRelationshipTemplate()) {
+ if (entity instanceof TNodeTemplate) {
+ TNodeTemplate nodeTemplate = (TNodeTemplate) entity;
+ if (nodeTemplate.getCapabilities() != null) {
+ for (TCapability capability: nodeTemplate.getCapabilities().getCapability()) {
+ String reqCapaType = "";
+ for (TRequirementType reqType: toscaAnalyzer.getRequirementTypes()) {
+ if (reqType.getName().equals(requirement.getType().getLocalPart())) {
+ reqCapaType = reqType.getRequiredCapabilityType().getLocalPart();
+ }
+ }
+ if (capability.getName().equals(reqCapaType)) {
+ fulfilled = true;
+ }
+ }
+ }
+ }
+ }
+ if (!fulfilled) {
+ for (TEntityTemplate entity: topologyTemplate.getNodeTemplateOrRelationshipTemplate()) {
+ if (entity.equals(removedRequirements.get(requirement))) {
+ TNodeTemplate foundNT = (TNodeTemplate) entity;
+ foundNT.getRequirements().getRequirement().add(requirement);
+ }
+ }
+ }
+ }
+ }
+
+ return solutions;
+ }
+
+ /**
+ * Runs a recursive depth search to find the path to the target NodeTemplate.
+ *
+ * @param source
+ * the source node of a given {@link TRelationshipTemplate}
+ * @param target
+ * the target node of a given {@link TRelationshipTemplate}
+ * @param path
+ * the current path to the target (can be incomplete)
+ * @param solutions
+ * list containing all possible solutions of the completion
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ *
+ * @return the path to the target NodeTemplate
+ */
+ private void runDepthFirstSearch(TNodeTemplate source, TNodeTemplate target, List<TEntityTemplate> path, List<TTopologyTemplate> solutions, TOSCAAnalyzer toscaAnalyzer) {
+
+ List<TNodeType> matchingNodeTypes = new ArrayList<TNodeType>();
+
+ if (source.getRequirements() != null) {
+
+ List<TRequirement> requirementsOfTemplate = new ArrayList<>();
+ for (TRequirement requirement : source.getRequirements().getRequirement()) {
+ requirementsOfTemplate.add(requirement);
+ }
+
+ for (TRequirement requirement : requirementsOfTemplate) {
+
+ // save the requirement to a list to avoid losing requirements (see line 83)
+ TRequirement sourceRequirement = new TRequirement();
+ sourceRequirement.setId(requirement.getId());
+ sourceRequirement.setName(requirement.getName());
+ sourceRequirement.setType(requirement.getType());
+
+ // Remember the removed requirements. In case a requirement
+ // can't be used for completing the deferred RelationshipTemplate it has to be re-added to the topology.
+ removedRequirements.put(sourceRequirement, source);
+
+ // search for matching NodeTypes for the requirement
+ matchingNodeTypes.addAll(Utils.matchRequirementAndCapability(requirement, toscaAnalyzer));
+
+ // remove the requirement so it is not handled again during the algorithm
+ source.getRequirements().getRequirement().remove(requirement);
+ }
+ }
+ for (TNodeType match : matchingNodeTypes) {
+
+ if (match.getName().equals(target.getType().getLocalPart()) && match.getTargetNamespace().equals(target.getType().getNamespaceURI())) {
+ // the search was successful connect the target
+ List<TRelationshipType> suitableRTs = NodeTemplateConnector.findRelationshipType(source, target, toscaAnalyzer, null);
+
+ for (TRelationshipType rt : suitableRTs) {
+ TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, source, target);
+ path.add(relationship);
+ }
+
+ TTopologyTemplate possiblePath = new TTopologyTemplate();
+ possiblePath.getNodeTemplateOrRelationshipTemplate().addAll(topology.getNodeTemplateOrRelationshipTemplate());
+
+ // add the path to the topology
+ for (TEntityTemplate pathTemplate : path) {
+ possiblePath.getNodeTemplateOrRelationshipTemplate().add(pathTemplate);
+ }
+
+ possiblePath.getNodeTemplateOrRelationshipTemplate().remove(target);
+
+ // this is no good style, however the target has to be the last item in the list for a proper stack layouting
+ possiblePath.getNodeTemplateOrRelationshipTemplate().add(target);
+ solutions.add(possiblePath);
+ path.clear();
+ } else {
+
+ // the end of the path is not reached, add the found NodeTemplate and continue the depth search
+ TNodeTemplate instantiatedNodeTemplate = ModelUtilities.instantiateNodeTemplate(match);
+
+ List<TRelationshipType> suitableRTs = NodeTemplateConnector.findRelationshipType(source, instantiatedNodeTemplate, toscaAnalyzer, null);
+
+ for (TRelationshipType rt : suitableRTs) {
+ TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, source, instantiatedNodeTemplate);
+ path.add(relationship);
+ }
+ path.add(instantiatedNodeTemplate);
+ runDepthFirstSearch(instantiatedNodeTemplate, target, path, solutions, toscaAnalyzer);
+
+ }
+ }
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/PlaceHolderCompleter.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/PlaceHolderCompleter.java
new file mode 100644
index 0000000..e76d897
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/PlaceHolderCompleter.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipType;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.NodeTemplateConnector;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.placeholderhandling.PlaceHolderHandler;
+
+/**
+ * This class completes a {@link TTopologyTemplate} containing place holders.
+ */
+public class PlaceHolderCompleter {
+
+ /**
+ * The {@link TTopologyTemplate} to be completed
+ */
+ TTopologyTemplate topology;
+
+ /**
+ * List containing user choices for {@link TRelationshipTemplate}s
+ */
+ List<TEntityTemplate> choices;
+
+ /**
+ * Whether an user interaction is necessary or not
+ */
+ boolean userInteraction;
+
+ /**
+ * The last inserted place holder
+ */
+ TNodeTemplate placeHolder;
+
+ /**
+ * The constructor of the class PlaceHolderCompleter.
+ *
+ * @param topology
+ * the {@link TTopologyTemplate} to be completed
+ */
+ public PlaceHolderCompleter(TTopologyTemplate topology) {
+ this.topology = topology;
+ userInteraction = false;
+ }
+
+ /**
+ * This method completes a {@link TTopologyTemplate} containing place holders.
+ *
+ * @param placeHolders
+ * the contained place holders
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ *
+ * @return the complete {@link TTopologyTemplate}
+ */
+ public List<TTopologyTemplate> completePlaceholderTopology(List<TNodeTemplate> placeHolders, TOSCAAnalyzer toscaAnalyzer) {
+
+ List<TTopologyTemplate> solutions = new ArrayList<TTopologyTemplate>();
+
+ for (TNodeTemplate placeHolder : placeHolders) {
+
+ List<TNodeType> suitableNodeTypes = PlaceHolderHandler.getSuitableNodeTypes(placeHolder, toscaAnalyzer);
+
+ // if there are more than one solution for an inserted NodeTemplate,
+ // create copies of the topology. The user can choose from them after the completion.
+ TTopologyTemplate topologyCopy = null;
+
+ for (TNodeType suitableNodeType : suitableNodeTypes) {
+ topologyCopy = new TTopologyTemplate();
+ topologyCopy.getNodeTemplateOrRelationshipTemplate().addAll(topology.getNodeTemplateOrRelationshipTemplate());
+
+ TNodeTemplate nodeTemplate = ModelUtilities.instantiateNodeTemplate(suitableNodeType);
+
+ List<TNodeTemplate> sourceTemplates = new ArrayList<>();
+
+ // contains RelationshipTemplates connecting to a place holder.
+ // These Templates are generic and have to be replaced with
+ // concrete ones.
+ List<TRelationshipTemplate> placeholderConnections = new ArrayList<>();
+
+ TRelationshipTemplate foundTarget = null;
+ for (TEntityTemplate entity : topology.getNodeTemplateOrRelationshipTemplate()) {
+ if (entity instanceof TRelationshipTemplate) {
+ TRelationshipTemplate rt = (TRelationshipTemplate) entity;
+ if (((TNodeTemplate) rt.getTargetElement().getRef()).getId().equals(placeHolder.getId())) {
+ TRelationshipTemplate placeHolderConnection = (TRelationshipTemplate) entity;
+ placeholderConnections.add(placeHolderConnection);
+ sourceTemplates.add((TNodeTemplate) placeHolderConnection.getSourceElement().getRef());
+ } else if (((TNodeTemplate) rt.getSourceElement().getRef()).getId().equals(placeHolder.getId())) {
+ foundTarget = (TRelationshipTemplate) entity;
+ }
+ }
+ }
+
+ // collect all possible RelationshipTemplates that can be used to connect to the placeholder
+ choices = new ArrayList<>();
+
+ for (TNodeTemplate sourceTemplate : sourceTemplates) {
+ // find matching RelationshipTypes to connect the Node Templates
+ List<TRelationshipType> suitableRTs = NodeTemplateConnector.findRelationshipType(sourceTemplate, nodeTemplate, toscaAnalyzer, null);
+ for (TRelationshipType rt : suitableRTs) {
+ TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, sourceTemplate, nodeTemplate);
+ choices.add(relationship);
+ }
+ }
+
+ // set the source elements of the RelationshipTemplates connecting from the replaced placeholder to other NodeTemplates
+ for (TEntityTemplate entityTemplate : topologyCopy.getNodeTemplateOrRelationshipTemplate()) {
+ if (entityTemplate instanceof TRelationshipTemplate) {
+ TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) entityTemplate;
+ if (relationshipTemplate.equals(foundTarget)) {
+ foundTarget.getSourceElement().setRef(nodeTemplate);
+ }
+ }
+ }
+
+ // remove the generic connections to the place holder
+ topologyCopy.getNodeTemplateOrRelationshipTemplate().removeAll(placeholderConnections);
+
+ // there are more than one possible Relationship Templates to connect to the inserted NodeTemplate(s), so
+ // interrupt the completion and ask the user which one to insert
+ if (choices.size() > 1 && sourceTemplates.size() == 1) {
+
+ choices.add(sourceTemplates.get(0));
+ choices.add(nodeTemplate);
+ topologyCopy.getNodeTemplateOrRelationshipTemplate().remove(placeHolder);
+
+ userInteraction = true;
+ this.placeHolder = placeHolder;
+ break;
+ } else if (choices.size() == 1 || sourceTemplates.size() > 1) {
+ // replace the place holder with an actual NodeTemplate
+ topologyCopy.getNodeTemplateOrRelationshipTemplate().addAll(choices);
+ topologyCopy.getNodeTemplateOrRelationshipTemplate().add(nodeTemplate);
+ topologyCopy.getNodeTemplateOrRelationshipTemplate().remove(placeHolder);
+ }
+ solutions.add(topologyCopy);
+ }
+ }
+ return solutions;
+ }
+
+ /**
+ * Returns the replaced place holder.
+ *
+ * @return the place holder
+ */
+ public TNodeTemplate getPlaceHolder() {
+ return placeHolder;
+ }
+
+ /**
+ * Returns whether an user interaction is necessary or not.
+ *
+ * @return the field userInteraction
+ */
+ public boolean getUserInteraction() {
+ return userInteraction;
+ }
+
+ /**
+ * Possible Relationship Template choices.
+ *
+ * @return the field choices
+ */
+ public List<TEntityTemplate> getChoices() {
+ return choices;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/RequirementCompleter.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/RequirementCompleter.java
new file mode 100644
index 0000000..b2e7c75
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/RequirementCompleter.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipType;
+import org.eclipse.winery.model.tosca.TRequirement;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.NodeTemplateConnector;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Utils;
+
+public class RequirementCompleter {
+
+ /**
+ * The TOSCA {@link TTopologyTemplate} document.
+ */
+ TTopologyTemplate topology;
+
+ /**
+ * The constructor the class.
+ *
+ * @param topology
+ * the topology to be completed
+ */
+ public RequirementCompleter(TTopologyTemplate topology) {
+ this.topology = topology;
+ }
+
+ /**
+ * This method completes a topology containing {@link TRequirement}s in one step (without user interaction).
+ *
+ * @param unfulfilledRequirements
+ * all the unfulfilled requirements that has been found in the topology
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ *
+ * @return the complete topology
+ */
+ public List<TTopologyTemplate> completeRequirementTopology(Map<TRequirement, TNodeTemplate> unfulfilledRequirements, TOSCAAnalyzer toscaAnalyzer) {
+
+ List<TTopologyTemplate> solutions = new ArrayList<TTopologyTemplate>();
+
+ Set<TRequirement> requirements = unfulfilledRequirements.keySet();
+
+ TNodeTemplate instantiatedNodeTemplate = null;
+
+ // fulfill the Requirements
+ for (TRequirement requirement : requirements) {
+
+ // remove the requirement from the NodeTemplate
+ TNodeTemplate requirementTemplate = unfulfilledRequirements.get(requirement);
+ for (TEntityTemplate element : topology.getNodeTemplateOrRelationshipTemplate()) {
+ if (requirementTemplate.getId().equals(element.getId())) {
+ ((TNodeTemplate) element).getRequirements().getRequirement().remove(requirement);
+ }
+ }
+
+ List<TNodeType> possibleNodeTypes = Utils.matchRequirementAndCapability(requirement, toscaAnalyzer);
+
+ // create a NodeTemplate for every matching Type, insert it into the topology and create a topology copy for each possible inserted NodeTemplate
+ TTopologyTemplate topologyCopy = null;
+ for (TNodeType possibleType : possibleNodeTypes) {
+
+ topologyCopy = new TTopologyTemplate();
+ topologyCopy.getNodeTemplateOrRelationshipTemplate().addAll(topology.getNodeTemplateOrRelationshipTemplate());
+
+ // instantiate the template
+ instantiatedNodeTemplate = ModelUtilities.instantiateNodeTemplate(possibleType);
+ topologyCopy.getNodeTemplateOrRelationshipTemplate().add(instantiatedNodeTemplate);
+
+ TNodeTemplate correspondingNodeTemplate = unfulfilledRequirements.get(requirement);
+
+ // find matching RelationshipTypes, instantiate RelationshipTemplates and connect the Node Templates
+ List<TRelationshipType> suitableRTs = NodeTemplateConnector.findRelationshipType(correspondingNodeTemplate, instantiatedNodeTemplate, toscaAnalyzer, requirement);
+ for (TRelationshipType rt : suitableRTs) {
+ TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, correspondingNodeTemplate, instantiatedNodeTemplate);
+ topologyCopy.getNodeTemplateOrRelationshipTemplate().add(relationship);
+ }
+
+ solutions.add(topologyCopy);
+ }
+ if (solutions.size() > 1) {
+ break;
+ }
+ }
+ return solutions;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/StepByStepCompleter.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/StepByStepCompleter.java
new file mode 100644
index 0000000..b8cc745
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/StepByStepCompleter.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipType;
+import org.eclipse.winery.model.tosca.TRequirement;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.NodeTemplateConnector;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.Utils;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.placeholderhandling.PlaceHolderHandler;
+
+/**
+ * This class handles topologies that are completed step by step
+ */
+public class StepByStepCompleter {
+
+ /**
+ * the topology to be completed
+ */
+ TTopologyTemplate topology;
+
+ /**
+ * the Node and RelationshipTemplates chosen by the user in every step
+ */
+ Map<TNodeTemplate, Map<TNodeTemplate, List<TEntityTemplate>>> templateChoices;
+
+ /**
+ * the last inserted place holder to be deleted
+ */
+ private TNodeTemplate placeHolder;
+
+ /**
+ * The constructor of the class.
+ *
+ * @param topology
+ * the {@link TTopologyTemplate} to be completed
+ */
+ public StepByStepCompleter(TTopologyTemplate topology) {
+ this.topology = topology;
+ }
+
+ /**
+ * This method is called when a topology containing {@link TRequirement}s is completed step by step.
+ *
+ * @param unfulfilledRequirements
+ * a list of unfulfilled requirements
+ * @param placeHolders
+ * a list of place holders to be fulfilled
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model
+ */
+ public void completeTopologyStepByStep(Map<TRequirement, TNodeTemplate> unfulfilledRequirements, TOSCAAnalyzer toscaAnalyzer) {
+
+ Set<TRequirement> requirements = unfulfilledRequirements.keySet();
+
+ TNodeTemplate nodeTemplate = null;
+
+ for (TRequirement requirement : requirements) {
+ // remove the requirement from the NodeTemplate
+ TNodeTemplate requirementTemplate = unfulfilledRequirements.get(requirement);
+ for (TEntityTemplate element : topology.getNodeTemplateOrRelationshipTemplate()) {
+ if (requirementTemplate.getId().equals(element.getId())) {
+ ((TNodeTemplate) element).getRequirements().getRequirement().remove(requirement);
+ }
+ }
+
+ List<TNodeType> possibleNodeTypes = Utils.matchRequirementAndCapability(requirement, toscaAnalyzer);
+
+ // create a NodeTemplate for each matching node type
+ List<TNodeTemplate> possibleTemplates = new ArrayList<>();
+ for (TNodeType possibleType : possibleNodeTypes) {
+ nodeTemplate = ModelUtilities.instantiateNodeTemplate(possibleType);
+ possibleTemplates.add(nodeTemplate);
+ }
+
+ TNodeTemplate correspondingNodeTemplate = unfulfilledRequirements.get(requirement);
+
+ Map<TNodeTemplate, List<TEntityTemplate>> entityTemplates = new HashMap<>();
+
+ // add all possible choices to a list and return it to the user
+ for (TNodeTemplate possibleTemplate : possibleTemplates) {
+ List<TEntityTemplate> choices = new ArrayList<TEntityTemplate>();
+ List<TRelationshipType> suitableRTs = NodeTemplateConnector.findRelationshipType(correspondingNodeTemplate, possibleTemplate, toscaAnalyzer, requirement);
+ for (TRelationshipType rt : suitableRTs) {
+ TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, correspondingNodeTemplate, possibleTemplate);
+ choices.add(relationship);
+ }
+ entityTemplates.put(possibleTemplate, choices);
+ }
+
+ templateChoices = new HashMap<TNodeTemplate, Map<TNodeTemplate, List<TEntityTemplate>>>();
+ templateChoices.put(correspondingNodeTemplate, entityTemplates);
+
+ // let the user decide which template shall be inserted
+ break;
+ }
+
+ }
+
+ /**
+ * Completes a place holder {@link TTopologyTemplate} step by step.
+ *
+ * @param placeHolders
+ * the place holders of the topology
+ * @param toscaAnalyzer
+ * the {@link TOSCAAnalyzer} object to access the data model.
+ * @return the generic {@link TRelationshipTemplate} which connects to the place holder.
+ */
+ public TRelationshipTemplate completeWildcardTopologyStepByStep(List<TNodeTemplate> placeHolders, TOSCAAnalyzer toscaAnalyzer) {
+
+ // take the first place holder, the order doesn't matter in the step by step approach
+ TNodeTemplate placeHolder = placeHolders.get(0);
+
+ // get suitable NodeTypes for a placeholder and instantiate NodeTemplates
+ List<TNodeType> suitableNodeTypes = PlaceHolderHandler.getSuitableNodeTypes(placeHolder, toscaAnalyzer);
+ List<TNodeTemplate> suitableNodeTemplates = new ArrayList<TNodeTemplate>();
+ for (TNodeType suitableNodeType : suitableNodeTypes) {
+ TNodeTemplate nodeTemplate = ModelUtilities.instantiateNodeTemplate(suitableNodeType);
+ suitableNodeTemplates.add(nodeTemplate);
+ }
+
+ /**
+ * map containing the choices for the user selection
+ */
+ Map<TNodeTemplate, List<TEntityTemplate>> entityTemplates = new HashMap<>();
+
+ TNodeTemplate sourceTemplate = null;
+
+ // the RelationshipTemplate connecting to the placeholder
+ TRelationshipTemplate connectingRelationshipTemplate = null;
+
+ for (TEntityTemplate entity : topology.getNodeTemplateOrRelationshipTemplate()) {
+ if (entity instanceof TRelationshipTemplate) {
+ TRelationshipTemplate rt = (TRelationshipTemplate) entity;
+ if (((TNodeTemplate) rt.getTargetElement().getRef()).getId().equals(placeHolder.getId())) {
+ connectingRelationshipTemplate = (TRelationshipTemplate) entity;
+ sourceTemplate = (TNodeTemplate) connectingRelationshipTemplate.getSourceElement().getRef();
+ }
+ }
+ }
+
+ for (TNodeTemplate nodeTemplate : suitableNodeTemplates) {
+
+ List<TEntityTemplate> choices = new ArrayList<>();
+
+ // find matching RelationshipTypes to connect the Node Templates
+ List<TRelationshipType> suitableRTs = NodeTemplateConnector.findRelationshipType(sourceTemplate, nodeTemplate, toscaAnalyzer, null);
+ for (TRelationshipType rt : suitableRTs) {
+ TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, sourceTemplate, nodeTemplate);
+ choices.add(relationship);
+ }
+ entityTemplates.put(nodeTemplate, choices);
+ }
+
+ templateChoices = new HashMap<TNodeTemplate, Map<TNodeTemplate, List<TEntityTemplate>>>();
+ templateChoices.put(sourceTemplate, entityTemplates);
+
+ this.placeHolder = placeHolder;
+
+ return connectingRelationshipTemplate;
+
+ }
+
+ /**
+ * Returns a map containing the choices for the user selection when the topology is completed step by step.
+ *
+ * @return the field ntChoices
+ */
+ public Map<TNodeTemplate, Map<TNodeTemplate, List<TEntityTemplate>>> getTemplateChoices() {
+ return templateChoices;
+ }
+
+ /**
+ * Returns the replaced place holder to remove it from the topology.
+ *
+ * @return the place holder
+ */
+ public TNodeTemplate getPlaceHolder() {
+ return placeHolder;
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/package-info.java
new file mode 100644
index 0000000..8a097d5
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/completer/package-info.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+/**
+ * This package contains classes and methods to actually execute the completion for several use cases.
+ */
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer;
+
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/package-info.java
new file mode 100644
index 0000000..bdaf170
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/topologycompletion/package-info.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+/**
+ * This package contains classes and methods to execute and manage the completion.
+ */
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion;
+
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/TopologyCompletionResource.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/TopologyCompletionResource.java
new file mode 100644
index 0000000..efc36e3
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/TopologyCompletionResource.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.resources;
+
+import java.io.StringReader;
+
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.eclipse.winery.model.tosca.Definitions;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TServiceTemplate;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.JAXBHelper;
+import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.RESTHelper;
+
+/**
+ * This class contains resources used for the topology completion.
+ *
+ */
+@Path("/")
+public class TopologyCompletionResource {
+
+ /**
+ * Adds selected {@link TNodeTemplate}s and {@link TRelationshipTemplate}s
+ * to a topology.
+ *
+ * @param topology
+ * the {@link TTopologyTemplate} as XML string
+ * @param allChoices
+ * all possible choices as XML
+ * @param selectedNodeTemplates
+ * the selected {@link TNodeTemplate}s as JSON array
+ * @param selectedRelationshipTemplates
+ * the selected {@link TRelationshipTemplate}s as JSON array
+ * @return the enhanced {@link TTopologyTemplate}
+ */
+ @Path("selectionhandler/")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response handleSelection(
+ @QueryParam(value = "topology") String topology,
+ @QueryParam(value = "allChoices") String allChoices,
+ @QueryParam(value = "selectedNodeTemplates") String selectedNodeTemplates,
+ @QueryParam(value = "selectedRelationshipTemplates") String selectedRelationshipTemplates) {
+ return Response
+ .ok()
+ .entity(JAXBHelper.addTemplatesToTopology(topology, allChoices,
+ selectedNodeTemplates, selectedRelationshipTemplates))
+ .build();
+ }
+
+ /**
+ * This resource is used to save a {@link TTopologyTemplate} to the repository.
+ *
+ * @param topology
+ * the topology to be saved
+ * @param templateURL
+ * the URL the {@link TTopologyTemplate} of the topology template
+ * @param repositoryURL
+ * the URL of the repository
+ * @param topologyName
+ * the name of the saved {@link TTopologyTemplate}
+ * @param topologyNamespace
+ * the namespace of the saved {@link TTopologyTemplate}
+ * @param overwriteTopology
+ * whether the {@link TTopologyTemplate} should be overwritten or not
+ *
+ * @return whether the save operation has been successful or not
+ */
+ @Path("topologysaver/")
+ @POST
+ public Response saveTopology(@FormParam("topology") String topology,
+ @FormParam(value = "templateURL") String templateURL,
+ @FormParam(value = "repositoryURL") String repositoryURL,
+ @FormParam(value = "topologyName") String topologyName,
+ @FormParam(value = "topologyNamespace") String topologyNamespace,
+ @FormParam(value = "overwriteTopology") String overwriteTopology) {
+ try {
+
+ boolean overwrite = Boolean.parseBoolean(overwriteTopology);
+
+ // initiate JaxB context
+ JAXBContext context;
+ context = JAXBContext.newInstance(Definitions.class);
+ StringReader reader = new StringReader(topology);
+
+ // unmarshall the topology XML string
+ Unmarshaller um;
+
+ um = context.createUnmarshaller();
+
+ Definitions jaxBDefinitions = (Definitions) um.unmarshal(reader);
+ TServiceTemplate st = (TServiceTemplate) jaxBDefinitions
+ .getServiceTemplateOrNodeTypeOrNodeTypeImplementation()
+ .get(0);
+ TTopologyTemplate toBeSaved = st.getTopologyTemplate();
+
+ // depending on the selected save method (overwrite or create new)
+ // the save method is called
+ if (overwrite) {
+ RESTHelper.saveCompleteTopology(toBeSaved, templateURL, true,
+ "", "", repositoryURL);
+ } else {
+ RESTHelper.saveCompleteTopology(toBeSaved, templateURL, false,
+ topologyName, topologyNamespace, repositoryURL);
+ }
+
+ return Response.ok().build();
+
+ } catch (JAXBException e) {
+ e.printStackTrace();
+ return Response.serverError().build();
+ }
+ }
+}
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/package-info.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/package-info.java
new file mode 100644
index 0000000..a06da46
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/resources/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the resources of the topology modeler
+ */
+package org.eclipse.winery.topologymodeler.resources; \ No newline at end of file