Skip to content

Commit 4b9b489

Browse files
committed
bug fix in .tosca generation: relationship templates in topology template files
1 parent 654e83c commit 4b9b489

File tree

2 files changed

+83
-55
lines changed

2 files changed

+83
-55
lines changed

src/main/java/fr/softeam/toscadesigner/export/AbstractToscaFileGenerator.java

Lines changed: 82 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,27 @@
3434
import org.modelio.metamodel.uml.statik.Class;
3535
import org.modelio.vcore.smkernel.mapi.MObject;
3636

37-
@objid ("e7453252-f578-4da1-815c-d2ce0e765130")
37+
@objid("e7453252-f578-4da1-815c-d2ce0e765130")
3838
public abstract class AbstractToscaFileGenerator {
39-
@objid ("6ca66b17-c54f-42dc-862d-4c41f8cbec9b")
39+
@objid("6ca66b17-c54f-42dc-862d-4c41f8cbec9b")
4040
private static final String TEMPLATE_PATH = "/fr/softeam/templates/";
4141

42-
@objid ("44617ecf-78ee-46d2-a367-cbdfee5c0854")
42+
@objid("44617ecf-78ee-46d2-a367-cbdfee5c0854")
4343
private static final String MAIN_TEMPLATE = "_mainTemplate";
4444

45-
@objid ("a897a13e-b8dc-4f4f-b967-60133eb7f69d")
45+
@objid("a897a13e-b8dc-4f4f-b967-60133eb7f69d")
4646
protected Handlebars handlebars = setupHandlebars();
4747

48-
@objid ("e1bdb1e7-0783-441d-96e1-fdaa0f8e8514")
48+
@objid("e1bdb1e7-0783-441d-96e1-fdaa0f8e8514")
4949
protected abstract String getFileType();
5050

51-
@objid ("ebedc3d7-f673-4680-a8b3-159124af40c8")
51+
@objid("ebedc3d7-f673-4680-a8b3-159124af40c8")
5252
protected abstract String[] getFileExtensions();
5353

54-
@objid ("a064e044-abc6-430f-9a31-680bf8f13dad")
54+
@objid("a064e044-abc6-430f-9a31-680bf8f13dad")
5555
public abstract void generateContent(MObject object) throws IOException;
5656

57-
@objid ("0a64efd3-9d89-46b9-91e8-40aaa00626a4")
57+
@objid("0a64efd3-9d89-46b9-91e8-40aaa00626a4")
5858
protected String saveToFile(String[] fileExtensions, String fileType) {
5959
FileDialog fileDialog = new FileDialog(Display.getCurrent().getActiveShell(), SWT.SAVE);
6060
fileDialog.setFilterExtensions(fileExtensions);
@@ -64,7 +64,7 @@ protected String saveToFile(String[] fileExtensions, String fileType) {
6464
return filePath;
6565
}
6666

67-
@objid ("3a782c82-535e-40a1-96b6-10d70a8fd4b4")
67+
@objid("3a782c82-535e-40a1-96b6-10d70a8fd4b4")
6868
private Handlebars setupHandlebars() {
6969
Handlebars handlebars = new Handlebars(new ClassPathTemplateLoader(TEMPLATE_PATH, ".hbs"));
7070
handlebars.setPrettyPrint(true);
@@ -133,15 +133,10 @@ private Handlebars setupHandlebars() {
133133
}
134134
throw new RuntimeException("Stereotype property " + searchedPropertyName + " not found in " + context);
135135
});
136-
handlebars.registerHelper("noStereotypeApplications", (ModelTree context, Options options) ->
137-
Stream.concat(
138-
context.getOwnedElement().stream(),
139-
context instanceof Class ? ((Class) context).getOwnedAttribute().stream() : Stream.empty()
140-
)
141-
.noneMatch(element -> element.getExtension().stream()
142-
.anyMatch(stereotype -> stereotype.getName().equals(options.params[0]))
143-
)
144-
);
136+
// Helper returning true if none of the owned elements/attributes/ends apply the
137+
// given stereotype name
138+
handlebars.registerHelper("noStereotypeApplications",
139+
(context, options) -> hasNoStereotypeApplications((ModelTree) context, (String) options.params[0]));
145140
handlebars.registerHelper("imports", (ModelElement context, Options options) -> {
146141

147142
Set<Import> imports = new HashSet<>();
@@ -159,30 +154,23 @@ private Handlebars setupHandlebars() {
159154
imports.add(new Import(derivedFromValue + ".tosca", targetNamespace, "MYRTUS-"));
160155
}
161156

162-
// 2. Check for non-tosca valid source types in capabilities
163-
// CapabilityDefinitionsType capabilityDefinitionsTypeInstance = tNodeType.getCapabilityDefinitions();
164-
// List<TCapabilityDefinition> capabilityDefinitions = capabilityDefinitionsTypeInstance.getCapabilityDefinition();
165-
// To develop when capabilities will be supported
166-
// for (TCapabilityDefinition tCapabilityDefinition : capabilityDefinitions) {
167-
// if (hasNonToscaValidSourceType(capability)) {
168-
// imports.add(/* import statement */);
169-
// }
170-
// }
171157
} else if (new TopologyTemplateChecker().isTypeOf(context)) {
172-
// 3. Check for non-tosca types in node templates
173-
List<TNodeTemplate> nodeTemplates = context.getCompositionChildren().stream().filter(object -> {
174-
Stereotype tNodeTemplateStereotype = ToscaDesignerModule.getInstance().getModuleContext()
175-
.getModelingSession().getMetamodelExtensions()
176-
.getStereotype("TNodeTemplate", object.getMClass());
177-
return tNodeTemplateStereotype != null
178-
&& ((ModelElement) object).isStereotyped(tNodeTemplateStereotype);
179-
}).map(Class.class::cast).map(c -> TNodeTemplate.safeInstantiate(c)).collect(Collectors.toList());
180-
for (TNodeTemplate nodeTemplate : nodeTemplates) {
181-
182-
String targetNamespace = ((Class) context).getOwner().getName();
183-
imports.add(new Import(nodeTemplate.getElement().getName() + ".tosca", targetNamespace , "MYRTUS-"));
184-
185-
}
158+
// 2. Check for non-tosca types in node templates
159+
List<TNodeTemplate> nodeTemplates = context.getCompositionChildren().stream().filter(object -> {
160+
Stereotype tNodeTemplateStereotype = ToscaDesignerModule.getInstance().getModuleContext()
161+
.getModelingSession().getMetamodelExtensions()
162+
.getStereotype("TNodeTemplate", object.getMClass());
163+
return tNodeTemplateStereotype != null
164+
&& ((ModelElement) object).isStereotyped(tNodeTemplateStereotype);
165+
}).map(Class.class::cast).map(c -> TNodeTemplate.safeInstantiate(c)).collect(Collectors.toList());
166+
for (TNodeTemplate nodeTemplate : nodeTemplates) {
167+
TNodeType nodeType = nodeTemplate.getNodeType();
168+
if (nodeType != null) {
169+
String typeName = nodeType.getElement().getName();
170+
String targetNamespace = nodeType.getTargetNamespace();
171+
imports.add(new Import(typeName + ".tosca", targetNamespace, "MYRTUS-"));
172+
}
173+
}
186174

187175
}
188176

@@ -195,7 +183,7 @@ private Handlebars setupHandlebars() {
195183
return handlebars;
196184
}
197185

198-
@objid ("4e0fc0cf-420e-4626-b34d-fd6df12a1e01")
186+
@objid("4e0fc0cf-420e-4626-b34d-fd6df12a1e01")
199187
private String generateImportString(Set<Import> imports) {
200188
StringBuilder importString = new StringBuilder();
201189
if (!imports.isEmpty())
@@ -209,7 +197,47 @@ private String generateImportString(Set<Import> imports) {
209197
return importString.toString();
210198
}
211199

212-
@objid ("b6716c1e-6ab4-4dce-8bbe-f749a6185d60")
200+
/**
201+
* Return true if none of the owned elements / attributes / composition children
202+
* (recursively)
203+
* apply the given stereotype name.
204+
* Recursive traversal replaces previous reliance on owned association ends.
205+
*/
206+
private boolean hasNoStereotypeApplications(ModelTree context, String stereotypeName) {
207+
Stream<ModelElement> ownedElements = context.getOwnedElement().stream()
208+
.filter(ModelElement.class::isInstance)
209+
.map(ModelElement.class::cast);
210+
211+
Stream<ModelElement> ownedAttributes = context instanceof Class
212+
? ((Class) context).getOwnedAttribute().stream()
213+
.filter(ModelElement.class::isInstance)
214+
.map(ModelElement.class::cast)
215+
: Stream.empty();
216+
217+
Stream<ModelElement> compositionDescendants = compositionDescendants(context);
218+
219+
return Stream.concat(Stream.concat(ownedElements, ownedAttributes), compositionDescendants)
220+
.distinct()
221+
.noneMatch(element -> element.getExtension().stream()
222+
.anyMatch(st -> st.getName().equals(stereotypeName)));
223+
}
224+
225+
/**
226+
* Recursively collect all composition children below the given context.
227+
*/
228+
private Stream<ModelElement> compositionDescendants(ModelTree parent) {
229+
return parent.getCompositionChildren().stream()
230+
.filter(ModelElement.class::isInstance)
231+
.map(ModelElement.class::cast)
232+
.flatMap(child -> {
233+
if (child instanceof ModelTree) {
234+
return Stream.concat(Stream.of(child), compositionDescendants((ModelTree) child));
235+
}
236+
return Stream.of(child);
237+
});
238+
}
239+
240+
@objid("b6716c1e-6ab4-4dce-8bbe-f749a6185d60")
213241
protected String renderTemplate(Handlebars handlebars, Object data) throws IOException {
214242
Template mainTemplate = handlebars.compile(MAIN_TEMPLATE);
215243
try (StringWriter writer = new StringWriter()) {
@@ -218,25 +246,25 @@ protected String renderTemplate(Handlebars handlebars, Object data) throws IOExc
218246
}
219247
}
220248

221-
@objid ("a0abc478-ed5d-497e-b9ec-7a8ca374ad06")
249+
@objid("a0abc478-ed5d-497e-b9ec-7a8ca374ad06")
222250
final class Import {
223-
@objid ("17c76b26-3910-426f-8cd6-38dede4173ba")
251+
@objid("17c76b26-3910-426f-8cd6-38dede4173ba")
224252
private String file;
225253

226-
@objid ("cd485831-b7d3-44c3-a39f-0cd6485a7afd")
254+
@objid("cd485831-b7d3-44c3-a39f-0cd6485a7afd")
227255
private String namespaceUri;
228256

229-
@objid ("bc36ccf4-d7ce-4126-bb6a-e5b56eb5001f")
257+
@objid("bc36ccf4-d7ce-4126-bb6a-e5b56eb5001f")
230258
private String namespacePrefix;
231259

232-
@objid ("cab33e64-b830-4ee5-be1e-d67a046d71b3")
233-
public Import(String file, String namespaceUri, String namespacePrefix) {
260+
@objid("cab33e64-b830-4ee5-be1e-d67a046d71b3")
261+
public Import(String file, String namespaceUri, String namespacePrefix) {
234262
this.file = file;
235263
this.namespaceUri = namespaceUri;
236264
this.namespacePrefix = namespacePrefix;
237265
}
238266

239-
@objid ("9e614e14-9276-4de0-adbf-7d3284e36ffa")
267+
@objid("9e614e14-9276-4de0-adbf-7d3284e36ffa")
240268
@Override
241269
public boolean equals(Object o) {
242270
if (this == o)
@@ -249,22 +277,22 @@ public boolean equals(Object o) {
249277
&& namespacePrefix.equals(anImport.namespacePrefix);
250278
}
251279

252-
@objid ("7539be58-524e-48ff-911d-db847524b474")
280+
@objid("7539be58-524e-48ff-911d-db847524b474")
253281
public String getFile() {
254282
return file;
255283
}
256284

257-
@objid ("e1838d70-2162-47c9-ad66-a1a204354ba1")
285+
@objid("e1838d70-2162-47c9-ad66-a1a204354ba1")
258286
public String getNamespaceUri() {
259287
return namespaceUri;
260288
}
261289

262-
@objid ("687bfd11-4d48-4a5c-89d0-f9dcd58d825d")
290+
@objid("687bfd11-4d48-4a5c-89d0-f9dcd58d825d")
263291
public String getNamespacePrefix() {
264292
return namespacePrefix;
265293
}
266294

267-
@objid ("76de5aa3-91b2-44f3-9741-8405f5ca3e6d")
295+
@objid("76de5aa3-91b2-44f3-9741-8405f5ca3e6d")
268296
@Override
269297
public int hashCode() {
270298
return Objects.hash(file, namespaceUri, namespacePrefix);

src/main/resources/fr/softeam/templates/TTopologyTemplate.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ topology_template:
2727
{{#unless (noStereotypeApplications this "TRelationshipTemplateEnd")}}
2828
relationship_templates:
2929
{{#ownedElement}}{{#targetingEnd}}{{#association as |association|}}{{#extension as |extension|}}{{#eq extension.name "TRelationshipTemplate"}}
30-
{{../name}}:
30+
{{association.name}}:
3131
type: {{getProperty association "type"}}
3232
{{/eq}}{{/extension}}{{/association}}{{/targetingEnd}}{{/ownedElement}}
3333
{{/unless}}

0 commit comments

Comments
 (0)