e76d89714150cbba07982aa347659ad0c8317060
[vfc/nfvo/wfengine.git] / winery / org.eclipse.winery.topologymodeler / src / main / java / org / eclipse / winery / topologymodeler / addons / topologycompleter / topologycompletion / completer / PlaceHolderCompleter.java
1 /*******************************************************************************
2  * Copyright (c) 2013 Pascal Hirmer.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * and the Apache License 2.0 which both accompany this distribution,
6  * and are available at http://www.eclipse.org/legal/epl-v10.html
7  * and http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Contributors:
10  *    Pascal Hirmer - initial API and implementation
11  *******************************************************************************/
12
13 package org.eclipse.winery.topologymodeler.addons.topologycompleter.topologycompletion.completer;
14
15 import java.util.ArrayList;
16 import java.util.List;
17
18 import org.eclipse.winery.common.ModelUtilities;
19 import org.eclipse.winery.model.tosca.TEntityTemplate;
20 import org.eclipse.winery.model.tosca.TNodeTemplate;
21 import org.eclipse.winery.model.tosca.TNodeType;
22 import org.eclipse.winery.model.tosca.TRelationshipTemplate;
23 import org.eclipse.winery.model.tosca.TRelationshipType;
24 import org.eclipse.winery.model.tosca.TTopologyTemplate;
25 import org.eclipse.winery.topologymodeler.addons.topologycompleter.analyzer.TOSCAAnalyzer;
26 import org.eclipse.winery.topologymodeler.addons.topologycompleter.helper.NodeTemplateConnector;
27 import org.eclipse.winery.topologymodeler.addons.topologycompleter.placeholderhandling.PlaceHolderHandler;
28
29 /**
30  * This class completes a {@link TTopologyTemplate} containing place holders.
31  */
32 public class PlaceHolderCompleter {
33
34         /**
35          * The {@link TTopologyTemplate} to be completed
36          */
37         TTopologyTemplate topology;
38
39         /**
40          * List containing user choices for {@link TRelationshipTemplate}s
41          */
42         List<TEntityTemplate> choices;
43
44         /**
45          * Whether an user interaction is necessary or not
46          */
47         boolean userInteraction;
48
49         /**
50          * The last inserted place holder
51          */
52         TNodeTemplate placeHolder;
53
54         /**
55          * The constructor of the class PlaceHolderCompleter.
56          *
57          * @param topology
58          *            the {@link TTopologyTemplate} to be completed
59          */
60         public PlaceHolderCompleter(TTopologyTemplate topology) {
61                 this.topology = topology;
62                 userInteraction = false;
63         }
64
65         /**
66          * This method completes a {@link TTopologyTemplate} containing place holders.
67          *
68          * @param placeHolders
69          *            the contained place holders
70          * @param toscaAnalyzer
71          *                        the {@link TOSCAAnalyzer} object to access the data model
72          *
73          * @return the complete {@link TTopologyTemplate}
74          */
75         public List<TTopologyTemplate> completePlaceholderTopology(List<TNodeTemplate> placeHolders, TOSCAAnalyzer toscaAnalyzer) {
76
77                 List<TTopologyTemplate> solutions = new ArrayList<TTopologyTemplate>();
78
79                 for (TNodeTemplate placeHolder : placeHolders) {
80
81                         List<TNodeType> suitableNodeTypes = PlaceHolderHandler.getSuitableNodeTypes(placeHolder, toscaAnalyzer);
82
83                         // if there are more than one solution for an inserted NodeTemplate,
84                         // create copies of the topology. The user can choose from them after the completion.
85                         TTopologyTemplate topologyCopy = null;
86
87                         for (TNodeType suitableNodeType : suitableNodeTypes) {
88                                 topologyCopy = new TTopologyTemplate();
89                                 topologyCopy.getNodeTemplateOrRelationshipTemplate().addAll(topology.getNodeTemplateOrRelationshipTemplate());
90
91                                 TNodeTemplate nodeTemplate = ModelUtilities.instantiateNodeTemplate(suitableNodeType);
92
93                                 List<TNodeTemplate> sourceTemplates = new ArrayList<>();
94
95                                 // contains RelationshipTemplates connecting to a place holder.
96                                 // These Templates are generic and have to be replaced with
97                                 // concrete ones.
98                                 List<TRelationshipTemplate> placeholderConnections = new ArrayList<>();
99
100                                 TRelationshipTemplate foundTarget = null;
101                                 for (TEntityTemplate entity : topology.getNodeTemplateOrRelationshipTemplate()) {
102                                         if (entity instanceof TRelationshipTemplate) {
103                                                 TRelationshipTemplate rt = (TRelationshipTemplate) entity;
104                                                 if (((TNodeTemplate) rt.getTargetElement().getRef()).getId().equals(placeHolder.getId())) {
105                                                         TRelationshipTemplate placeHolderConnection = (TRelationshipTemplate) entity;
106                                                         placeholderConnections.add(placeHolderConnection);
107                                                         sourceTemplates.add((TNodeTemplate) placeHolderConnection.getSourceElement().getRef());
108                                                 } else if (((TNodeTemplate) rt.getSourceElement().getRef()).getId().equals(placeHolder.getId())) {
109                                                         foundTarget = (TRelationshipTemplate) entity;
110                                                 }
111                                         }
112                                 }
113
114                                 // collect all possible RelationshipTemplates that can be used to connect to the placeholder
115                                 choices = new ArrayList<>();
116
117                                 for (TNodeTemplate sourceTemplate : sourceTemplates) {
118                                         // find matching RelationshipTypes to connect the Node Templates
119                                         List<TRelationshipType> suitableRTs = NodeTemplateConnector.findRelationshipType(sourceTemplate, nodeTemplate, toscaAnalyzer, null);
120                                         for (TRelationshipType rt : suitableRTs) {
121                                                 TRelationshipTemplate relationship = ModelUtilities.instantiateRelationshipTemplate(rt, sourceTemplate, nodeTemplate);
122                                                 choices.add(relationship);
123                                         }
124                                 }
125
126                                 // set the source elements of the RelationshipTemplates connecting from the replaced placeholder to other NodeTemplates
127                                 for (TEntityTemplate entityTemplate : topologyCopy.getNodeTemplateOrRelationshipTemplate()) {
128                                         if (entityTemplate instanceof TRelationshipTemplate) {
129                                                 TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) entityTemplate;
130                                                 if (relationshipTemplate.equals(foundTarget)) {
131                                                         foundTarget.getSourceElement().setRef(nodeTemplate);
132                                                 }
133                                         }
134                                 }
135
136                                 // remove the generic connections to the place holder
137                                 topologyCopy.getNodeTemplateOrRelationshipTemplate().removeAll(placeholderConnections);
138
139                                 // there are more than one possible Relationship Templates to connect to the inserted NodeTemplate(s), so
140                                 // interrupt the completion and ask the user which one to insert
141                                 if (choices.size() > 1 && sourceTemplates.size() == 1) {
142
143                                         choices.add(sourceTemplates.get(0));
144                                         choices.add(nodeTemplate);
145                                         topologyCopy.getNodeTemplateOrRelationshipTemplate().remove(placeHolder);
146
147                                         userInteraction = true;
148                                         this.placeHolder = placeHolder;
149                                         break;
150                                 } else if (choices.size() == 1 || sourceTemplates.size() > 1) {
151                                         // replace the place holder with an actual NodeTemplate
152                                         topologyCopy.getNodeTemplateOrRelationshipTemplate().addAll(choices);
153                                         topologyCopy.getNodeTemplateOrRelationshipTemplate().add(nodeTemplate);
154                                         topologyCopy.getNodeTemplateOrRelationshipTemplate().remove(placeHolder);
155                                 }
156                                 solutions.add(topologyCopy);
157                         }
158                 }
159                 return solutions;
160         }
161
162         /**
163          * Returns the replaced place holder.
164          *
165          * @return the place holder
166          */
167         public TNodeTemplate getPlaceHolder() {
168                 return placeHolder;
169         }
170
171         /**
172          * Returns whether an user interaction is necessary or not.
173          *
174          * @return the field userInteraction
175          */
176         public boolean getUserInteraction() {
177                 return userInteraction;
178         }
179
180         /**
181          * Possible Relationship Template choices.
182          *
183          * @return the field choices
184          */
185         public List<TEntityTemplate> getChoices() {
186                 return choices;
187         }
188 }