]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/typicals/TypicalUtil.java
Sync git svn branch with SVN repository r33249.
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / typicals / TypicalUtil.java
1 /*******************************************************************************\r
2  * Copyright (c) 2012 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.modeling.typicals;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Collection;\r
16 import java.util.Collections;\r
17 import java.util.List;\r
18 import java.util.Map;\r
19 import java.util.Set;\r
20 import java.util.concurrent.Semaphore;\r
21 import java.util.concurrent.atomic.AtomicReference;\r
22 import java.util.function.Consumer;\r
23 \r
24 import org.simantics.NameLabelMode;\r
25 import org.simantics.NameLabelUtil;\r
26 import org.simantics.Simantics;\r
27 import org.simantics.databoard.Bindings;\r
28 import org.simantics.db.ReadGraph;\r
29 import org.simantics.db.RequestProcessor;\r
30 import org.simantics.db.Resource;\r
31 import org.simantics.db.WriteGraph;\r
32 import org.simantics.db.WriteOnlyGraph;\r
33 import org.simantics.db.common.CommentMetadata;\r
34 import org.simantics.db.common.NamedResource;\r
35 import org.simantics.db.common.request.FreshName;\r
36 import org.simantics.db.common.request.ObjectsWithType;\r
37 import org.simantics.db.common.request.PossibleIndexRoot;\r
38 import org.simantics.db.common.request.UniqueRead;\r
39 import org.simantics.db.common.request.WriteResultRequest;\r
40 import org.simantics.db.common.uri.UnescapedChildMapOfResource;\r
41 import org.simantics.db.common.utils.CommonDBUtils;\r
42 import org.simantics.db.common.utils.NameUtils;\r
43 import org.simantics.db.exception.DatabaseException;\r
44 import org.simantics.db.exception.RuntimeDatabaseException;\r
45 import org.simantics.db.layer0.adapter.CopyHandler;\r
46 import org.simantics.db.layer0.adapter.Instances;\r
47 import org.simantics.db.layer0.request.Configuration;\r
48 import org.simantics.db.layer0.request.PossibleModel;\r
49 import org.simantics.db.layer0.util.ClipboardUtils;\r
50 import org.simantics.db.layer0.util.SimanticsClipboard.Representation;\r
51 import org.simantics.db.layer0.util.SimanticsClipboardImpl;\r
52 import org.simantics.db.layer0.util.SimanticsKeys;\r
53 import org.simantics.db.layer0.variable.Variable;\r
54 import org.simantics.db.layer0.variable.Variables;\r
55 import org.simantics.db.procedure.Procedure;\r
56 import org.simantics.db.request.WriteResult;\r
57 import org.simantics.diagram.stubs.DiagramResource;\r
58 import org.simantics.graph.db.IImportAdvisor;\r
59 import org.simantics.graph.db.TransferableGraphs;\r
60 import org.simantics.graph.representation.Root;\r
61 import org.simantics.graph.representation.TransferableGraph1;\r
62 import org.simantics.layer0.Layer0;\r
63 import org.simantics.modeling.ModelingResources;\r
64 import org.simantics.modeling.ModelingUtils.CompositeInfo;\r
65 import org.simantics.modeling.ModelingUtils.DiagramComponentInfo;\r
66 import org.simantics.modeling.services.ComponentNamingUtil;\r
67 import org.simantics.modeling.services.NamingException;\r
68 import org.simantics.operation.Layer0X;\r
69 import org.simantics.scl.runtime.function.Function2;\r
70 import org.simantics.scl.runtime.function.Function4;\r
71 import org.simantics.structural.stubs.StructuralResource2;\r
72 import org.simantics.structural2.utils.StructuralUtils;\r
73 import org.simantics.ui.SimanticsUI;\r
74 import org.simantics.utils.datastructures.Pair;\r
75 import org.simantics.utils.ui.dialogs.ShowMessage;\r
76 \r
77 /**\r
78  * @author Tuukka Lehtonen\r
79  */\r
80 public class TypicalUtil {\r
81 \r
82     private static final boolean DEBUG = false;\r
83 \r
84     private static class TypicalNamingFunction implements Function2<ReadGraph, Resource, String> {\r
85         private NameLabelMode mode;\r
86 \r
87         @Override\r
88         public String apply(ReadGraph graph, Resource r) {\r
89             try {\r
90                 if (mode == null)\r
91                     mode = NameLabelUtil.getNameLabelMode(graph);\r
92                 Variable v = Variables.getPossibleVariable(graph, r);\r
93                 if (v != null) {\r
94                     Resource root = Variables.getPossibleIndexRoot(graph, v);\r
95                     if (root != null) {\r
96                         Variable rootV = Variables.getVariable(graph, root);\r
97                         List<Variable> path = Variables.getPath(graph, rootV, v);\r
98                         path.add(0, rootV);\r
99                         return typicalLabel(graph, v, path);\r
100                     }\r
101                 }\r
102                 return TypicalUtil.getName(graph, r);\r
103             } catch (DatabaseException e) {\r
104                 throw new RuntimeDatabaseException(e);\r
105             }\r
106         }\r
107 \r
108         protected String typicalLabel(ReadGraph graph, Variable v, List<Variable> path) throws DatabaseException {\r
109             StringBuilder sb = new StringBuilder();\r
110             labelVariable(graph, v, sb);\r
111             if (path.size() > 0) {\r
112                 sb.append(" (");\r
113                 for (Variable vv : path) {\r
114                     sb.append("/");\r
115                     labelVariable(graph, vv, sb);\r
116                 }\r
117                 sb.append(")");\r
118             }\r
119             return sb.toString();\r
120         }\r
121 \r
122         protected StringBuilder labelVariable(ReadGraph graph, Variable v, StringBuilder result) throws DatabaseException {\r
123             Resource r = v.getPossibleRepresents(graph);\r
124             if (r != null) {\r
125                 result.append(NameLabelUtil.modalName(graph, r, mode));\r
126             } else {\r
127                 result.append(NameLabelUtil.modalName(graph, v, mode));\r
128             }\r
129             return result;\r
130         }\r
131     };\r
132 \r
133     public static List<NamedResource> toNamedResources(RequestProcessor processor, final Collection<Resource> rs) throws DatabaseException {\r
134         return toNamedResources(processor, rs, new TypicalNamingFunction());\r
135     }\r
136 \r
137     public static List<NamedResource> toNamedResources(RequestProcessor processor, final Collection<Resource> rs, final Function2<ReadGraph, Resource, String> namingFunction) throws DatabaseException {\r
138         return processor.syncRequest(new UniqueRead<List<NamedResource>>() {\r
139             @Override\r
140             public List<NamedResource> perform(ReadGraph graph) throws DatabaseException {\r
141                 return toNamedResources(graph, rs, namingFunction);\r
142             }\r
143         });\r
144     }\r
145 \r
146     public static List<NamedResource> toNamedResources(ReadGraph graph, Collection<Resource> rs, final Function2<ReadGraph, Resource, String> namingFunction) throws DatabaseException {\r
147         List<NamedResource> result = new ArrayList<>(rs.size());\r
148         for (Resource r : rs)\r
149             result.add(new NamedResource(namingFunction.apply(graph, r), r));\r
150         return result;\r
151     }\r
152 \r
153     public static String getName(ReadGraph graph, Resource r) throws DatabaseException {\r
154         String s = graph.getPossibleAdapter(r, String.class);\r
155         if (s == null)\r
156             s = NameUtils.getSafeLabel(graph, r);\r
157         return s;\r
158     }\r
159 \r
160     public static WriteResult<Resource> instantiateTemplate(\r
161             Resource target,\r
162             NamedResource template,\r
163             Consumer<Pair<WriteGraph, Resource>> successContinuation)\r
164     {\r
165         return new WriteResultRequest<Resource>() {\r
166             @Override\r
167             public Resource perform(WriteGraph graph) throws DatabaseException {\r
168                 // Custom instantiation by copying the original and mapping the original to the copy\r
169                 CommonDBUtils.selectClusterSet(graph, target);\r
170                 SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();\r
171                 CopyHandler ch = new TypicalCompositeCopyHandler(template.getResource());\r
172                 ch.copyToClipboard(graph, clipboard);\r
173 \r
174                 Map<String,Object> hints = Collections.singletonMap(ClipboardUtils.HINT_TARGET_RESOURCE, target);\r
175 \r
176                 for (Set<Representation> object : clipboard.getContents()) {\r
177                     TransferableGraph1 tg = ClipboardUtils.accept(graph, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH, hints);\r
178                     if (tg != null) {\r
179                         DiagramPasteImportAdvisor advisor = new DiagramPasteImportAdvisor(graph, target, template.getName());\r
180                         TransferableGraphs.importGraph1(graph, tg, advisor);\r
181                         Resource copy = advisor.getRoot();\r
182 \r
183                         configureCopyType(graph, copy, template.getResource());\r
184                         associateCopyToTemplate(graph, copy, template.getResource());\r
185 \r
186                         if (successContinuation!= null)\r
187                             successContinuation.accept(Pair.make(graph, copy));\r
188 \r
189                         return copy;\r
190                     }\r
191                 }\r
192                 throw new DatabaseException("Failed to instantiate typical template through clipboard");\r
193             }\r
194         };\r
195     }\r
196 \r
197     public static void configureCopyType(WriteGraph graph, Resource copy, Resource template) throws DatabaseException {\r
198         // Remove master template instance tag type(s)\r
199         Layer0 L0 = Layer0.getInstance(graph);\r
200         DiagramResource DIA = DiagramResource.getInstance(graph);\r
201         ModelingResources MOD = ModelingResources.getInstance(graph);\r
202         for (Resource type : graph.getObjects(template, L0.InstanceOf)) {\r
203             if (graph.isInheritedFrom(type, MOD.MasterTypicalCompositeType))\r
204                 graph.deny(copy, L0.InstanceOf, type);\r
205             else\r
206                 graph.claim(copy, L0.InstanceOf, null, type);\r
207         }\r
208         for (Resource templateDiagram : graph.getObjects(template, MOD.CompositeToDiagram)) {\r
209             Resource templateDiagramType = graph.getPossibleType(templateDiagram, DIA.Diagram);\r
210             if (templateDiagramType != null) {\r
211                 for (Resource copiedDiagram : graph.getObjects(copy, MOD.CompositeToDiagram)) {\r
212                     graph.claim(copiedDiagram, L0.InstanceOf, null, templateDiagramType);\r
213                 }\r
214             }\r
215         }\r
216     }\r
217 \r
218     public static void associateCopyToTemplate(WriteGraph graph, Resource copy, Resource template) throws DatabaseException {\r
219         DiagramResource DIA = DiagramResource.getInstance(graph);\r
220         ModelingResources MOD = ModelingResources.getInstance(graph);\r
221         Resource templateDiagram = graph.getSingleObject(template, MOD.CompositeToDiagram);\r
222         Resource copyDiagram = graph.getSingleObject(copy, MOD.CompositeToDiagram);\r
223         Map<String, Resource> templateDiagramElements = graph.syncRequest(new UnescapedChildMapOfResource(templateDiagram));\r
224         Map<String, Resource> copyDiagramElements = graph.syncRequest(new UnescapedChildMapOfResource(copyDiagram));\r
225 \r
226         // Associations are intentionally bi-directional\r
227         graph.claim(copyDiagram, MOD.HasDiagramSource, MOD.DiagramHasInstance, templateDiagram);\r
228         for (String element : templateDiagramElements.keySet()) {\r
229             Resource templateElement = templateDiagramElements.get(element);\r
230             if (!graph.isInstanceOf(templateElement, DIA.Element))\r
231                 continue;\r
232             Resource copyElement = copyDiagramElements.get(element);\r
233             graph.claim(copyElement, MOD.HasElementSource, MOD.ElementHasInstance, templateElement);\r
234             graph.claim(copyElement, MOD.IsTemplatized, MOD.IsTemplatized, copyElement);\r
235         }\r
236 \r
237         Long modCount = graph.getPossibleRelatedValue(copyDiagram, DIA.HasModCount);\r
238         if (modCount == null)\r
239             modCount = 0L;\r
240         modCount += 1L << 32;\r
241         graph.claimLiteral(copyDiagram, DiagramResource.getInstance(graph).HasModCount, modCount, Bindings.LONG);\r
242     }\r
243 \r
244     /**\r
245      * @param graph\r
246      * @param typicalCompositeInstance\r
247      * @param excludedComponents the set of components in the specified\r
248      *        composite that are not freshly renamed or <code>null</code> to\r
249      *        freshly name all components\r
250      * @throws DatabaseException\r
251      */\r
252     public static void generateFreshModuleNames(WriteGraph graph, Resource typicalCompositeInstance, Set<Resource> excludedComponents) throws DatabaseException {\r
253         Layer0 L0 = Layer0.getInstance(graph);\r
254         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
255         Resource configurationRoot = graph.sync(new Configuration(typicalCompositeInstance));\r
256         for(Map.Entry<String, Resource> entry : graph.syncRequest(new UnescapedChildMapOfResource(typicalCompositeInstance)).entrySet()) {\r
257             Resource component = entry.getValue();\r
258             if (!graph.isInstanceOf(component, STR.Component))\r
259                 continue;\r
260             if (excludedComponents != null && excludedComponents.contains(component))\r
261                 continue;\r
262             try {\r
263                 String renamed = ComponentNamingUtil.findFreshInstanceName(graph, SimanticsUI.getProject(), configurationRoot, typicalCompositeInstance, component);\r
264                 if (DEBUG)\r
265                     System.out.println("Typicals: renamed " + entry.getKey() + " -> " + renamed);\r
266                 graph.claimLiteral(entry.getValue(), L0.HasName, L0.NameOf, renamed, Bindings.STRING);\r
267             } catch (NamingException e) {\r
268                 throw new DatabaseException(e);\r
269             }\r
270         }\r
271     }\r
272 \r
273     public static class DiagramPasteImportAdvisor implements IImportAdvisor {\r
274 \r
275         protected final Resource library;\r
276         protected final Resource model;\r
277         protected Resource diagram;\r
278         protected final String diagramName;\r
279 \r
280         public DiagramPasteImportAdvisor(ReadGraph graph, Resource library, String originalName) throws DatabaseException {\r
281             this.library = library;\r
282             this.diagram = null;\r
283             this.diagramName = graph.syncRequest(new FreshName(library, originalName));\r
284             this.model = graph.syncRequest(new PossibleModel(library));\r
285         }\r
286 \r
287         public void analyzeType(ReadGraph graph, Root root) throws DatabaseException {\r
288         }\r
289 \r
290         @Override\r
291         public Resource analyzeRoot(ReadGraph graph, Root root) throws DatabaseException {\r
292                 if("%model".equals(root.name)) return model;\r
293                 return null;\r
294         }\r
295         @Override\r
296         public Resource createRoot(WriteOnlyGraph graph, Root root) throws DatabaseException {\r
297 \r
298                 Layer0 l0 = graph.getService(Layer0.class);\r
299             if(CompositeInfo.isComposite(root.name)) {\r
300                 // Use existing if available\r
301                 if(diagram == null) diagram = graph.newResource();\r
302                 graph.claim(library, l0.ConsistsOf, l0.PartOf, diagram);\r
303                 graph.newClusterSet(diagram);\r
304                 graph.setClusterSet4NewResource(diagram);\r
305                 graph.addLiteral(diagram, l0.HasName, l0.NameOf, l0.String, diagramName, Bindings.STRING);\r
306                 return diagram;\r
307             } else if (DiagramComponentInfo.isDiagramComponent(root.name)) {\r
308                 DiagramComponentInfo info = DiagramComponentInfo.parse(root.name);\r
309                 Resource child = graph.newResource();\r
310                 graph.addLiteral(child, l0.HasName, l0.NameOf, l0.String, info.getUnescapedComponentName(), Bindings.STRING);\r
311                 return child;\r
312             } else {\r
313                 throw new DatabaseException("Unclassified root " + root.name);\r
314             }\r
315 \r
316         }\r
317 \r
318         public Resource getRoot() {\r
319             return diagram;\r
320         }\r
321 \r
322     }\r
323 \r
324     /**\r
325      * @param graph\r
326      * @param typicalInstanceComposite\r
327      * @param renamedComponentsOutput a set that can be provided to get the set\r
328      *        of components that was renamed as output from this method or\r
329      *        <code>null</code> to not collect renamed components\r
330      * @throws DatabaseException\r
331      */\r
332     public static void applyTypicalModuleNames(WriteGraph graph, Resource typicalInstanceComposite, Set<Resource> renamedComponentsOutput) throws DatabaseException {\r
333         \r
334         Layer0 L0 = Layer0.getInstance(graph);\r
335         StructuralResource2 STR = StructuralResource2.getInstance(graph); \r
336 \r
337         Function4<ReadGraph, Resource, Resource, String, String> nameEvaluator = getTypicalNamingFunction(graph, typicalInstanceComposite);\r
338         if (nameEvaluator == null)\r
339             return;\r
340 \r
341         Collection<Resource> components = graph.syncRequest(new ObjectsWithType(typicalInstanceComposite, L0.ConsistsOf, STR.Component));\r
342         for (Resource component : components) {\r
343                 applyTypicalModuleName(graph, component, nameEvaluator, renamedComponentsOutput);  \r
344         }\r
345         \r
346     }\r
347 \r
348     public static boolean applyTypicalModuleName(WriteGraph graph, Resource instanceComponent, Function4<ReadGraph, Resource, Resource, String, String> nameEvaluator, Set<Resource> renamedComponentsOutput) throws DatabaseException {\r
349 \r
350         Layer0 L0 = Layer0.getInstance(graph);\r
351         StructuralResource2 STR = StructuralResource2.getInstance(graph); \r
352         ModelingResources MOD = ModelingResources.getInstance(graph);\r
353 \r
354         Resource componentType = graph.getPossibleType(instanceComponent, STR.Component);\r
355         if (componentType == null)\r
356             return false;\r
357 \r
358         Resource instanceElement = graph.getPossibleObject(instanceComponent, MOD.ComponentToElement);\r
359         if (instanceElement == null)\r
360             return false;\r
361 \r
362         Resource templateElement = graph.getPossibleObject(instanceElement, MOD.HasElementSource);\r
363         if (templateElement == null)\r
364             return false;\r
365 \r
366         Resource templateComponent = graph.getPossibleObject(templateElement, MOD.ElementToComponent);\r
367         if (templateComponent == null)\r
368             return false;\r
369 \r
370         // TODO: Use variables and EXPRESSION property instead ?\r
371         String nameExpression = graph.getPossibleRelatedValue(templateComponent, L0.HasName, Bindings.STRING);\r
372         if (nameExpression == null)\r
373             return false;\r
374 \r
375         Resource instanceComposite = graph.getPossibleObject(instanceComponent, L0.PartOf);\r
376         if (instanceComposite == null)\r
377             return false;\r
378         \r
379         // This evaluator replaces % with assigned primary position name\r
380         String evaluatedInstanceName = (String) nameEvaluator.apply(graph, instanceComposite, instanceComponent, nameExpression);\r
381         if(evaluatedInstanceName == null)\r
382                 return false;\r
383 \r
384         String instanceName = graph.getPossibleRelatedValue(instanceComponent, L0.HasName, Bindings.STRING);\r
385         if(instanceName == null)\r
386                 return false;\r
387 \r
388         if(!evaluatedInstanceName.equals(instanceName)) {\r
389                 \r
390             graph.claimLiteral(instanceComponent, L0.HasName, evaluatedInstanceName, Bindings.STRING);\r
391             if (renamedComponentsOutput != null)\r
392                 renamedComponentsOutput.add(instanceComponent);\r
393             \r
394             if (DEBUG)\r
395                 System.out.println("TypicalUtil.applyTypicalModuleName: applied name expression " + nameExpression + " -> " + instanceName + " -> " + evaluatedInstanceName);\r
396             \r
397             return true;\r
398                 \r
399         }\r
400         \r
401         return false;\r
402         \r
403     }\r
404     \r
405     /**\r
406      * @param graph\r
407      * @param typicalComposite\r
408      * @param componentsToCheck the set of components to check for required\r
409      *        naming\r
410      * @throws DatabaseException\r
411      */\r
412     public static void applySelectedModuleNames(WriteGraph graph, Resource typicalComposite, List<Resource> componentsToCheck) throws DatabaseException {\r
413         Layer0 L0 = Layer0.getInstance(graph);\r
414         StructuralResource2 STR = StructuralResource2.getInstance(graph); \r
415         ModelingResources MOD = ModelingResources.getInstance(graph);\r
416 \r
417         Function4<ReadGraph, Resource, Resource, String, String> nameEvaluator = getTypicalNamingFunction(graph, typicalComposite);\r
418         if (nameEvaluator == null)\r
419             return;\r
420 \r
421         for (Resource component : componentsToCheck) {\r
422             Resource componentType = graph.getPossibleType(component, STR.Component);\r
423             if (componentType == null)\r
424                 continue;\r
425 \r
426             Resource element = graph.getPossibleObject(component, MOD.ComponentToElement);\r
427             if (element == null)\r
428                 continue;\r
429 \r
430             Resource templateElement = graph.getPossibleObject(element, MOD.HasElementSource);\r
431             if (templateElement == null)\r
432                 continue;\r
433 \r
434             Resource templateComponent = graph.getPossibleObject(templateElement, MOD.ElementToComponent);\r
435             if (templateComponent == null)\r
436                 continue;\r
437 \r
438             String nameExpression = graph.getPossibleRelatedValue(templateComponent, L0.HasName, Bindings.STRING);\r
439             if (nameExpression == null)\r
440                 continue;\r
441 \r
442             // NOTE: This assumes that nameEvaluator also makes sure that the\r
443             // evaluated names do not collide with any existing names in the\r
444             // model.\r
445             String evaluatedInstanceName = (String) nameEvaluator.apply(graph, typicalComposite, component, nameExpression);\r
446             if (evaluatedInstanceName != null && !evaluatedInstanceName.equals(nameExpression)) {\r
447                 if (DEBUG)\r
448                     System.out.println("TypicalUtil.applySelectionModuleNames: applied name expression " + nameExpression + " -> " + evaluatedInstanceName);\r
449                 graph.claimLiteral(component, L0.HasName, evaluatedInstanceName, Bindings.STRING);\r
450             }\r
451         }\r
452     }\r
453 \r
454     /**\r
455      * @param graph\r
456      * @param typicalComposite\r
457      * @return f :: ReadGraph -> Resource composite -> Resource component -> String expression -> String name\r
458      * @throws DatabaseException\r
459      */\r
460     public static Function4<ReadGraph, Resource, Resource, String, String> getTypicalNamingFunction(ReadGraph graph, Resource typicalComposite) throws DatabaseException {\r
461         ModelingResources MOD = ModelingResources.getInstance(graph);\r
462         Function4<ReadGraph, Resource, Resource, String, String> nameEvaluator = graph.getPossibleRelatedValue2(typicalComposite, MOD.TypicalComposite_typicalNamingFunction);\r
463         return nameEvaluator;\r
464     }\r
465 \r
466     /**\r
467      * @param processor\r
468      * @param model\r
469      * @return\r
470      * @throws DatabaseException\r
471      */\r
472     public static Collection<Resource> findModelTypicals(RequestProcessor processor, final Resource model) throws DatabaseException {\r
473         return processor.syncRequest(new UniqueRead<Collection<Resource>>() {\r
474             @Override\r
475             public Collection<Resource> perform(ReadGraph graph) throws DatabaseException {\r
476                 ModelingResources MOD = ModelingResources.getInstance(graph);\r
477                 Resource typicalMasterType = graph.getSingleObject(model, MOD.StructuralModel_HasMasterTypicalCompositeType);\r
478                 Instances query = graph.adapt(typicalMasterType, Instances.class);\r
479                 return query.find(graph, model);\r
480             }\r
481         });\r
482     }\r
483 \r
484     /**\r
485      * A utility for synchronous execution of asynchronous procedures.\r
486      * @param runnable the callback that contains asynchronous execution\r
487      * @return the result received from the specified callback\r
488      * @throws DatabaseException\r
489      */\r
490     public static <T> T syncExec(Consumer<Procedure<T>> runnable) throws DatabaseException {\r
491         final AtomicReference<T> ref = new AtomicReference<T>();\r
492         final AtomicReference<Throwable> exc = new AtomicReference<Throwable>();\r
493         final Semaphore sem = new Semaphore(0);\r
494         runnable.accept(new Procedure<T>() {\r
495             @Override\r
496             public void execute(T result) {\r
497                 if (ref.compareAndSet(null, result))\r
498                     sem.release();\r
499             }\r
500             @Override\r
501             public void exception(Throwable t) {\r
502                 if (exc.compareAndSet(null, t))\r
503                     sem.release();\r
504             }\r
505         });\r
506         try {\r
507             sem.acquire();\r
508             Throwable t = exc.get();\r
509             if (t != null) {\r
510                 if (t instanceof DatabaseException)\r
511                     throw (DatabaseException) t;\r
512                 throw new DatabaseException(t);\r
513             } \r
514             return (T) ref.get();\r
515         } catch (InterruptedException ex) {\r
516             throw new DatabaseException(ex);\r
517         }\r
518     }\r
519     \r
520     /*\r
521      * SCL API\r
522      */\r
523     public static void syncTypicalInstance(WriteGraph graph, Resource instance) throws DatabaseException {\r
524         SyncTypicalTemplatesToInstances sync = SyncTypicalTemplatesToInstances.syncSingleInstance(null, instance);\r
525         sync.perform(graph);\r
526     }\r
527     \r
528     /**\r
529      * Creates a new master typical diagram and its corresponding composites.\r
530      * \r
531      * <p>\r
532      * The created typical composite and diagram type are specified by the model\r
533      * using {@link ModelingResources#StructuralModel_HasTypicalCompositeBaseType}\r
534      * and {@link ModelingResources#StructuralModel_HasTypicalDiagramBaseType}.\r
535      * \r
536      * <p>\r
537      * Marks the created master composite with the model-specified master composite\r
538      * type to support searching. The master type is specified by the model using\r
539      * {@link ModelingResources#StructuralModel_HasMasterTypicalCompositeType}.\r
540      * \r
541      * <p>\r
542      * Clones symbol contributions from the sources specified by the model through\r
543      * {@link ModelingResources#StructuralModel_CloneTypicalDiagramSymbolContributionsFrom}\r
544      * .\r
545      * \r
546      * @author Tuukka Lehtonen\r
547      */\r
548 \r
549     public static Resource newMasterTypical(final Resource target) throws DatabaseException {\r
550         \r
551         return Simantics.getSession().syncRequest(new WriteResultRequest<Resource>() {\r
552         \r
553             @Override\r
554             public Resource perform(WriteGraph graph) throws DatabaseException {\r
555                 Layer0 L0 = Layer0.getInstance(graph);\r
556                 Layer0X L0X = Layer0X.getInstance(graph);\r
557                 DiagramResource DIA = DiagramResource.getInstance(graph);\r
558                 ModelingResources MOD = ModelingResources.getInstance(graph);\r
559 \r
560                 Resource indexRoot = graph.sync(new PossibleIndexRoot(target));\r
561                 if (indexRoot == null) {\r
562                     ShowMessage.showInformation("No Model or Shared Library", "Cannot find a containing model or shared library from the input selection. Typical master diagram creation not possible.");\r
563                     return null;\r
564                 }\r
565 \r
566                 Resource compositeBaseType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasTypicalCompositeBaseType);\r
567                 Resource diagramBaseType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasTypicalDiagramBaseType);\r
568                 Resource masterCompositeType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasMasterTypicalCompositeType);\r
569                 Collection<Resource> cloneSymbolContributionsFrom = graph.getObjects(indexRoot, MOD.StructuralModel_CloneTypicalDiagramSymbolContributionsFrom);\r
570                 if (compositeBaseType == null || diagramBaseType == null || masterCompositeType == null) {\r
571                     ShowMessage.showInformation("No Typical Support", "Creation of typical diagrams is not supported for this container.");\r
572                     return null;\r
573                 }\r
574 \r
575                 Resource compositeType = graph.newResource();\r
576                 graph.claim(compositeType, L0.Inherits, compositeBaseType);\r
577                 String compositeTypeName = NameUtils.findFreshName(graph, "TypicalCompositeType", target);\r
578                 graph.claimLiteral(compositeType, L0.HasName, compositeTypeName);\r
579 \r
580                 Resource diagramType = graph.newResource();\r
581                 graph.claim(diagramType, L0.Inherits, diagramBaseType);\r
582                 graph.claimLiteral(diagramType, L0.HasName, "Type");\r
583 \r
584                 String name = NameUtils.findFreshName(graph, "Typical", target, L0.ConsistsOf, "%s%d");\r
585 \r
586                 Resource composite = StructuralUtils.newComponent(graph, target, name + "@1", compositeType);\r
587                 graph.claim(composite, L0.InstanceOf, null, masterCompositeType);\r
588 \r
589                 Resource diagram = graph.newResource();\r
590                 graph.claim(diagram, L0.InstanceOf, null, diagramType);\r
591                 graph.claimLiteral(diagram, L0.HasName, "__DIAGRAM__", Bindings.STRING);\r
592                 graph.claim(diagram, L0.SubrelationOf, null, L0.HasNext);\r
593                 graph.claim(diagram, MOD.DiagramToComposite, composite);\r
594                 Resource diagramInv = graph.newResource();\r
595                 graph.claim(diagramInv, L0.InverseOf, diagram);\r
596                 graph.claim(diagramInv, L0.SubrelationOf, null, L0.HasPrevious);\r
597                 graph.claimLiteral(diagramInv, L0.HasName, "Inverse", Bindings.STRING);\r
598                 graph.claim(diagram, L0.ConsistsOf, diagramInv);\r
599                 graph.claim(diagram, diagram, diagramInv, diagram);\r
600 \r
601                 Resource mapping = graph.newResource();\r
602                 graph.claim(diagram, L0X.HasTrigger, mapping);\r
603                 graph.claim(mapping, L0.InstanceOf, null, MOD.DiagramToCompositeMapping);\r
604 \r
605                 // Make diagram part of a dummy container entity attached to the parent\r
606                 // composite if it's not already part of something.\r
607                 Resource container = graph.newResource();\r
608                 graph.claim(container, L0.InstanceOf, null, DIA.DiagramContainer);\r
609                 graph.addLiteral(container, L0.HasName, L0.NameOf, L0.String, "__CONTAINER__", Bindings.STRING);\r
610 \r
611                 // Compose all created resources into the following hierarchy:\r
612                 // Typical Composite : TypicalCompositeType\r
613                 //     Typical Composite Type : STR.CompositeType\r
614                 //     __CONTAINER__ : DIA.DiagramContainer\r
615                 //         "__DIAGRAM__" : "Type"\r
616                 //             "Type" <T DIA.Diagram\r
617                 graph.claim(diagram, L0.ConsistsOf, diagramType);\r
618                 graph.claim(container, L0.ConsistsOf, diagram);\r
619                 graph.claim(composite, L0.ConsistsOf, container);\r
620                 graph.claim(composite, L0.ConsistsOf, compositeType);\r
621 \r
622                 // Attach the same symbol contributions to the created typical\r
623                 // diagram type as are attached to the model-designated\r
624                 // contribution source diagram type.\r
625                 boolean clonedIndexRootContribution = false;\r
626                 for (Resource symbolContributionSource : cloneSymbolContributionsFrom) {\r
627                     for (Resource contribution : graph.getObjects(symbolContributionSource, DIA.HasSymbolContribution)) {\r
628                         graph.claim(diagramType, DIA.HasSymbolContribution, contribution);\r
629                         clonedIndexRootContribution |= graph.isInstanceOf(contribution, DIA.IndexRootSymbolContribution);\r
630                     }\r
631                 }\r
632 \r
633                 if (!clonedIndexRootContribution) {\r
634                     Resource indexContribution = graph.newResource();\r
635                     graph.claim(indexContribution, L0.InstanceOf, DIA.IndexRootSymbolContribution);\r
636                     graph.claim(diagramType, DIA.HasSymbolContribution, indexContribution);\r
637                 }\r
638 \r
639                 // Add comment to change set.\r
640                 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);\r
641                 graph.addMetadata(cm.add("Created typical master diagram " + composite));\r
642 \r
643                 return composite;\r
644             }\r
645         });\r
646     \r
647     }\r
648 }\r
649 \r