]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/DiagramGraphUtil.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / synchronization / graph / DiagramGraphUtil.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 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.diagram.synchronization.graph;\r
13 \r
14 import gnu.trove.set.hash.THashSet;\r
15 \r
16 import java.awt.geom.AffineTransform;\r
17 import java.lang.reflect.Array;\r
18 import java.util.ArrayList;\r
19 import java.util.Arrays;\r
20 import java.util.Collection;\r
21 import java.util.Collections;\r
22 import java.util.List;\r
23 import java.util.Set;\r
24 \r
25 import org.simantics.Simantics;\r
26 import org.simantics.databoard.Bindings;\r
27 import org.simantics.databoard.binding.Binding;\r
28 import org.simantics.datatypes.literal.Vec2d;\r
29 import org.simantics.db.AsyncReadGraph;\r
30 import org.simantics.db.ReadGraph;\r
31 import org.simantics.db.Resource;\r
32 import org.simantics.db.Statement;\r
33 import org.simantics.db.WriteGraph;\r
34 import org.simantics.db.common.CommentMetadata;\r
35 import org.simantics.db.common.primitiverequest.OrderedSet;\r
36 import org.simantics.db.common.request.IndexRoot;\r
37 import org.simantics.db.common.request.Queries;\r
38 import org.simantics.db.common.utils.NameUtils;\r
39 import org.simantics.db.common.utils.OrderedSetUtils;\r
40 import org.simantics.db.exception.DatabaseException;\r
41 import org.simantics.db.exception.DoesNotContainValueException;\r
42 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
43 import org.simantics.db.exception.NoSingleResultException;\r
44 import org.simantics.db.exception.ServiceException;\r
45 import org.simantics.db.exception.ValidationException;\r
46 import org.simantics.db.layer0.request.PossibleModel;\r
47 import org.simantics.db.procedure.AsyncProcedure;\r
48 import org.simantics.diagram.connection.ConnectionSegmentEnd;\r
49 import org.simantics.diagram.connection.ConnectionVisuals;\r
50 import org.simantics.diagram.content.ConnectionUtil;\r
51 import org.simantics.diagram.content.DesignatedTerminal;\r
52 import org.simantics.diagram.content.ElementContext;\r
53 import org.simantics.diagram.content.ResourceTerminal;\r
54 import org.simantics.diagram.content.TerminalMap;\r
55 import org.simantics.diagram.internal.DebugPolicy;\r
56 import org.simantics.diagram.query.DiagramRequests;\r
57 import org.simantics.diagram.stubs.DiagramResource;\r
58 import org.simantics.diagram.stubs.G2DResource;\r
59 import org.simantics.g2d.connection.EdgeVisualsConfigurer;\r
60 import org.simantics.g2d.diagram.IDiagram;\r
61 import org.simantics.g2d.diagram.handler.DataElementMap;\r
62 import org.simantics.g2d.diagram.handler.Topology.Terminal;\r
63 import org.simantics.g2d.element.ElementHints;\r
64 import org.simantics.g2d.element.IElement;\r
65 import org.simantics.g2d.element.handler.EdgeVisuals;\r
66 import org.simantics.g2d.element.handler.EdgeVisuals.ArrowType;\r
67 import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
68 import org.simantics.g2d.element.handler.FillColor;\r
69 import org.simantics.g2d.element.handler.TerminalTopology;\r
70 import org.simantics.g2d.elementclass.FlagClass;\r
71 import org.simantics.g2d.elementclass.FlagClass.Type;\r
72 import org.simantics.g2d.page.DiagramDesc;\r
73 import org.simantics.g2d.routing.IRouter2;\r
74 import org.simantics.g2d.svg.LineCap;\r
75 import org.simantics.g2d.svg.LineJoin;\r
76 import org.simantics.g2d.utils.Alignment;\r
77 import org.simantics.layer0.Layer0;\r
78 import org.simantics.layer0.utils.binaryPredicates.OrderedSetElementsPredicate;\r
79 import org.simantics.modeling.ModelingResources;\r
80 import org.simantics.scl.commands.Commands;\r
81 import org.simantics.structural.stubs.StructuralResource2;\r
82 import org.simantics.structural2.modelingRules.CPTerminal;\r
83 import org.simantics.structural2.modelingRules.IAttachmentRelationMap;\r
84 import org.simantics.structural2.modelingRules.IConnectionPoint;\r
85 import org.simantics.structural2.modelingRules.IModelingRules;\r
86 import org.simantics.ui.selection.WorkbenchSelectionElement;\r
87 import org.simantics.utils.page.MarginUtils.Margin;\r
88 import org.simantics.utils.page.MarginUtils.Margins;\r
89 import org.simantics.utils.page.PageCentering;\r
90 import org.simantics.utils.page.PageDesc;\r
91 import org.simantics.utils.page.PageOrientation;\r
92 import org.simantics.utils.ui.ErrorLogger;\r
93 \r
94 /**\r
95  * @author Tuukka Lehtonen\r
96  */\r
97 public final class DiagramGraphUtil {\r
98 \r
99     public static double[] validateAffineTransform(Resource resource, double[] matrix) {\r
100         if (matrix != null) {\r
101             if (matrix.length < 4) {\r
102                 ErrorLogger.defaultLogError("resource " + resource + " matrix too small for AffineTransform: " + Arrays.toString(matrix), new Exception("trace"));\r
103                 return null;\r
104             }\r
105 \r
106             // Validate scale/rotation part\r
107             if (DebugPolicy.DEBUG_TRANSFORM_LOAD) {\r
108                 double det = new AffineTransform(matrix).getDeterminant();\r
109                 double detabs = Math.abs(det);\r
110                 if (detabs < DebugPolicy.DETERMINANT_LIMIT_LOW)\r
111                     ErrorLogger.defaultLogWarning("resource " + resource + " transform determinant absolute value is close to zero: " + detabs + "(transform=" + Arrays.toString(matrix) + ")", new Exception("trace"));\r
112                 if (detabs > DebugPolicy.DETERMINANT_LIMIT_HIGH)\r
113                     ErrorLogger.defaultLogWarning("resource " + resource + " transform determinant absolute value is suspiciously large: " + detabs + "(transform=" + Arrays.toString(matrix) + ")", new Exception("trace"));\r
114             }\r
115 \r
116             if (matrix.length > 5) {\r
117                 // Validate translation\r
118                 double xabs = Math.abs(matrix[4]);\r
119                 double yabs = Math.abs(matrix[5]);\r
120                 double limit = DebugPolicy.TRANSLATION_LIMIT_HIGH;\r
121                 boolean largeX = xabs > limit;\r
122                 boolean largeY = yabs > limit;\r
123                 if (largeX || largeY)\r
124                     ErrorLogger.defaultLogWarning("resource " + resource + " transform translation is suspiciously large: " + Arrays.toString(matrix), new Exception("trace"));\r
125                 return matrix;\r
126             }\r
127         }\r
128         return matrix;\r
129     }\r
130 \r
131     public static AffineTransform getAffineTransform(ReadGraph graph, Resource resource) throws DatabaseException {\r
132         G2DResource g2d = G2DResource.getInstance(graph);\r
133         return getAffineTransform(graph, resource, g2d.HasTransform, true);\r
134     }\r
135 \r
136     public static Vec2d getOffset(ReadGraph graph, Resource resource) throws DatabaseException {\r
137         DiagramResource DIA = DiagramResource.getInstance(graph);\r
138         Vec2d offset = graph.getPossibleRelatedValue(resource, DIA.Element_profileMonitorOffset, Vec2d.BINDING);\r
139         if(offset != null) return offset;\r
140         else return new Vec2d(0, 0);\r
141     }\r
142     \r
143     public static boolean getProfileMonitorsHidden(ReadGraph graph, Resource resource) throws DatabaseException {\r
144         DiagramResource DIA = DiagramResource.getInstance(graph);\r
145         Boolean value = graph.getPossibleRelatedValue(resource, DIA.Element_hideProfileMonitors, Bindings.BOOLEAN);\r
146         if(value == null) value = false;\r
147         return value;\r
148     }\r
149 \r
150     public static boolean getProfileMonitorsUp(ReadGraph graph, Resource resource) throws DatabaseException {\r
151         DiagramResource DIA = DiagramResource.getInstance(graph);\r
152         Boolean value = graph.getPossibleRelatedValue(resource, DIA.Element_upProfileMonitors, Bindings.BOOLEAN);\r
153         if(value == null) value = true;\r
154         return value;\r
155     }\r
156 \r
157     public static double getProfileMonitorSpacing(ReadGraph graph, Resource resource) throws DatabaseException {\r
158         DiagramResource DIA = DiagramResource.getInstance(graph);\r
159         Double value = graph.getPossibleRelatedValue(resource, DIA.Element_profileMonitorSpacing, Bindings.DOUBLE);\r
160         if(value == null) value = 0.0;\r
161         return value;\r
162     }\r
163 \r
164     public static AffineTransform getDynamicAffineTransform(ReadGraph graph, Resource runtime, Resource element) throws DatabaseException {\r
165         DiagramResource DIA = DiagramResource.getInstance(graph);\r
166         return getDynamicAffineTransform(graph, runtime, element, DIA.HasDynamicTransform, true);\r
167     }\r
168 \r
169     /**\r
170      * @param graph\r
171      * @param element\r
172      * @return\r
173      * @throws DatabaseException\r
174      */\r
175     public static AffineTransform getWorldTransform(ReadGraph graph, Resource element) throws DatabaseException {\r
176         ModelingResources MOD = ModelingResources.getInstance(graph);\r
177         AffineTransform result = DiagramGraphUtil.getAffineTransform(graph, element);\r
178         while (true) {\r
179             Resource parentComponent = graph.getPossibleObject(element, MOD.HasParentComponent);\r
180             if (parentComponent == null)\r
181                 return result;\r
182             element = graph.getPossibleObject(parentComponent, MOD.ComponentToElement);\r
183             if (element == null)\r
184                 return result;\r
185             AffineTransform tr = DiagramGraphUtil.getAffineTransform(graph, element);\r
186             tr.setToTranslation(tr.getTranslateX(), tr.getTranslateY());\r
187             result.preConcatenate(tr);\r
188         }\r
189     }\r
190 \r
191     /**\r
192      * @param graph\r
193      * @param runtime\r
194      * @param element\r
195      * @return\r
196      * @throws DatabaseException\r
197      */\r
198     public static AffineTransform getDynamicWorldTransform(ReadGraph graph, Resource runtime, Resource element) throws DatabaseException {\r
199         ModelingResources MOD = ModelingResources.getInstance(graph);\r
200         AffineTransform result = DiagramGraphUtil.getDynamicAffineTransform(graph, runtime, element);\r
201         while (true) {\r
202             Resource parentComponent = graph.getPossibleObject(element, MOD.HasParentComponent);\r
203             if (parentComponent == null)\r
204                 return result;\r
205             element = graph.getPossibleObject(parentComponent, MOD.ComponentToElement);\r
206             if (element == null)\r
207                 return result;\r
208             AffineTransform tr = DiagramGraphUtil.getDynamicAffineTransform(graph, runtime, element);\r
209             tr.setToTranslation(tr.getTranslateX(), tr.getTranslateY());\r
210             result.preConcatenate(tr);\r
211         }\r
212     }\r
213 \r
214     /**\r
215      * @param graph\r
216      * @param resource\r
217      * @param relation\r
218      * @param invalidAsIdentity true to return invalid transforms as identity\r
219      *        transforms, <code>false</code> to return <code>null</code>\r
220      * @return\r
221      * @throws DatabaseException\r
222      */\r
223     public static AffineTransform getAffineTransform(ReadGraph graph, Resource resource, Resource relation, boolean invalidAsIdentity) throws DatabaseException {\r
224         double mat[] = getPossibleRelatedDoubleArray(graph, resource, relation);\r
225         mat = validateAffineTransform(resource, mat);\r
226         return mat != null ? new AffineTransform(mat) :\r
227             invalidAsIdentity ? new AffineTransform() : null;\r
228     }\r
229 \r
230     public static AffineTransform getDynamicAffineTransform(ReadGraph graph, Resource runtime, Resource element, Resource relation, boolean invalidAsIdentity) throws DatabaseException {\r
231         double mat[] = graph.getPossibleRelatedValue2(element, relation, new ElementContext(runtime, element), Bindings.DOUBLE_ARRAY);\r
232         mat = validateAffineTransform(element, mat);\r
233         return mat != null ? new AffineTransform(mat) :\r
234             invalidAsIdentity ? new AffineTransform() : null;\r
235     }\r
236     \r
237     public static double[] getPossibleRelatedDoubleArray(ReadGraph graph, Resource resource, Resource relation) throws DatabaseException {\r
238         Resource res = graph.getPossibleObject(resource, relation);\r
239         if (res == null)\r
240             return null;\r
241         return graph.getValue(res, Bindings.getBindingUnchecked(double[].class));\r
242     }\r
243     \r
244     public static AffineTransform getTransform(ReadGraph graph, Resource resource) throws DatabaseException {\r
245         DiagramResource DIA = DiagramResource.getInstance(graph);\r
246 \r
247         double[] matrix = graph.getPossibleRelatedValue(resource, DIA.HasTransform, Bindings.DOUBLE_ARRAY);\r
248         if (matrix == null)\r
249             return new AffineTransform();\r
250         if (matrix.length < 4)\r
251             return new AffineTransform();\r
252         return new AffineTransform(matrix);\r
253     }\r
254 \r
255     public static void setTransform(WriteGraph graph, Resource resource, AffineTransform at) throws DatabaseException {\r
256         double[] matrix = new double[6];\r
257         at.getMatrix(matrix);\r
258         changeTransform(graph, resource, matrix);\r
259     }\r
260     \r
261     public static void setTransform(WriteGraph graph, Resource resource, double[] matrix) throws DatabaseException {\r
262         DiagramResource DIA = DiagramResource.getInstance(graph);\r
263         G2DResource G2D = G2DResource.getInstance(graph);\r
264 \r
265         setRelatedValue(graph, resource, DIA.HasTransform, G2D.Transform, matrix, Bindings.DOUBLE_ARRAY);\r
266     }\r
267     \r
268     public static void changeTransform(WriteGraph graph, Resource resource, AffineTransform at) throws DatabaseException {\r
269         double[] matrix = new double[6];\r
270         at.getMatrix(matrix);\r
271         changeTransform(graph, resource, matrix);\r
272     }\r
273     \r
274     public static void changeTransform(WriteGraph graph, Resource resource, double[] matrix) throws DatabaseException {\r
275         Commands.get(graph, "Simantics/Diagram/setTransform")\r
276                 .execute(graph, graph.syncRequest(new IndexRoot(resource)), resource, matrix);\r
277     }\r
278 \r
279     public static void setRelatedValue(WriteGraph graph, Resource resource, Resource relation, Resource valueType, Object arrayValue, Binding binding) throws DatabaseException {\r
280         Statement stm = graph.getPossibleStatement(resource, relation);\r
281         if (stm == null) {\r
282             addRelatedValue(graph, resource, relation, valueType, arrayValue, binding);\r
283         } else {\r
284             // statement might be asserted, check this before overwriting\r
285             if (!stm.getSubject().equals(resource)) {\r
286                 // Asserted, just add a new related value\r
287                 addRelatedValue(graph, resource, relation, valueType, arrayValue, binding);\r
288             } else {\r
289                 //Object old = graph.getValue2(p);\r
290                 //if (!Arrays.equals(old, arrayValue))\r
291                 graph.claimValue(stm.getObject(), arrayValue, binding);\r
292             }\r
293         }\r
294     }\r
295 \r
296     public static Resource addRelatedValue(WriteGraph graph, Resource resource, Resource relation, Resource valueType, Object arrayValue, Binding binding) throws DatabaseException {\r
297         Resource d = graph.newResource();\r
298         Layer0 b = Layer0.getInstance(graph);\r
299         graph.claim(d, b.InstanceOf, null, valueType);\r
300         graph.claimValue(d, arrayValue);\r
301         graph.claim(resource, relation, d);\r
302         return d;\r
303     }\r
304 \r
305     public static <T> T getPossibleRelatedValue(ReadGraph graph, Resource r, Resource relation, Class<T> valueClass, T defaultValue) throws DatabaseException {\r
306         Resource object = graph.getPossibleObject(r, relation);\r
307         if (object == null)\r
308             return defaultValue;\r
309         T t = graph.getPossibleValue(object, Bindings.getBindingUnchecked(valueClass));\r
310         if (t != null && valueClass.isArray()) {\r
311             if (defaultValue != null) {\r
312                 int defaultValueLength = Array.getLength(defaultValue);\r
313                 int valueLength = Array.getLength(t);\r
314                 if (valueLength < defaultValueLength)\r
315                     return defaultValue;\r
316             }\r
317         }\r
318         return t == null ? defaultValue : t;\r
319     }\r
320 \r
321     public static Resource getConnectionPointOfTerminal(ReadGraph g, Terminal forTerminal) throws DatabaseException {\r
322         if (forTerminal instanceof ResourceTerminal)\r
323             return getConnectionPointOfTerminal(g, ((ResourceTerminal) forTerminal).getResource());\r
324         return null;\r
325     }\r
326 \r
327     public static Resource tryGetBindingRelation(ReadGraph g, Terminal forTerminal) throws DatabaseException {\r
328         if (forTerminal instanceof ResourceTerminal)\r
329             return getPossibleConnectionPointOfTerminal(g, ((ResourceTerminal) forTerminal).getResource());\r
330         return null;\r
331     }\r
332 \r
333     public static LineJoin toLineJoin(G2DResource g2d, Resource lineJoin) {\r
334         if (lineJoin != null) {\r
335             if (lineJoin.equals(g2d.LineJoin_BevelJoin))\r
336                 return LineJoin.bevel;\r
337             if (lineJoin.equals(g2d.LineJoin_RoundJoin))\r
338                 return LineJoin.round;\r
339         }\r
340         return LineJoin.miter;\r
341     }\r
342 \r
343     public static LineCap toLineCap(G2DResource g2d, Resource lineCap) {\r
344         if (lineCap != null) {\r
345             if (lineCap.equals(g2d.LineCap_ButtCap))\r
346                 return LineCap.butt;\r
347             if (lineCap.equals(g2d.LineCap_RoundCap))\r
348                 return LineCap.round;\r
349         }\r
350         return LineCap.square;\r
351     }\r
352 \r
353     public static Resource toLineJoin(G2DResource g2d, LineJoin lineJoin) {\r
354         if (lineJoin != null) {\r
355             if (lineJoin.equals(LineJoin.bevel))\r
356                 return g2d.LineJoin_BevelJoin;\r
357             if (lineJoin.equals(LineJoin.round))\r
358                 return g2d.LineJoin_RoundJoin;\r
359         }\r
360         return g2d.LineJoin_MiterJoin;\r
361     }\r
362 \r
363     public static Resource toLineCap(G2DResource g2d, LineCap lineCap) {\r
364         if (lineCap != null) {\r
365             if (lineCap.equals(LineCap.butt))\r
366                 return g2d.LineCap_ButtCap;\r
367             if (lineCap.equals(LineCap.round))\r
368                 return g2d.LineCap_RoundCap;\r
369         }\r
370         return g2d.LineCap_SquareCap;\r
371     }\r
372 \r
373     public static Alignment toAlignment(Resource align, G2DResource g2d, Alignment defaultValue) {\r
374         if (align == null)\r
375             return defaultValue;\r
376         if (align.equals(g2d.Alignment_Leading))\r
377             return Alignment.LEADING;\r
378         if (align.equals(g2d.Alignment_Trailing))\r
379             return Alignment.TRAILING;\r
380         if (align.equals(g2d.Alignment_Center))\r
381             return Alignment.CENTER;\r
382         return defaultValue;\r
383     }\r
384 \r
385     public static Alignment toVerticalAlignment(Resource align, G2DResource g2d, Alignment defaultValue) {\r
386         if (align == null)\r
387             return defaultValue;\r
388         if (align.equals(g2d.Alignment_Leading))\r
389             return Alignment.LEADING;\r
390         if (align.equals(g2d.Alignment_Trailing))\r
391             return Alignment.TRAILING;\r
392         if (align.equals(g2d.Alignment_Center))\r
393             return Alignment.CENTER;\r
394         if (align.equals(g2d.Alignment_Baseline))\r
395             return Alignment.BASELINE;\r
396         return defaultValue;\r
397     }\r
398 \r
399 \r
400     public static Resource toFlagTypeResource(DiagramResource dr, FlagClass.Type type) {\r
401         switch (type) {\r
402             case In: return dr.FlagType_InputFlag;\r
403             case Out: return dr.FlagType_OutputFlag;\r
404             default: throw new IllegalArgumentException("unsupported flag type: " + type);\r
405         }\r
406     }\r
407 \r
408     public static FlagClass.Type toFlagType(DiagramResource dr, Resource type) {\r
409         return toFlagType(dr, type, Type.In);\r
410     }\r
411 \r
412     public static FlagClass.Type toFlagType(DiagramResource dr, Resource type, FlagClass.Type defaultValue) {\r
413         if (type != null) {\r
414             if (dr.FlagType_InputFlag.equals(type))\r
415                 return Type.In;\r
416             if (dr.FlagType_OutputFlag.equals(type))\r
417                 return Type.Out;\r
418         }\r
419         return defaultValue;\r
420     }\r
421 \r
422     public static void tag(WriteGraph g, Resource object, Resource tag, boolean set) throws DatabaseException {\r
423         if (set)\r
424             g.claim(object, tag, tag, object);\r
425         else\r
426             g.deny(object, tag, tag, object);\r
427     }\r
428 \r
429     /**\r
430      * @param graph\r
431      * @param diagram the diagram from which to look for a page description\r
432      *        property\r
433      * @return if the diagram does not have a page desc definition,\r
434      *         <code>defaultValue</code> is returned\r
435      * @throws DatabaseException\r
436      */\r
437     public static PageDesc getPageDesc(ReadGraph graph, Resource diagram, PageDesc defaultValue) throws DatabaseException {\r
438         DiagramResource dr = DiagramResource.getInstance(graph);\r
439         Resource pd = graph.getPossibleObject(diagram, dr.HasPageDescription);\r
440         if (pd == null)\r
441             return defaultValue;\r
442         return readPageDesc(graph, pd);\r
443     }\r
444 \r
445     /**\r
446      * @param graph\r
447      * @param diagram\r
448      *            the diagram from which to look for a page description property\r
449      * @return PageDesc for the specified diagram\r
450      * @throws DatabaseException\r
451      *             if DIA.HasPageDescription can't be read\r
452      */\r
453     public static PageDesc getPageDesc(ReadGraph graph, Resource diagram) throws DatabaseException {\r
454         DiagramResource dr = DiagramResource.getInstance(graph);\r
455         Resource pd = graph.getSingleObject(diagram, dr.HasPageDescription);\r
456         return readPageDesc(graph, pd);\r
457     }\r
458 \r
459     public static PageDesc readPageDesc(ReadGraph graph, Resource pageDesc) throws DatabaseException {\r
460         Layer0 l0 = Layer0.getInstance(graph);\r
461         DiagramResource dr = DiagramResource.getInstance(graph);\r
462         Resource orientation = graph.getSingleObject(pageDesc, dr.PageDescription_Orientation);\r
463         double[] size = graph.getRelatedValue(pageDesc, dr.PageDescription_Size, Bindings.getBindingUnchecked(double[].class));\r
464         Resource margins = graph.getSingleObject(pageDesc, dr.PageDescription_Margins);\r
465         Margins m = readMargins(graph, margins);\r
466         //PageDesc pd = PageDesc.getDescription(toOrientation(orientation, dr), size[0], size[1]);\r
467         String name = graph.getPossibleRelatedValue(pageDesc, l0.HasName);\r
468         if (name == null)\r
469             name = "";\r
470         PageDesc pd = new PageDesc(name, toOrientation(orientation, dr), PageCentering.TopLeftAtOrigin, size[0], size[1], m);\r
471         return pd;\r
472     }\r
473 \r
474     public static Margins readMargins(ReadGraph graph, Resource margins) throws NoSingleResultException, DoesNotContainValueException, ServiceException {\r
475         DiagramResource dr = DiagramResource.getInstance(graph);\r
476         double t = graph.getRelatedValue(margins, dr.PageDescription_Margins_Top);\r
477         double b = graph.getRelatedValue(margins, dr.PageDescription_Margins_Bottom);\r
478         double l = graph.getRelatedValue(margins, dr.PageDescription_Margins_Left);\r
479         double r = graph.getRelatedValue(margins, dr.PageDescription_Margins_Right);\r
480         Margin mt = new Margin(0, 0, t);\r
481         Margin mb = new Margin(0, 0, b);\r
482         Margin ml = new Margin(0, 0, l);\r
483         Margin mr = new Margin(0, 0, r);\r
484         return new Margins(mt, mb, ml, mr);\r
485     }\r
486 \r
487     public static void setPageDesc(WriteGraph graph, Resource diagram, String pageDescRepr) throws DatabaseException {\r
488         setPageDesc(graph, diagram, PageDesc.fromRepr(pageDescRepr));\r
489     }\r
490     \r
491     public static void setPageDesc(WriteGraph graph, Resource diagram, PageDesc pageDesc) throws DatabaseException {\r
492         Layer0 b = Layer0.getInstance(graph);\r
493         G2DResource g2d = G2DResource.getInstance(graph);\r
494         DiagramResource dr = DiagramResource.getInstance(graph);\r
495         Resource pd = graph.getPossibleObject(diagram, dr.HasPageDescription);\r
496         if(pd != null && graph.isImmutable(pd)) {\r
497                 graph.deny(diagram, dr.HasPageDescription);\r
498                 pd = null;\r
499         }\r
500         if (pd == null) {\r
501             pd = graph.newResource();\r
502             graph.claim(pd, b.InstanceOf, null, dr.PageDescription);\r
503             graph.claim(diagram, dr.HasPageDescription, pd);\r
504         }\r
505         graph.deny(pd, dr.PageDescription_Size);\r
506         Resource pageSize = graph.newResource();\r
507         graph.claim(pageSize, b.InstanceOf, null, g2d.Point2D);\r
508         graph.claimValue(pageSize, new double[] { pageDesc.getWidth(), pageDesc.getHeight() });\r
509         graph.claim(pd, dr.PageDescription_Size, pageSize);\r
510         graph.deny(pd, dr.PageDescription_Orientation);\r
511         graph.claim(pd, dr.PageDescription_Orientation, toOrientationResource(pageDesc.getOrientation(), dr));\r
512         Resource margins = graph.getPossibleObject(pd, dr.PageDescription_Margins);\r
513         if (margins == null) {\r
514             margins = graph.newResource();\r
515             graph.claim(margins, b.InstanceOf, null, dr.Margins);\r
516             graph.claim(pd, dr.PageDescription_Margins, margins);\r
517         }\r
518         setMargins(graph,pageDesc.getMargins(),margins, dr);\r
519         graph.claimLiteral(pd, b.HasName,pageDesc.getText());\r
520     }\r
521 \r
522     private static PageOrientation toOrientation(Resource orientation, DiagramResource dr) {\r
523         if (orientation != null) {\r
524             if (orientation.equals(dr.Orientation_Portrait))\r
525                 return PageOrientation.Portrait;\r
526             if (orientation.equals(dr.Orientation_Landscape))\r
527                 return PageOrientation.Landscape;\r
528         }\r
529         return PageOrientation.Portrait;\r
530     }\r
531 \r
532     public static Resource toOrientationResource(PageOrientation orientation, DiagramResource dr) {\r
533         if (PageOrientation.Portrait.equals(orientation))\r
534             return dr.Orientation_Portrait;\r
535         if (PageOrientation.Landscape.equals(orientation))\r
536             return dr.Orientation_Landscape;\r
537         return dr.Orientation_Portrait;\r
538     }\r
539 \r
540     private static void setMargins(WriteGraph g, Margins margins, Resource marginsR,DiagramResource dr) throws ServiceException, ManyObjectsForFunctionalRelationException {\r
541 \r
542         g.claimLiteral(marginsR, dr.PageDescription_Margins_Top,margins.top.diagramAbsolute);\r
543         g.claimLiteral(marginsR, dr.PageDescription_Margins_Bottom,margins.bottom.diagramAbsolute);\r
544         g.claimLiteral(marginsR, dr.PageDescription_Margins_Left,margins.left.diagramAbsolute);\r
545         g.claimLiteral(marginsR, dr.PageDescription_Margins_Right,margins.right.diagramAbsolute);\r
546 \r
547     }\r
548 \r
549     public static Double getGridSize(ReadGraph graph, Resource diagram, Double defaultValue) throws ManyObjectsForFunctionalRelationException, ServiceException {\r
550         DiagramResource dr = DiagramResource.getInstance(graph);\r
551         Double gridSize = graph.getPossibleRelatedValue(diagram, dr.HasGridSize);\r
552         return gridSize == null ? defaultValue : gridSize;\r
553     }\r
554 \r
555     public static void setGridSize(WriteGraph graph, Resource diagram, double gridSize) throws ManyObjectsForFunctionalRelationException, ServiceException {\r
556         DiagramResource dr = DiagramResource.getInstance(graph);\r
557         graph.claimLiteral(diagram, dr.HasGridSize, gridSize);\r
558     }\r
559 \r
560     public static boolean isPageBordersVisible(ReadGraph graph, Resource diagram) throws DatabaseException {\r
561         DiagramResource dr = DiagramResource.getInstance(graph);\r
562         return graph.hasStatement(diagram, dr.DisplayPageSize);\r
563     }\r
564 \r
565     public static boolean isMarginsVisible(ReadGraph graph, Resource diagram) throws DatabaseException {\r
566         DiagramResource dr = DiagramResource.getInstance(graph);\r
567         return graph.hasStatement(diagram, dr.DisplayMargins);\r
568     }\r
569 \r
570     public static void setPageBordersVisible(WriteGraph graph, Resource diagram, boolean visible) throws DatabaseException {\r
571         DiagramResource dr = DiagramResource.getInstance(graph);\r
572         tag(graph, diagram, dr.DisplayPageSize, visible);\r
573     }\r
574 \r
575     public static void setMarginsVisible(WriteGraph graph, Resource diagram, boolean visible) throws DatabaseException {\r
576         DiagramResource dr = DiagramResource.getInstance(graph);\r
577         tag(graph, diagram, dr.DisplayMargins, visible);\r
578     }\r
579 \r
580     public static void setDiagramDesc(WriteGraph graph, Resource diagram, DiagramDesc desc) throws DatabaseException {\r
581         DiagramGraphUtil.setPageDesc(graph, diagram, desc.getPageDesc());\r
582         DiagramGraphUtil.setGridSize(graph, diagram, desc.getGridSize());\r
583         DiagramGraphUtil.setPageBordersVisible(graph, diagram, desc.isPageBordersVisible());\r
584         DiagramGraphUtil.setMarginsVisible(graph, diagram, desc.isMarginsVisible());\r
585         // Add comment to change set.\r
586         CommentMetadata cm = graph.getMetadata(CommentMetadata.class);\r
587         graph.addMetadata(cm.add("Set diagram description for diagram resource " + diagram));\r
588     }\r
589 \r
590     /**\r
591      * Potentially returns the connection connected to the element with the\r
592      * given connectionRelation.\r
593      */\r
594     public static Resource getRelatedConnection(ReadGraph g, Resource element, Resource connectionRelation) throws DatabaseException {\r
595         StructuralResource2 sr = StructuralResource2.getInstance(g);\r
596         for(Resource connector : g.getObjects(element, connectionRelation))\r
597             for(Resource connection : g.getObjects(connector, sr.Connects))\r
598                 if(!connection.equals(element))\r
599                     return connection;\r
600         return null;\r
601     }\r
602 \r
603     /**\r
604      * Returns the connection type of a potential connection connected to the\r
605      * element with the given connectionRelation.\r
606      */\r
607     public static Resource getRelatedConnectionType(ReadGraph g, Resource element, Resource connectionRelation) throws DatabaseException {\r
608         StructuralResource2 sr = StructuralResource2.getInstance(g);\r
609         for(Resource connector : g.getObjects(element, connectionRelation))\r
610             for(Resource connection : g.getObjects(connector, sr.Connects))\r
611                 if(!connection.equals(element))\r
612                     for(Resource connectionType : g.getObjects(connection, sr.HasConnectionType))\r
613                         return connectionType;\r
614         return null;\r
615     }\r
616 \r
617     /**\r
618      * Returns a flag that is joined to this flag with a ConnectionJoin.\r
619      */\r
620     public static Resource getJoinedFlag(ReadGraph g, Resource flag) throws DatabaseException {\r
621         DiagramResource dr = DiagramResource.getInstance(g);\r
622         for(Resource join : g.getObjects(flag, dr.FlagIsJoinedBy))\r
623             for(Resource otherFlag : g.getObjects(join, dr.JoinsFlag))\r
624                 if(!otherFlag.equals(flag))\r
625                     return otherFlag;\r
626         return null;\r
627     }\r
628 \r
629     public static Resource getConnectionTypeForFlag(ReadGraph g, Resource flag) throws DatabaseException {\r
630         DiagramResource dr = DiagramResource.getInstance(g);\r
631 \r
632         Resource connectionType = getRelatedConnectionType(g, flag, dr.Flag_ConnectionPoint);\r
633         if(connectionType != null)\r
634             return connectionType;\r
635 \r
636         Resource otherFlag = getJoinedFlag(g, flag);\r
637         if(otherFlag == null)\r
638             return null;\r
639 \r
640         return getRelatedConnectionType(g, otherFlag, dr.Flag_ConnectionPoint);\r
641     }\r
642 \r
643     /**\r
644      * Checks if the two specified diagram elements exist on the same diagram.\r
645      */\r
646     public static boolean onSameDiagram(ReadGraph graph, Resource element1, Resource element2) throws DatabaseException {\r
647         return !Collections.disjoint(\r
648                 OrderedSetElementsPredicate.INSTANCE.getSubjects(graph, element1),\r
649                 OrderedSetElementsPredicate.INSTANCE.getSubjects(graph, element2));\r
650     }\r
651 \r
652     /**\r
653      * Checks whether a diagram element has a <code>DIAGRAM.Routing</code> tag\r
654      * that is adaptable to {@link IRouter2}.\r
655      * \r
656      * @param graph\r
657      * @param element\r
658      * @param procedure\r
659      */\r
660     public static void getPossibleRouter(AsyncReadGraph graph, final Resource element, final AsyncProcedure<IRouter2> procedure) {\r
661         DiagramResource dr = graph.getService(DiagramResource.class);\r
662         graph.forPossibleStatement(element, dr.Routing, new AsyncProcedure<Statement>() {\r
663             @Override\r
664             public void exception(AsyncReadGraph graph, Throwable throwable) {\r
665                 procedure.exception(graph, throwable);\r
666             }\r
667             @Override\r
668             public void execute(AsyncReadGraph graph, Statement result) {\r
669                 if (result != null)\r
670                     graph.forPossibleAdapted(result.getPredicate(), IRouter2.class, procedure);\r
671                 else\r
672                     procedure.execute(graph, null);\r
673             }\r
674         });\r
675     }\r
676 \r
677     /**\r
678      * @param graph\r
679      * @param modelingRules\r
680      * @param connection\r
681      * @param diagram\r
682      * @param edge\r
683      * @param firstTerminal\r
684      * @param secondTerminal\r
685      * @throws DatabaseException\r
686      */\r
687     public static void loadConnectionVisuals(ReadGraph graph, IModelingRules modelingRules, Resource connection,\r
688             IDiagram diagram, IElement edge, DesignatedTerminal firstTerminal, DesignatedTerminal secondTerminal)\r
689     throws DatabaseException {\r
690         List<EdgeVisuals> evs = edge.getElementClass().getItemsByClass(EdgeVisuals.class);\r
691         if (evs.isEmpty())\r
692             return;\r
693 \r
694         IAttachmentRelationMap attachmentRelations = modelingRules.getAttachmentRelations(graph, connection);\r
695 \r
696         IConnectionPoint firstCp = ConnectionUtil.toConnectionPoint(graph, firstTerminal);\r
697         IConnectionPoint secondCp = ConnectionUtil.toConnectionPoint(graph, secondTerminal);\r
698 \r
699         Resource firstAttachment = null;\r
700         Resource secondAttachment = null;\r
701 \r
702         if (firstCp instanceof CPTerminal)\r
703             firstAttachment = attachmentRelations.get(graph, (CPTerminal) firstCp);\r
704         if (secondCp instanceof CPTerminal)\r
705             secondAttachment = attachmentRelations.get(graph, (CPTerminal) secondCp);\r
706 \r
707         if (DebugPolicy.DEBUG_CONNECTION_VISUALS_LOAD) {\r
708             System.out.println("first attachment relation : " + NameUtils.getSafeName(graph, firstAttachment));\r
709             System.out.println("second attachment relation : " + NameUtils.getSafeName(graph, secondAttachment));\r
710         }\r
711 \r
712         // 1. Configure edge ends\r
713         loadEdgeEnds(graph, modelingRules, connection, edge, firstAttachment, secondAttachment);\r
714 \r
715         // 2. Configure edge line style\r
716         loadLineStyle(graph, modelingRules, connection, edge);\r
717     }\r
718 \r
719     public static void loadEdgeEnds(ReadGraph graph, IModelingRules modelingRules, Resource connection, IElement edge,\r
720             Resource firstAttachment, Resource secondAttachment) throws DatabaseException {\r
721         EdgeVisualsConfigurer startConfig = (firstAttachment != null) ? graph.syncRequest(Queries.adapt(\r
722                 firstAttachment, EdgeVisualsConfigurer.class, true)) : null;\r
723         EdgeVisualsConfigurer endConfig = (secondAttachment != null) ? graph.syncRequest(Queries.adapt(\r
724                 secondAttachment, EdgeVisualsConfigurer.class, true)) : null;\r
725 \r
726         for (EdgeVisuals ev : edge.getElementClass().getItemsByClass(EdgeVisuals.class)) {\r
727             if (startConfig != null)\r
728                 startConfig.configure(edge, ev, EdgeVisuals.BEGIN);\r
729             else\r
730                 ev.setArrowType(edge, EdgeEnd.Begin, ArrowType.None);\r
731             if (endConfig != null)\r
732                 endConfig.configure(edge, ev, EdgeVisuals.END);\r
733             else\r
734                 ev.setArrowType(edge, EdgeEnd.End, ArrowType.None);\r
735         }\r
736     }\r
737 \r
738     public static void loadLineStyle(ReadGraph graph, IModelingRules modelingRules, Resource connection, IElement edge)\r
739     throws DatabaseException {\r
740         Resource connectionType = modelingRules.getConnectionType(graph, connection);\r
741         if (connectionType != null) {\r
742             loadLineStyleFromConnectionType(graph, modelingRules, connectionType, edge);\r
743         }\r
744     }\r
745 \r
746     public static void loadLineStyleFromConnectionType(ReadGraph graph, IModelingRules modelingRules, Resource connectionType, IElement edge)\r
747     throws DatabaseException {\r
748         edge.setHint(ElementHints.KEY_CONNECTION_TYPE, connectionType);\r
749         if (DebugPolicy.DEBUG_CONNECTION_VISUALS_LOAD)\r
750             System.out.println("Connection type : " + NameUtils.getSafeName(graph, connectionType));\r
751 \r
752         // Load standard visual aspects of the specified edge\r
753         ConnectionVisuals cv = graph.syncRequest(DiagramRequests.getConnectionVisuals(connectionType));\r
754 \r
755         if (cv.color != null) {\r
756             for (FillColor fc : edge.getElementClass().getItemsByClass(FillColor.class)) {\r
757                 fc.setFillColor(edge, cv.toColor());\r
758             }\r
759         }\r
760         for (EdgeVisuals ev : edge.getElementClass().getItemsByClass(EdgeVisuals.class)) {\r
761             if (cv.stroke != null)\r
762                 ev.setStroke(edge, cv.stroke);\r
763             if (cv.strokeType != null)\r
764                 ev.setStrokeType(edge, cv.strokeType);\r
765         }\r
766     }\r
767 \r
768     /**\r
769      * @param graph\r
770      * @param connectionPart\r
771      * @return\r
772      * @throws DatabaseException\r
773      */\r
774     public static ConnectionSegmentEnd resolveConnectionSegmentEnd(ReadGraph graph, Resource connectionPart)\r
775     throws DatabaseException {\r
776         BasicResources br = BasicResources.getInstance(graph);\r
777         if (graph.isInstanceOf(connectionPart, br.DIA.BranchPoint))\r
778             return ConnectionSegmentEnd.BRANCH;\r
779         if (graph.isInstanceOf(connectionPart, br.DIA.Connector))\r
780             return ConnectionSegmentEnd.CONNECTOR;\r
781         return null;\r
782     }\r
783 \r
784     /**\r
785      * @param graph\r
786      * @param diagram\r
787      * @param segmentEnd\r
788      * @param endType\r
789      * @return\r
790      * @throws DatabaseException\r
791      */\r
792     public static DesignatedTerminal findDesignatedTerminal(ReadGraph graph, IDiagram diagram, Resource segmentEnd, ConnectionSegmentEnd endType)\r
793     throws DatabaseException {\r
794         if (DebugPolicy.DEBUG_TERMINAL_SEARCH)\r
795             System.out.println("findDesignatedTerminal: " + NameUtils.getSafeName(graph, segmentEnd) + " : " + endType);\r
796 \r
797         BasicResources br = BasicResources.getInstance(graph);\r
798         DataElementMap dem = diagram.getDiagramClass().getSingleItem(DataElementMap.class);\r
799 \r
800         switch (endType) {\r
801             case CONNECTOR: {\r
802                 List<Terminal> ts = new ArrayList<Terminal>();\r
803                 for (Statement stm : graph.getStatements(segmentEnd, br.STR.Connects)) {\r
804                     // Ignore the Is Connector Of relation that goes to the\r
805                     // owner :Connection\r
806                     if (graph.isSubrelationOf(stm.getPredicate(), br.DIA.IsConnectorOf))\r
807                         continue;\r
808 \r
809                     Resource connectionRelation = graph.getInverse(stm.getPredicate());\r
810                     if (DebugPolicy.DEBUG_TERMINAL_SEARCH)\r
811                         System.out.println("CONNECTION RELATION: " + NameUtils.getSafeName(graph, connectionRelation));\r
812                     Resource elementResource = stm.getObject();\r
813                     if (DebugPolicy.DEBUG_TERMINAL_SEARCH)\r
814                         System.out.println("ELEMENT RESOURCE: " + NameUtils.getSafeName(graph, elementResource));\r
815                     IElement e = dem.getElement(diagram, elementResource);\r
816                     if (e == null) {\r
817                         return null;\r
818 //                        throw new ValidationException("connector "\r
819 //                                + NameUtils.getSafeName(graph, segmentEnd)\r
820 //                                + " is connected to an entity that has not (yet) been loaded as an IElement: "\r
821 //                                + NameUtils.getSafeName(graph, elementResource));\r
822                     }\r
823 \r
824                     TerminalTopology tt = e.getElementClass().getSingleItem(TerminalTopology.class);\r
825                     ts.clear();\r
826                     tt.getTerminals(e, ts);\r
827                     for (Terminal t : ts) {\r
828                         if (t instanceof ResourceTerminal) {\r
829                             ResourceTerminal rt = (ResourceTerminal) t;\r
830                             Resource binds = DiagramGraphUtil.getConnectionPointOfTerminal(graph, rt.getResource());\r
831                             if (DebugPolicy.DEBUG_TERMINAL_SEARCH) {\r
832                                 System.out.println("connection relation: "\r
833                                         + NameUtils.getSafeName(graph, connectionRelation) + " " + connectionRelation.getResourceId());\r
834                                 System.out.println("  terminal: " + NameUtils.getSafeName(graph, rt.getResource()) + " " + rt.getResource().getResourceId());\r
835                                 System.out.println("  binds:    " + NameUtils.getSafeName(graph, binds) + " " + binds.getResourceId());\r
836                             }\r
837                             if (graph.isSubrelationOf(connectionRelation, binds)) {\r
838                                 return new DesignatedTerminal(e, t);\r
839                             }\r
840                         }\r
841                     }\r
842 \r
843                     throw new ValidationException("connector "\r
844                             + NameUtils.getSafeName(graph, segmentEnd)\r
845                             + " is connected using a relation that is not its own: "\r
846                             + NameUtils.getSafeName(graph, connectionRelation));\r
847                 }\r
848                 // throw new\r
849                 // ValidationException("connector " +\r
850                 // NameUtils.getSafeName(g, segmentEnd) +\r
851                 // " is not connected to anything");\r
852                 return null;\r
853             }\r
854             case BRANCH: {\r
855                 List<Terminal> ts = new ArrayList<Terminal>();\r
856                 IElement e = dem.getElement(diagram, segmentEnd);\r
857                 if (e == null) {\r
858 //                    throw new ValidationException("branch point "\r
859 //                            + NameUtils.getSafeName(graph, segmentEnd)\r
860 //                            + " has not (yet) been loaded as an IElement");\r
861                     return null;\r
862                 }\r
863 \r
864                 TerminalTopology tt = e.getElementClass().getSingleItem(TerminalTopology.class);\r
865                 tt.getTerminals(e, ts);\r
866                 if (ts.size() != 1)\r
867                     throw new IllegalStateException("branch point element has " + ts.size()\r
868                             + " terminals, expected 1");\r
869                 return new DesignatedTerminal(e, ts.get(0));\r
870             }\r
871             default:\r
872                 throw new IllegalArgumentException("unexpected connection segment end: " + endType);\r
873         }\r
874     }\r
875 \r
876     /**\r
877      * @param graph\r
878      * @param diagram\r
879      * @param terminalStm the statement that goes from the connection\r
880      *        connector to the node with inverse relation of the terminal\r
881      *        relation.\r
882      * @return\r
883      * @throws DatabaseException\r
884      */\r
885     public static DesignatedTerminal getDesignatedTerminalForConnector(ReadGraph graph, IDiagram diagram, Resource elementResource, Resource terminalRelation, Resource connector)\r
886     throws DatabaseException {\r
887         if (DebugPolicy.DEBUG_TERMINAL_SEARCH)\r
888             System.out.println("getDesignatedTerminalForConnector: ("\r
889                     + NameUtils.getSafeName(graph, elementResource) + ", "\r
890                     + NameUtils.getSafeName(graph, terminalRelation) + ", "\r
891                     + NameUtils.getSafeName(graph, connector) + ")"\r
892                     );\r
893 \r
894         DataElementMap dem = diagram.getDiagramClass().getSingleItem(DataElementMap.class);\r
895         IElement e = dem.getElement(diagram, elementResource);\r
896         if (e == null)\r
897             return null;\r
898 \r
899         TerminalTopology tt = e.getElementClass().getSingleItem(TerminalTopology.class);\r
900         List<Terminal> ts = new ArrayList<Terminal>();\r
901         tt.getTerminals(e, ts);\r
902         for (Terminal t : ts) {\r
903             if (t instanceof ResourceTerminal) {\r
904                 ResourceTerminal rt = (ResourceTerminal) t;\r
905                 Resource binds = DiagramGraphUtil.getConnectionPointOfTerminal(graph, rt.getResource());\r
906                 if (DebugPolicy.DEBUG_TERMINAL_SEARCH) {\r
907                     System.out.println("connection relation: "\r
908                             + NameUtils.getSafeName(graph, terminalRelation, true));\r
909                     System.out.println("  terminal: " + NameUtils.getSafeName(graph, rt.getResource(), true));\r
910                     System.out.println("  binds:    " + NameUtils.getSafeName(graph, binds, true));\r
911                 }\r
912                 if (graph.isSubrelationOf(terminalRelation, binds)) {\r
913                     return new DesignatedTerminal(e, t);\r
914                 }\r
915             }\r
916         }\r
917 \r
918         throw new ValidationException("terminal connection statement ("\r
919                 + NameUtils.getSafeName(graph, elementResource) + ", "\r
920                 + NameUtils.getSafeName(graph, terminalRelation) + ", "\r
921                 + NameUtils.getSafeName(graph, connector) + ")"\r
922                 + " is using using a terminal relation that is not its own: "\r
923                 + NameUtils.getSafeName(graph, terminalRelation));\r
924     }\r
925 \r
926     /**\r
927      * @param graph\r
928      * @return\r
929      * @throws DatabaseException\r
930      */\r
931     public static TerminalMap getElementTerminals(ReadGraph graph, Resource element)\r
932     throws DatabaseException {\r
933         DiagramResource DIA = DiagramResource.getInstance(graph);\r
934         Resource elementType = graph.getPossibleType(element, DIA.Element);\r
935         return elementType != null ? getElementTypeTerminals(graph, elementType) : TerminalMap.EMPTY;\r
936     }\r
937 \r
938     private static final boolean DEBUG_GET_ELEMENT_TYPE_TERMINALS = false;\r
939 \r
940     /**\r
941      * @param graph\r
942      * @param elementType\r
943      * @return\r
944      * @throws DatabaseException\r
945      */\r
946     public static TerminalMap getElementTypeTerminals(ReadGraph graph, Resource elementType) throws DatabaseException {\r
947         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
948         DiagramResource DIA = DiagramResource.getInstance(graph);\r
949         if (DEBUG_GET_ELEMENT_TYPE_TERMINALS)\r
950             System.out.println("getElementTypeTerminals: " + NameUtils.getSafeName(graph, elementType));\r
951         Resource definedBy = graph.getSingleObject(elementType, STR.IsDefinedBy);\r
952         Collection<Resource> parts = OrderedSetUtils.toList(graph, definedBy);\r
953         if (DEBUG_GET_ELEMENT_TYPE_TERMINALS)\r
954             System.out.println("\tdefining part count: " + parts.size());\r
955         TerminalMap result = null;\r
956         for (Resource part : parts) {\r
957             if (DEBUG_GET_ELEMENT_TYPE_TERMINALS)\r
958                 System.out.println("\t\tpart: " + NameUtils.getSafeName(graph, part));\r
959             if (graph.isInstanceOf(part, DIA.Terminal)) {\r
960                 Resource binds = DiagramGraphUtil.getConnectionPointOfTerminal(graph, part);\r
961                 if (result == null)\r
962                     result = new TerminalMap(parts.size());\r
963                 if (DEBUG_GET_ELEMENT_TYPE_TERMINALS)\r
964                     System.out.println("\t\t\tFOUND TERMINAL <-> BINDING RELATION: " + NameUtils.getSafeName(graph, part) + " <-> " + NameUtils.getSafeName(graph, binds));\r
965                 result.put(part, binds);\r
966             }\r
967         }\r
968         return result != null ? result : TerminalMap.EMPTY;\r
969     }\r
970 \r
971     /**\r
972      * Get the value of a specified on/off diagram preference setting (=tag)\r
973      * where the tag may be stored in:\r
974      * <ol>\r
975      * <li>The diagram itself</li>\r
976      * <li>The model</li>\r
977      * <li>The project</li>\r
978      * </ol>\r
979      * \r
980      * @param graph database access\r
981      * @param diagram the diagram to look for the tag in\r
982      * @param preference the tag relation of the boolean preference to check for\r
983      * @return value of the preference\r
984      * @throws DatabaseException\r
985      */\r
986     public static boolean getDiagramTagPreference(ReadGraph graph, Resource diagram, Resource preference) throws DatabaseException {\r
987         boolean result = graph.hasStatement(diagram, preference);\r
988         if (!result) {\r
989             Resource model = graph.sync(new PossibleModel(diagram));\r
990             if (model != null)\r
991                 result = graph.hasStatement(model, preference);\r
992             if (!result)\r
993                 result = graph.hasStatement(Simantics.getProjectResource(), preference);\r
994         }\r
995         return result;\r
996     }\r
997 \r
998     public static void rotateConnection(WriteGraph graph, Resource r, \r
999             double cx, double cy, boolean clockwise) throws DatabaseException {\r
1000         DiagramResource DIA = DiagramResource.getInstance(graph);\r
1001         for(Resource node : graph.getObjects(r, DIA.HasInteriorRouteNode))\r
1002             if(graph.isInstanceOf(node, DIA.RouteLine)) {\r
1003                 boolean isHorizontal = (Boolean)graph.getRelatedValue(node, DIA.IsHorizontal);\r
1004                 double position = (Double)graph.getRelatedValue(node, DIA.HasPosition);\r
1005                 \r
1006                 if(isHorizontal) {\r
1007                     position -= cy;\r
1008                     if(clockwise)\r
1009                         position = -position;\r
1010                     position += cx;\r
1011                 }\r
1012                 else {\r
1013                     position -= cx;\r
1014                     if(!clockwise)\r
1015                         position = -position;\r
1016                     position += cy;\r
1017                 }\r
1018                 isHorizontal = !isHorizontal;                \r
1019                 \r
1020                 graph.claimLiteral(node, DIA.IsHorizontal, isHorizontal);\r
1021                 graph.claimLiteral(node, DIA.HasPosition, position);\r
1022             }\r
1023     }\r
1024 \r
1025     public static void flipConnection(WriteGraph graph, Resource r,\r
1026             boolean xAxis, double c) throws DatabaseException {\r
1027         DiagramResource DIA = DiagramResource.getInstance(graph);\r
1028         for(Resource node : graph.getObjects(r, DIA.HasInteriorRouteNode))\r
1029             if(graph.isInstanceOf(node, DIA.RouteLine)) {\r
1030                 boolean isHorizontal = (Boolean)graph.getRelatedValue(node, DIA.IsHorizontal);\r
1031 \r
1032                 if(isHorizontal == xAxis) {\r
1033                     double position = (Double)graph.getRelatedValue(node, DIA.HasPosition);\r
1034                     position = 2*c-position;\r
1035                     graph.claimLiteral(node, DIA.HasPosition, position);\r
1036                 }\r
1037             }\r
1038     }\r
1039     \r
1040     /*public static void addConnectionPoint(WriteGraph g, Resource symbol, Resource terminal, \r
1041             Resource diagramConnectionRelation) throws DatabaseException {\r
1042         Layer0 L0 = Layer0.getInstance(g);\r
1043         StructuralResource2 STR = StructuralResource2.getInstance(g);\r
1044         DiagramResource DIA = DiagramResource.getInstance(g);\r
1045         \r
1046         Resource variable = g.newResource();\r
1047         g.claim(variable, L0.InstanceOf, null, STR.ConnectionVariable);\r
1048         g.claim(terminal, DIA.HasConnectionVariable, variable);\r
1049         g.claim(variable, STR.Binds, diagramConnectionRelation);\r
1050         g.claim(variable, STR.IsParameterOf, symbol);\r
1051     }\r
1052     \r
1053 \r
1054     public static Resource getConnectionPointOfTerminal(ReadGraph g, Resource forTerminal) throws DatabaseException {\r
1055         return g.getSingleObject(\r
1056                 g.getSingleObject(forTerminal, DiagramResource.getInstance(g).HasConnectionVariable),\r
1057                 StructuralResource2.getInstance(g).Binds);\r
1058     }\r
1059 \r
1060     public static Resource getPossibleConnectionPointOfTerminal(ReadGraph g, Resource forTerminal) throws DatabaseException {\r
1061         Resource connectionVariable = g.getPossibleObject(forTerminal, DiagramResource.getInstance(g).HasConnectionVariable);\r
1062         return (connectionVariable == null) ? null : g.getPossibleObject(connectionVariable, StructuralResource2.getInstance(g).Binds);\r
1063     }*/\r
1064     \r
1065     public static void addConnectionPoint(WriteGraph g, Resource symbol, Resource terminal, \r
1066             Resource diagramConnectionRelation) throws DatabaseException {\r
1067         Layer0 L0 = Layer0.getInstance(g);\r
1068         DiagramResource DIA = DiagramResource.getInstance(g);\r
1069         \r
1070         g.claim(terminal, DIA.HasConnectionPoint, diagramConnectionRelation);\r
1071         g.claim(diagramConnectionRelation, L0.HasDomain, symbol);\r
1072     }\r
1073     \r
1074 \r
1075     public static Resource getConnectionPointOfTerminal(ReadGraph g, Resource forTerminal) throws DatabaseException {\r
1076         return g.getSingleObject(forTerminal, DiagramResource.getInstance(g).HasConnectionPoint);\r
1077     }\r
1078 \r
1079     public static Resource getPossibleConnectionPointOfTerminal(ReadGraph g, Resource forTerminal) throws DatabaseException {\r
1080         return g.getPossibleObject(forTerminal, DiagramResource.getInstance(g).HasConnectionPoint);\r
1081     }\r
1082 \r
1083     public static Collection<Resource> getTerminals(ReadGraph g, Resource symbol) throws DatabaseException {\r
1084 //        Layer0 L0 = Layer0.getInstance(g);\r
1085         StructuralResource2 STR = StructuralResource2.getInstance(g);\r
1086         DiagramResource DIA = DiagramResource.getInstance(g);\r
1087         List<Resource> terminals = null;\r
1088         for (Resource definedBy : g.getObjects(symbol, STR.IsDefinedBy)) {\r
1089             Collection<Resource> elements = g.syncRequest( new OrderedSet(definedBy) );\r
1090             if (terminals == null)\r
1091                 terminals = new ArrayList<Resource>( elements.size() );\r
1092             for (Resource element : elements)\r
1093                 if (g.isInstanceOf(element, DIA.Terminal))\r
1094                     terminals.add(element);\r
1095         }\r
1096 //        Collection<Resource> definedBy = g.getObjects(symbol, STR.IsDefinedBy);\r
1097 //        if (!definedBy.isEmpty()) {\r
1098 //            Collection<Resource> relations = g.getObjects(symbol, L0.DomainOf);\r
1099 //            terminals = new ArrayList<Resource>(relations.size());\r
1100 //            for(Resource relation : relations) {\r
1101 //                for (Resource element : g.getObjects(relation, DIA.HasConnectionPoint_Inverse)) {\r
1102 //                    Collection<Resource> owners = OrderedSetUtils.getOwnerLists(g, element, DIA.Diagram);\r
1103 //                    if (!Collections.disjoint(definedBy, owners))\r
1104 //                        terminals.add(element);\r
1105 //                }\r
1106 //            }\r
1107 //        }\r
1108         return terminals == null ? Collections.<Resource>emptyList() : terminals;\r
1109     }\r
1110         \r
1111     /**\r
1112      * Determines the connection type of the given diagram connection. Uses the modeling rules\r
1113      * specified in the diagram the connection belongs to.\r
1114      */\r
1115         public static Resource determineConnectionType(ReadGraph graph, Resource diagramConnection) throws DatabaseException {\r
1116                 Layer0 L0 = Layer0.getInstance(graph);\r
1117                 Resource diagram = graph.getPossibleObject(diagramConnection, L0.PartOf);\r
1118                 if (diagram == null)\r
1119                         // Invalid diagram connection resource, not a part of any diagram.\r
1120                         return null;\r
1121                 IModelingRules modelingRules = graph.syncRequest(DiagramRequests.getModelingRules(diagram, null));\r
1122                 if (modelingRules == null)\r
1123                         return null;\r
1124                 return determineConnectionType(graph, diagramConnection, modelingRules);\r
1125         }\r
1126 \r
1127         /**\r
1128      * Determines the connection type of the given diagram connection assuming the given modeling rules.\r
1129      */\r
1130         public static Resource determineConnectionType(ReadGraph graph, Resource diagramConnection, IModelingRules modelingRules) throws DatabaseException {\r
1131 \r
1132                 Set<IConnectionPoint> cps = new THashSet<IConnectionPoint>();\r
1133                 DiagramRequests.expandConnections(graph, diagramConnection, new THashSet<Resource>(), cps);\r
1134                 return modelingRules.computeConnectionType(graph, cps);\r
1135                 \r
1136         }\r
1137         \r
1138         public static void defaultSymbolDropHandler(WriteGraph graph, List<WorkbenchSelectionElement> drop) throws DatabaseException {\r
1139                 System.err.println("dropped " + drop);\r
1140         }\r
1141     \r
1142 }\r