3434import org .modelio .metamodel .uml .statik .Class ;
3535import org .modelio .vcore .smkernel .mapi .MObject ;
3636
37- @ objid ("e7453252-f578-4da1-815c-d2ce0e765130" )
37+ @ objid ("e7453252-f578-4da1-815c-d2ce0e765130" )
3838public 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 );
0 commit comments