--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.diagram.synchronization.graph;\r
+\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+import java.awt.geom.AffineTransform;\r
+import java.lang.reflect.Array;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.simantics.Simantics;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.datatypes.literal.Vec2d;\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.CommentMetadata;\r
+import org.simantics.db.common.primitiverequest.OrderedSet;\r
+import org.simantics.db.common.request.IndexRoot;\r
+import org.simantics.db.common.request.Queries;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.DoesNotContainValueException;\r
+import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
+import org.simantics.db.exception.NoSingleResultException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.db.layer0.request.PossibleModel;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.diagram.connection.ConnectionSegmentEnd;\r
+import org.simantics.diagram.connection.ConnectionVisuals;\r
+import org.simantics.diagram.content.ConnectionUtil;\r
+import org.simantics.diagram.content.DesignatedTerminal;\r
+import org.simantics.diagram.content.ElementContext;\r
+import org.simantics.diagram.content.ResourceTerminal;\r
+import org.simantics.diagram.content.TerminalMap;\r
+import org.simantics.diagram.internal.DebugPolicy;\r
+import org.simantics.diagram.query.DiagramRequests;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.stubs.G2DResource;\r
+import org.simantics.g2d.connection.EdgeVisualsConfigurer;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.DataElementMap;\r
+import org.simantics.g2d.diagram.handler.Topology.Terminal;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.EdgeVisuals;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.ArrowType;\r
+import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;\r
+import org.simantics.g2d.element.handler.FillColor;\r
+import org.simantics.g2d.element.handler.TerminalTopology;\r
+import org.simantics.g2d.elementclass.FlagClass;\r
+import org.simantics.g2d.elementclass.FlagClass.Type;\r
+import org.simantics.g2d.page.DiagramDesc;\r
+import org.simantics.g2d.routing.IRouter2;\r
+import org.simantics.g2d.svg.LineCap;\r
+import org.simantics.g2d.svg.LineJoin;\r
+import org.simantics.g2d.utils.Alignment;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.binaryPredicates.OrderedSetElementsPredicate;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.scl.commands.Commands;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.structural2.modelingRules.CPTerminal;\r
+import org.simantics.structural2.modelingRules.IAttachmentRelationMap;\r
+import org.simantics.structural2.modelingRules.IConnectionPoint;\r
+import org.simantics.structural2.modelingRules.IModelingRules;\r
+import org.simantics.ui.selection.WorkbenchSelectionElement;\r
+import org.simantics.utils.page.MarginUtils.Margin;\r
+import org.simantics.utils.page.MarginUtils.Margins;\r
+import org.simantics.utils.page.PageCentering;\r
+import org.simantics.utils.page.PageDesc;\r
+import org.simantics.utils.page.PageOrientation;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public final class DiagramGraphUtil {\r
+\r
+ public static double[] validateAffineTransform(Resource resource, double[] matrix) {\r
+ if (matrix != null) {\r
+ if (matrix.length < 4) {\r
+ ErrorLogger.defaultLogError("resource " + resource + " matrix too small for AffineTransform: " + Arrays.toString(matrix), new Exception("trace"));\r
+ return null;\r
+ }\r
+\r
+ // Validate scale/rotation part\r
+ if (DebugPolicy.DEBUG_TRANSFORM_LOAD) {\r
+ double det = new AffineTransform(matrix).getDeterminant();\r
+ double detabs = Math.abs(det);\r
+ if (detabs < DebugPolicy.DETERMINANT_LIMIT_LOW)\r
+ ErrorLogger.defaultLogWarning("resource " + resource + " transform determinant absolute value is close to zero: " + detabs + "(transform=" + Arrays.toString(matrix) + ")", new Exception("trace"));\r
+ if (detabs > DebugPolicy.DETERMINANT_LIMIT_HIGH)\r
+ ErrorLogger.defaultLogWarning("resource " + resource + " transform determinant absolute value is suspiciously large: " + detabs + "(transform=" + Arrays.toString(matrix) + ")", new Exception("trace"));\r
+ }\r
+\r
+ if (matrix.length > 5) {\r
+ // Validate translation\r
+ double xabs = Math.abs(matrix[4]);\r
+ double yabs = Math.abs(matrix[5]);\r
+ double limit = DebugPolicy.TRANSLATION_LIMIT_HIGH;\r
+ boolean largeX = xabs > limit;\r
+ boolean largeY = yabs > limit;\r
+ if (largeX || largeY)\r
+ ErrorLogger.defaultLogWarning("resource " + resource + " transform translation is suspiciously large: " + Arrays.toString(matrix), new Exception("trace"));\r
+ return matrix;\r
+ }\r
+ }\r
+ return matrix;\r
+ }\r
+\r
+ public static AffineTransform getAffineTransform(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ G2DResource g2d = G2DResource.getInstance(graph);\r
+ return getAffineTransform(graph, resource, g2d.HasTransform, true);\r
+ }\r
+\r
+ public static Vec2d getOffset(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ Vec2d offset = graph.getPossibleRelatedValue(resource, DIA.Element_profileMonitorOffset, Vec2d.BINDING);\r
+ if(offset != null) return offset;\r
+ else return new Vec2d(0, 0);\r
+ }\r
+ \r
+ public static boolean getProfileMonitorsHidden(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ Boolean value = graph.getPossibleRelatedValue(resource, DIA.Element_hideProfileMonitors, Bindings.BOOLEAN);\r
+ if(value == null) value = false;\r
+ return value;\r
+ }\r
+\r
+ public static boolean getProfileMonitorsUp(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ Boolean value = graph.getPossibleRelatedValue(resource, DIA.Element_upProfileMonitors, Bindings.BOOLEAN);\r
+ if(value == null) value = true;\r
+ return value;\r
+ }\r
+\r
+ public static double getProfileMonitorSpacing(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ Double value = graph.getPossibleRelatedValue(resource, DIA.Element_profileMonitorSpacing, Bindings.DOUBLE);\r
+ if(value == null) value = 0.0;\r
+ return value;\r
+ }\r
+\r
+ public static AffineTransform getDynamicAffineTransform(ReadGraph graph, Resource runtime, Resource element) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ return getDynamicAffineTransform(graph, runtime, element, DIA.HasDynamicTransform, true);\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param element\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public static AffineTransform getWorldTransform(ReadGraph graph, Resource element) throws DatabaseException {\r
+ ModelingResources MOD = ModelingResources.getInstance(graph);\r
+ AffineTransform result = DiagramGraphUtil.getAffineTransform(graph, element);\r
+ while (true) {\r
+ Resource parentComponent = graph.getPossibleObject(element, MOD.HasParentComponent);\r
+ if (parentComponent == null)\r
+ return result;\r
+ element = graph.getPossibleObject(parentComponent, MOD.ComponentToElement);\r
+ if (element == null)\r
+ return result;\r
+ AffineTransform tr = DiagramGraphUtil.getAffineTransform(graph, element);\r
+ tr.setToTranslation(tr.getTranslateX(), tr.getTranslateY());\r
+ result.preConcatenate(tr);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param runtime\r
+ * @param element\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public static AffineTransform getDynamicWorldTransform(ReadGraph graph, Resource runtime, Resource element) throws DatabaseException {\r
+ ModelingResources MOD = ModelingResources.getInstance(graph);\r
+ AffineTransform result = DiagramGraphUtil.getDynamicAffineTransform(graph, runtime, element);\r
+ while (true) {\r
+ Resource parentComponent = graph.getPossibleObject(element, MOD.HasParentComponent);\r
+ if (parentComponent == null)\r
+ return result;\r
+ element = graph.getPossibleObject(parentComponent, MOD.ComponentToElement);\r
+ if (element == null)\r
+ return result;\r
+ AffineTransform tr = DiagramGraphUtil.getDynamicAffineTransform(graph, runtime, element);\r
+ tr.setToTranslation(tr.getTranslateX(), tr.getTranslateY());\r
+ result.preConcatenate(tr);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param resource\r
+ * @param relation\r
+ * @param invalidAsIdentity true to return invalid transforms as identity\r
+ * transforms, <code>false</code> to return <code>null</code>\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public static AffineTransform getAffineTransform(ReadGraph graph, Resource resource, Resource relation, boolean invalidAsIdentity) throws DatabaseException {\r
+ double mat[] = getPossibleRelatedDoubleArray(graph, resource, relation);\r
+ mat = validateAffineTransform(resource, mat);\r
+ return mat != null ? new AffineTransform(mat) :\r
+ invalidAsIdentity ? new AffineTransform() : null;\r
+ }\r
+\r
+ public static AffineTransform getDynamicAffineTransform(ReadGraph graph, Resource runtime, Resource element, Resource relation, boolean invalidAsIdentity) throws DatabaseException {\r
+ double mat[] = graph.getPossibleRelatedValue2(element, relation, new ElementContext(runtime, element), Bindings.DOUBLE_ARRAY);\r
+ mat = validateAffineTransform(element, mat);\r
+ return mat != null ? new AffineTransform(mat) :\r
+ invalidAsIdentity ? new AffineTransform() : null;\r
+ }\r
+ \r
+ public static double[] getPossibleRelatedDoubleArray(ReadGraph graph, Resource resource, Resource relation) throws DatabaseException {\r
+ Resource res = graph.getPossibleObject(resource, relation);\r
+ if (res == null)\r
+ return null;\r
+ return graph.getValue(res, Bindings.getBindingUnchecked(double[].class));\r
+ }\r
+ \r
+ public static AffineTransform getTransform(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+\r
+ double[] matrix = graph.getPossibleRelatedValue(resource, DIA.HasTransform, Bindings.DOUBLE_ARRAY);\r
+ if (matrix == null)\r
+ return new AffineTransform();\r
+ if (matrix.length < 4)\r
+ return new AffineTransform();\r
+ return new AffineTransform(matrix);\r
+ }\r
+\r
+ public static void setTransform(WriteGraph graph, Resource resource, AffineTransform at) throws DatabaseException {\r
+ double[] matrix = new double[6];\r
+ at.getMatrix(matrix);\r
+ changeTransform(graph, resource, matrix);\r
+ }\r
+ \r
+ public static void setTransform(WriteGraph graph, Resource resource, double[] matrix) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ G2DResource G2D = G2DResource.getInstance(graph);\r
+\r
+ setRelatedValue(graph, resource, DIA.HasTransform, G2D.Transform, matrix, Bindings.DOUBLE_ARRAY);\r
+ }\r
+ \r
+ public static void changeTransform(WriteGraph graph, Resource resource, AffineTransform at) throws DatabaseException {\r
+ double[] matrix = new double[6];\r
+ at.getMatrix(matrix);\r
+ changeTransform(graph, resource, matrix);\r
+ }\r
+ \r
+ public static void changeTransform(WriteGraph graph, Resource resource, double[] matrix) throws DatabaseException {\r
+ Commands.get(graph, "Simantics/Diagram/setTransform")\r
+ .execute(graph, graph.syncRequest(new IndexRoot(resource)), resource, matrix);\r
+ }\r
+\r
+ public static void setRelatedValue(WriteGraph graph, Resource resource, Resource relation, Resource valueType, Object arrayValue, Binding binding) throws DatabaseException {\r
+ Statement stm = graph.getPossibleStatement(resource, relation);\r
+ if (stm == null) {\r
+ addRelatedValue(graph, resource, relation, valueType, arrayValue, binding);\r
+ } else {\r
+ // statement might be asserted, check this before overwriting\r
+ if (!stm.getSubject().equals(resource)) {\r
+ // Asserted, just add a new related value\r
+ addRelatedValue(graph, resource, relation, valueType, arrayValue, binding);\r
+ } else {\r
+ //Object old = graph.getValue2(p);\r
+ //if (!Arrays.equals(old, arrayValue))\r
+ graph.claimValue(stm.getObject(), arrayValue, binding);\r
+ }\r
+ }\r
+ }\r
+\r
+ public static Resource addRelatedValue(WriteGraph graph, Resource resource, Resource relation, Resource valueType, Object arrayValue, Binding binding) throws DatabaseException {\r
+ Resource d = graph.newResource();\r
+ Layer0 b = Layer0.getInstance(graph);\r
+ graph.claim(d, b.InstanceOf, null, valueType);\r
+ graph.claimValue(d, arrayValue);\r
+ graph.claim(resource, relation, d);\r
+ return d;\r
+ }\r
+\r
+ public static <T> T getPossibleRelatedValue(ReadGraph graph, Resource r, Resource relation, Class<T> valueClass, T defaultValue) throws DatabaseException {\r
+ Resource object = graph.getPossibleObject(r, relation);\r
+ if (object == null)\r
+ return defaultValue;\r
+ T t = graph.getPossibleValue(object, Bindings.getBindingUnchecked(valueClass));\r
+ if (t != null && valueClass.isArray()) {\r
+ if (defaultValue != null) {\r
+ int defaultValueLength = Array.getLength(defaultValue);\r
+ int valueLength = Array.getLength(t);\r
+ if (valueLength < defaultValueLength)\r
+ return defaultValue;\r
+ }\r
+ }\r
+ return t == null ? defaultValue : t;\r
+ }\r
+\r
+ public static Resource getConnectionPointOfTerminal(ReadGraph g, Terminal forTerminal) throws DatabaseException {\r
+ if (forTerminal instanceof ResourceTerminal)\r
+ return getConnectionPointOfTerminal(g, ((ResourceTerminal) forTerminal).getResource());\r
+ return null;\r
+ }\r
+\r
+ public static Resource tryGetBindingRelation(ReadGraph g, Terminal forTerminal) throws DatabaseException {\r
+ if (forTerminal instanceof ResourceTerminal)\r
+ return getPossibleConnectionPointOfTerminal(g, ((ResourceTerminal) forTerminal).getResource());\r
+ return null;\r
+ }\r
+\r
+ public static LineJoin toLineJoin(G2DResource g2d, Resource lineJoin) {\r
+ if (lineJoin != null) {\r
+ if (lineJoin.equals(g2d.LineJoin_BevelJoin))\r
+ return LineJoin.bevel;\r
+ if (lineJoin.equals(g2d.LineJoin_RoundJoin))\r
+ return LineJoin.round;\r
+ }\r
+ return LineJoin.miter;\r
+ }\r
+\r
+ public static LineCap toLineCap(G2DResource g2d, Resource lineCap) {\r
+ if (lineCap != null) {\r
+ if (lineCap.equals(g2d.LineCap_ButtCap))\r
+ return LineCap.butt;\r
+ if (lineCap.equals(g2d.LineCap_RoundCap))\r
+ return LineCap.round;\r
+ }\r
+ return LineCap.square;\r
+ }\r
+\r
+ public static Resource toLineJoin(G2DResource g2d, LineJoin lineJoin) {\r
+ if (lineJoin != null) {\r
+ if (lineJoin.equals(LineJoin.bevel))\r
+ return g2d.LineJoin_BevelJoin;\r
+ if (lineJoin.equals(LineJoin.round))\r
+ return g2d.LineJoin_RoundJoin;\r
+ }\r
+ return g2d.LineJoin_MiterJoin;\r
+ }\r
+\r
+ public static Resource toLineCap(G2DResource g2d, LineCap lineCap) {\r
+ if (lineCap != null) {\r
+ if (lineCap.equals(LineCap.butt))\r
+ return g2d.LineCap_ButtCap;\r
+ if (lineCap.equals(LineCap.round))\r
+ return g2d.LineCap_RoundCap;\r
+ }\r
+ return g2d.LineCap_SquareCap;\r
+ }\r
+\r
+ public static Alignment toAlignment(Resource align, G2DResource g2d, Alignment defaultValue) {\r
+ if (align == null)\r
+ return defaultValue;\r
+ if (align.equals(g2d.Alignment_Leading))\r
+ return Alignment.LEADING;\r
+ if (align.equals(g2d.Alignment_Trailing))\r
+ return Alignment.TRAILING;\r
+ if (align.equals(g2d.Alignment_Center))\r
+ return Alignment.CENTER;\r
+ return defaultValue;\r
+ }\r
+\r
+ public static Alignment toVerticalAlignment(Resource align, G2DResource g2d, Alignment defaultValue) {\r
+ if (align == null)\r
+ return defaultValue;\r
+ if (align.equals(g2d.Alignment_Leading))\r
+ return Alignment.LEADING;\r
+ if (align.equals(g2d.Alignment_Trailing))\r
+ return Alignment.TRAILING;\r
+ if (align.equals(g2d.Alignment_Center))\r
+ return Alignment.CENTER;\r
+ if (align.equals(g2d.Alignment_Baseline))\r
+ return Alignment.BASELINE;\r
+ return defaultValue;\r
+ }\r
+\r
+\r
+ public static Resource toFlagTypeResource(DiagramResource dr, FlagClass.Type type) {\r
+ switch (type) {\r
+ case In: return dr.FlagType_InputFlag;\r
+ case Out: return dr.FlagType_OutputFlag;\r
+ default: throw new IllegalArgumentException("unsupported flag type: " + type);\r
+ }\r
+ }\r
+\r
+ public static FlagClass.Type toFlagType(DiagramResource dr, Resource type) {\r
+ return toFlagType(dr, type, Type.In);\r
+ }\r
+\r
+ public static FlagClass.Type toFlagType(DiagramResource dr, Resource type, FlagClass.Type defaultValue) {\r
+ if (type != null) {\r
+ if (dr.FlagType_InputFlag.equals(type))\r
+ return Type.In;\r
+ if (dr.FlagType_OutputFlag.equals(type))\r
+ return Type.Out;\r
+ }\r
+ return defaultValue;\r
+ }\r
+\r
+ public static void tag(WriteGraph g, Resource object, Resource tag, boolean set) throws DatabaseException {\r
+ if (set)\r
+ g.claim(object, tag, tag, object);\r
+ else\r
+ g.deny(object, tag, tag, object);\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param diagram the diagram from which to look for a page description\r
+ * property\r
+ * @return if the diagram does not have a page desc definition,\r
+ * <code>defaultValue</code> is returned\r
+ * @throws DatabaseException\r
+ */\r
+ public static PageDesc getPageDesc(ReadGraph graph, Resource diagram, PageDesc defaultValue) throws DatabaseException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ Resource pd = graph.getPossibleObject(diagram, dr.HasPageDescription);\r
+ if (pd == null)\r
+ return defaultValue;\r
+ return readPageDesc(graph, pd);\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param diagram\r
+ * the diagram from which to look for a page description property\r
+ * @return PageDesc for the specified diagram\r
+ * @throws DatabaseException\r
+ * if DIA.HasPageDescription can't be read\r
+ */\r
+ public static PageDesc getPageDesc(ReadGraph graph, Resource diagram) throws DatabaseException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ Resource pd = graph.getSingleObject(diagram, dr.HasPageDescription);\r
+ return readPageDesc(graph, pd);\r
+ }\r
+\r
+ public static PageDesc readPageDesc(ReadGraph graph, Resource pageDesc) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ Resource orientation = graph.getSingleObject(pageDesc, dr.PageDescription_Orientation);\r
+ double[] size = graph.getRelatedValue(pageDesc, dr.PageDescription_Size, Bindings.getBindingUnchecked(double[].class));\r
+ Resource margins = graph.getSingleObject(pageDesc, dr.PageDescription_Margins);\r
+ Margins m = readMargins(graph, margins);\r
+ //PageDesc pd = PageDesc.getDescription(toOrientation(orientation, dr), size[0], size[1]);\r
+ String name = graph.getPossibleRelatedValue(pageDesc, l0.HasName);\r
+ if (name == null)\r
+ name = "";\r
+ PageDesc pd = new PageDesc(name, toOrientation(orientation, dr), PageCentering.TopLeftAtOrigin, size[0], size[1], m);\r
+ return pd;\r
+ }\r
+\r
+ public static Margins readMargins(ReadGraph graph, Resource margins) throws NoSingleResultException, DoesNotContainValueException, ServiceException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ double t = graph.getRelatedValue(margins, dr.PageDescription_Margins_Top);\r
+ double b = graph.getRelatedValue(margins, dr.PageDescription_Margins_Bottom);\r
+ double l = graph.getRelatedValue(margins, dr.PageDescription_Margins_Left);\r
+ double r = graph.getRelatedValue(margins, dr.PageDescription_Margins_Right);\r
+ Margin mt = new Margin(0, 0, t);\r
+ Margin mb = new Margin(0, 0, b);\r
+ Margin ml = new Margin(0, 0, l);\r
+ Margin mr = new Margin(0, 0, r);\r
+ return new Margins(mt, mb, ml, mr);\r
+ }\r
+\r
+ public static void setPageDesc(WriteGraph graph, Resource diagram, String pageDescRepr) throws DatabaseException {\r
+ setPageDesc(graph, diagram, PageDesc.fromRepr(pageDescRepr));\r
+ }\r
+ \r
+ public static void setPageDesc(WriteGraph graph, Resource diagram, PageDesc pageDesc) throws DatabaseException {\r
+ Layer0 b = Layer0.getInstance(graph);\r
+ G2DResource g2d = G2DResource.getInstance(graph);\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ Resource pd = graph.getPossibleObject(diagram, dr.HasPageDescription);\r
+ if(pd != null && graph.isImmutable(pd)) {\r
+ graph.deny(diagram, dr.HasPageDescription);\r
+ pd = null;\r
+ }\r
+ if (pd == null) {\r
+ pd = graph.newResource();\r
+ graph.claim(pd, b.InstanceOf, null, dr.PageDescription);\r
+ graph.claim(diagram, dr.HasPageDescription, pd);\r
+ }\r
+ graph.deny(pd, dr.PageDescription_Size);\r
+ Resource pageSize = graph.newResource();\r
+ graph.claim(pageSize, b.InstanceOf, null, g2d.Point2D);\r
+ graph.claimValue(pageSize, new double[] { pageDesc.getWidth(), pageDesc.getHeight() });\r
+ graph.claim(pd, dr.PageDescription_Size, pageSize);\r
+ graph.deny(pd, dr.PageDescription_Orientation);\r
+ graph.claim(pd, dr.PageDescription_Orientation, toOrientationResource(pageDesc.getOrientation(), dr));\r
+ Resource margins = graph.getPossibleObject(pd, dr.PageDescription_Margins);\r
+ if (margins == null) {\r
+ margins = graph.newResource();\r
+ graph.claim(margins, b.InstanceOf, null, dr.Margins);\r
+ graph.claim(pd, dr.PageDescription_Margins, margins);\r
+ }\r
+ setMargins(graph,pageDesc.getMargins(),margins, dr);\r
+ graph.claimLiteral(pd, b.HasName,pageDesc.getText());\r
+ }\r
+\r
+ private static PageOrientation toOrientation(Resource orientation, DiagramResource dr) {\r
+ if (orientation != null) {\r
+ if (orientation.equals(dr.Orientation_Portrait))\r
+ return PageOrientation.Portrait;\r
+ if (orientation.equals(dr.Orientation_Landscape))\r
+ return PageOrientation.Landscape;\r
+ }\r
+ return PageOrientation.Portrait;\r
+ }\r
+\r
+ public static Resource toOrientationResource(PageOrientation orientation, DiagramResource dr) {\r
+ if (PageOrientation.Portrait.equals(orientation))\r
+ return dr.Orientation_Portrait;\r
+ if (PageOrientation.Landscape.equals(orientation))\r
+ return dr.Orientation_Landscape;\r
+ return dr.Orientation_Portrait;\r
+ }\r
+\r
+ private static void setMargins(WriteGraph g, Margins margins, Resource marginsR,DiagramResource dr) throws ServiceException, ManyObjectsForFunctionalRelationException {\r
+\r
+ g.claimLiteral(marginsR, dr.PageDescription_Margins_Top,margins.top.diagramAbsolute);\r
+ g.claimLiteral(marginsR, dr.PageDescription_Margins_Bottom,margins.bottom.diagramAbsolute);\r
+ g.claimLiteral(marginsR, dr.PageDescription_Margins_Left,margins.left.diagramAbsolute);\r
+ g.claimLiteral(marginsR, dr.PageDescription_Margins_Right,margins.right.diagramAbsolute);\r
+\r
+ }\r
+\r
+ public static Double getGridSize(ReadGraph graph, Resource diagram, Double defaultValue) throws ManyObjectsForFunctionalRelationException, ServiceException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ Double gridSize = graph.getPossibleRelatedValue(diagram, dr.HasGridSize);\r
+ return gridSize == null ? defaultValue : gridSize;\r
+ }\r
+\r
+ public static void setGridSize(WriteGraph graph, Resource diagram, double gridSize) throws ManyObjectsForFunctionalRelationException, ServiceException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ graph.claimLiteral(diagram, dr.HasGridSize, gridSize);\r
+ }\r
+\r
+ public static boolean isPageBordersVisible(ReadGraph graph, Resource diagram) throws DatabaseException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ return graph.hasStatement(diagram, dr.DisplayPageSize);\r
+ }\r
+\r
+ public static boolean isMarginsVisible(ReadGraph graph, Resource diagram) throws DatabaseException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ return graph.hasStatement(diagram, dr.DisplayMargins);\r
+ }\r
+\r
+ public static void setPageBordersVisible(WriteGraph graph, Resource diagram, boolean visible) throws DatabaseException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ tag(graph, diagram, dr.DisplayPageSize, visible);\r
+ }\r
+\r
+ public static void setMarginsVisible(WriteGraph graph, Resource diagram, boolean visible) throws DatabaseException {\r
+ DiagramResource dr = DiagramResource.getInstance(graph);\r
+ tag(graph, diagram, dr.DisplayMargins, visible);\r
+ }\r
+\r
+ public static void setDiagramDesc(WriteGraph graph, Resource diagram, DiagramDesc desc) throws DatabaseException {\r
+ DiagramGraphUtil.setPageDesc(graph, diagram, desc.getPageDesc());\r
+ DiagramGraphUtil.setGridSize(graph, diagram, desc.getGridSize());\r
+ DiagramGraphUtil.setPageBordersVisible(graph, diagram, desc.isPageBordersVisible());\r
+ DiagramGraphUtil.setMarginsVisible(graph, diagram, desc.isMarginsVisible());\r
+ // Add comment to change set.\r
+ CommentMetadata cm = graph.getMetadata(CommentMetadata.class);\r
+ graph.addMetadata(cm.add("Set diagram description for diagram resource " + diagram));\r
+ }\r
+\r
+ /**\r
+ * Potentially returns the connection connected to the element with the\r
+ * given connectionRelation.\r
+ */\r
+ public static Resource getRelatedConnection(ReadGraph g, Resource element, Resource connectionRelation) throws DatabaseException {\r
+ StructuralResource2 sr = StructuralResource2.getInstance(g);\r
+ for(Resource connector : g.getObjects(element, connectionRelation))\r
+ for(Resource connection : g.getObjects(connector, sr.Connects))\r
+ if(!connection.equals(element))\r
+ return connection;\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Returns the connection type of a potential connection connected to the\r
+ * element with the given connectionRelation.\r
+ */\r
+ public static Resource getRelatedConnectionType(ReadGraph g, Resource element, Resource connectionRelation) throws DatabaseException {\r
+ StructuralResource2 sr = StructuralResource2.getInstance(g);\r
+ for(Resource connector : g.getObjects(element, connectionRelation))\r
+ for(Resource connection : g.getObjects(connector, sr.Connects))\r
+ if(!connection.equals(element))\r
+ for(Resource connectionType : g.getObjects(connection, sr.HasConnectionType))\r
+ return connectionType;\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Returns a flag that is joined to this flag with a ConnectionJoin.\r
+ */\r
+ public static Resource getJoinedFlag(ReadGraph g, Resource flag) throws DatabaseException {\r
+ DiagramResource dr = DiagramResource.getInstance(g);\r
+ for(Resource join : g.getObjects(flag, dr.FlagIsJoinedBy))\r
+ for(Resource otherFlag : g.getObjects(join, dr.JoinsFlag))\r
+ if(!otherFlag.equals(flag))\r
+ return otherFlag;\r
+ return null;\r
+ }\r
+\r
+ public static Resource getConnectionTypeForFlag(ReadGraph g, Resource flag) throws DatabaseException {\r
+ DiagramResource dr = DiagramResource.getInstance(g);\r
+\r
+ Resource connectionType = getRelatedConnectionType(g, flag, dr.Flag_ConnectionPoint);\r
+ if(connectionType != null)\r
+ return connectionType;\r
+\r
+ Resource otherFlag = getJoinedFlag(g, flag);\r
+ if(otherFlag == null)\r
+ return null;\r
+\r
+ return getRelatedConnectionType(g, otherFlag, dr.Flag_ConnectionPoint);\r
+ }\r
+\r
+ /**\r
+ * Checks if the two specified diagram elements exist on the same diagram.\r
+ */\r
+ public static boolean onSameDiagram(ReadGraph graph, Resource element1, Resource element2) throws DatabaseException {\r
+ return !Collections.disjoint(\r
+ OrderedSetElementsPredicate.INSTANCE.getSubjects(graph, element1),\r
+ OrderedSetElementsPredicate.INSTANCE.getSubjects(graph, element2));\r
+ }\r
+\r
+ /**\r
+ * Checks whether a diagram element has a <code>DIAGRAM.Routing</code> tag\r
+ * that is adaptable to {@link IRouter2}.\r
+ * \r
+ * @param graph\r
+ * @param element\r
+ * @param procedure\r
+ */\r
+ public static void getPossibleRouter(AsyncReadGraph graph, final Resource element, final AsyncProcedure<IRouter2> procedure) {\r
+ DiagramResource dr = graph.getService(DiagramResource.class);\r
+ graph.forPossibleStatement(element, dr.Routing, new AsyncProcedure<Statement>() {\r
+ @Override\r
+ public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+ procedure.exception(graph, throwable);\r
+ }\r
+ @Override\r
+ public void execute(AsyncReadGraph graph, Statement result) {\r
+ if (result != null)\r
+ graph.forPossibleAdapted(result.getPredicate(), IRouter2.class, procedure);\r
+ else\r
+ procedure.execute(graph, null);\r
+ }\r
+ });\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param modelingRules\r
+ * @param connection\r
+ * @param diagram\r
+ * @param edge\r
+ * @param firstTerminal\r
+ * @param secondTerminal\r
+ * @throws DatabaseException\r
+ */\r
+ public static void loadConnectionVisuals(ReadGraph graph, IModelingRules modelingRules, Resource connection,\r
+ IDiagram diagram, IElement edge, DesignatedTerminal firstTerminal, DesignatedTerminal secondTerminal)\r
+ throws DatabaseException {\r
+ List<EdgeVisuals> evs = edge.getElementClass().getItemsByClass(EdgeVisuals.class);\r
+ if (evs.isEmpty())\r
+ return;\r
+\r
+ IAttachmentRelationMap attachmentRelations = modelingRules.getAttachmentRelations(graph, connection);\r
+\r
+ IConnectionPoint firstCp = ConnectionUtil.toConnectionPoint(graph, firstTerminal);\r
+ IConnectionPoint secondCp = ConnectionUtil.toConnectionPoint(graph, secondTerminal);\r
+\r
+ Resource firstAttachment = null;\r
+ Resource secondAttachment = null;\r
+\r
+ if (firstCp instanceof CPTerminal)\r
+ firstAttachment = attachmentRelations.get(graph, (CPTerminal) firstCp);\r
+ if (secondCp instanceof CPTerminal)\r
+ secondAttachment = attachmentRelations.get(graph, (CPTerminal) secondCp);\r
+\r
+ if (DebugPolicy.DEBUG_CONNECTION_VISUALS_LOAD) {\r
+ System.out.println("first attachment relation : " + NameUtils.getSafeName(graph, firstAttachment));\r
+ System.out.println("second attachment relation : " + NameUtils.getSafeName(graph, secondAttachment));\r
+ }\r
+\r
+ // 1. Configure edge ends\r
+ loadEdgeEnds(graph, modelingRules, connection, edge, firstAttachment, secondAttachment);\r
+\r
+ // 2. Configure edge line style\r
+ loadLineStyle(graph, modelingRules, connection, edge);\r
+ }\r
+\r
+ public static void loadEdgeEnds(ReadGraph graph, IModelingRules modelingRules, Resource connection, IElement edge,\r
+ Resource firstAttachment, Resource secondAttachment) throws DatabaseException {\r
+ EdgeVisualsConfigurer startConfig = (firstAttachment != null) ? graph.syncRequest(Queries.adapt(\r
+ firstAttachment, EdgeVisualsConfigurer.class, true)) : null;\r
+ EdgeVisualsConfigurer endConfig = (secondAttachment != null) ? graph.syncRequest(Queries.adapt(\r
+ secondAttachment, EdgeVisualsConfigurer.class, true)) : null;\r
+\r
+ for (EdgeVisuals ev : edge.getElementClass().getItemsByClass(EdgeVisuals.class)) {\r
+ if (startConfig != null)\r
+ startConfig.configure(edge, ev, EdgeVisuals.BEGIN);\r
+ else\r
+ ev.setArrowType(edge, EdgeEnd.Begin, ArrowType.None);\r
+ if (endConfig != null)\r
+ endConfig.configure(edge, ev, EdgeVisuals.END);\r
+ else\r
+ ev.setArrowType(edge, EdgeEnd.End, ArrowType.None);\r
+ }\r
+ }\r
+\r
+ public static void loadLineStyle(ReadGraph graph, IModelingRules modelingRules, Resource connection, IElement edge)\r
+ throws DatabaseException {\r
+ Resource connectionType = modelingRules.getConnectionType(graph, connection);\r
+ if (connectionType != null) {\r
+ loadLineStyleFromConnectionType(graph, modelingRules, connectionType, edge);\r
+ }\r
+ }\r
+\r
+ public static void loadLineStyleFromConnectionType(ReadGraph graph, IModelingRules modelingRules, Resource connectionType, IElement edge)\r
+ throws DatabaseException {\r
+ edge.setHint(ElementHints.KEY_CONNECTION_TYPE, connectionType);\r
+ if (DebugPolicy.DEBUG_CONNECTION_VISUALS_LOAD)\r
+ System.out.println("Connection type : " + NameUtils.getSafeName(graph, connectionType));\r
+\r
+ // Load standard visual aspects of the specified edge\r
+ ConnectionVisuals cv = graph.syncRequest(DiagramRequests.getConnectionVisuals(connectionType));\r
+\r
+ if (cv.color != null) {\r
+ for (FillColor fc : edge.getElementClass().getItemsByClass(FillColor.class)) {\r
+ fc.setFillColor(edge, cv.toColor());\r
+ }\r
+ }\r
+ for (EdgeVisuals ev : edge.getElementClass().getItemsByClass(EdgeVisuals.class)) {\r
+ if (cv.stroke != null)\r
+ ev.setStroke(edge, cv.stroke);\r
+ if (cv.strokeType != null)\r
+ ev.setStrokeType(edge, cv.strokeType);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param connectionPart\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public static ConnectionSegmentEnd resolveConnectionSegmentEnd(ReadGraph graph, Resource connectionPart)\r
+ throws DatabaseException {\r
+ BasicResources br = BasicResources.getInstance(graph);\r
+ if (graph.isInstanceOf(connectionPart, br.DIA.BranchPoint))\r
+ return ConnectionSegmentEnd.BRANCH;\r
+ if (graph.isInstanceOf(connectionPart, br.DIA.Connector))\r
+ return ConnectionSegmentEnd.CONNECTOR;\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param diagram\r
+ * @param segmentEnd\r
+ * @param endType\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public static DesignatedTerminal findDesignatedTerminal(ReadGraph graph, IDiagram diagram, Resource segmentEnd, ConnectionSegmentEnd endType)\r
+ throws DatabaseException {\r
+ if (DebugPolicy.DEBUG_TERMINAL_SEARCH)\r
+ System.out.println("findDesignatedTerminal: " + NameUtils.getSafeName(graph, segmentEnd) + " : " + endType);\r
+\r
+ BasicResources br = BasicResources.getInstance(graph);\r
+ DataElementMap dem = diagram.getDiagramClass().getSingleItem(DataElementMap.class);\r
+\r
+ switch (endType) {\r
+ case CONNECTOR: {\r
+ List<Terminal> ts = new ArrayList<Terminal>();\r
+ for (Statement stm : graph.getStatements(segmentEnd, br.STR.Connects)) {\r
+ // Ignore the Is Connector Of relation that goes to the\r
+ // owner :Connection\r
+ if (graph.isSubrelationOf(stm.getPredicate(), br.DIA.IsConnectorOf))\r
+ continue;\r
+\r
+ Resource connectionRelation = graph.getInverse(stm.getPredicate());\r
+ if (DebugPolicy.DEBUG_TERMINAL_SEARCH)\r
+ System.out.println("CONNECTION RELATION: " + NameUtils.getSafeName(graph, connectionRelation));\r
+ Resource elementResource = stm.getObject();\r
+ if (DebugPolicy.DEBUG_TERMINAL_SEARCH)\r
+ System.out.println("ELEMENT RESOURCE: " + NameUtils.getSafeName(graph, elementResource));\r
+ IElement e = dem.getElement(diagram, elementResource);\r
+ if (e == null) {\r
+ return null;\r
+// throw new ValidationException("connector "\r
+// + NameUtils.getSafeName(graph, segmentEnd)\r
+// + " is connected to an entity that has not (yet) been loaded as an IElement: "\r
+// + NameUtils.getSafeName(graph, elementResource));\r
+ }\r
+\r
+ TerminalTopology tt = e.getElementClass().getSingleItem(TerminalTopology.class);\r
+ ts.clear();\r
+ tt.getTerminals(e, ts);\r
+ for (Terminal t : ts) {\r
+ if (t instanceof ResourceTerminal) {\r
+ ResourceTerminal rt = (ResourceTerminal) t;\r
+ Resource binds = DiagramGraphUtil.getConnectionPointOfTerminal(graph, rt.getResource());\r
+ if (DebugPolicy.DEBUG_TERMINAL_SEARCH) {\r
+ System.out.println("connection relation: "\r
+ + NameUtils.getSafeName(graph, connectionRelation) + " " + connectionRelation.getResourceId());\r
+ System.out.println(" terminal: " + NameUtils.getSafeName(graph, rt.getResource()) + " " + rt.getResource().getResourceId());\r
+ System.out.println(" binds: " + NameUtils.getSafeName(graph, binds) + " " + binds.getResourceId());\r
+ }\r
+ if (graph.isSubrelationOf(connectionRelation, binds)) {\r
+ return new DesignatedTerminal(e, t);\r
+ }\r
+ }\r
+ }\r
+\r
+ throw new ValidationException("connector "\r
+ + NameUtils.getSafeName(graph, segmentEnd)\r
+ + " is connected using a relation that is not its own: "\r
+ + NameUtils.getSafeName(graph, connectionRelation));\r
+ }\r
+ // throw new\r
+ // ValidationException("connector " +\r
+ // NameUtils.getSafeName(g, segmentEnd) +\r
+ // " is not connected to anything");\r
+ return null;\r
+ }\r
+ case BRANCH: {\r
+ List<Terminal> ts = new ArrayList<Terminal>();\r
+ IElement e = dem.getElement(diagram, segmentEnd);\r
+ if (e == null) {\r
+// throw new ValidationException("branch point "\r
+// + NameUtils.getSafeName(graph, segmentEnd)\r
+// + " has not (yet) been loaded as an IElement");\r
+ return null;\r
+ }\r
+\r
+ TerminalTopology tt = e.getElementClass().getSingleItem(TerminalTopology.class);\r
+ tt.getTerminals(e, ts);\r
+ if (ts.size() != 1)\r
+ throw new IllegalStateException("branch point element has " + ts.size()\r
+ + " terminals, expected 1");\r
+ return new DesignatedTerminal(e, ts.get(0));\r
+ }\r
+ default:\r
+ throw new IllegalArgumentException("unexpected connection segment end: " + endType);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param diagram\r
+ * @param terminalStm the statement that goes from the connection\r
+ * connector to the node with inverse relation of the terminal\r
+ * relation.\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public static DesignatedTerminal getDesignatedTerminalForConnector(ReadGraph graph, IDiagram diagram, Resource elementResource, Resource terminalRelation, Resource connector)\r
+ throws DatabaseException {\r
+ if (DebugPolicy.DEBUG_TERMINAL_SEARCH)\r
+ System.out.println("getDesignatedTerminalForConnector: ("\r
+ + NameUtils.getSafeName(graph, elementResource) + ", "\r
+ + NameUtils.getSafeName(graph, terminalRelation) + ", "\r
+ + NameUtils.getSafeName(graph, connector) + ")"\r
+ );\r
+\r
+ DataElementMap dem = diagram.getDiagramClass().getSingleItem(DataElementMap.class);\r
+ IElement e = dem.getElement(diagram, elementResource);\r
+ if (e == null)\r
+ return null;\r
+\r
+ TerminalTopology tt = e.getElementClass().getSingleItem(TerminalTopology.class);\r
+ List<Terminal> ts = new ArrayList<Terminal>();\r
+ tt.getTerminals(e, ts);\r
+ for (Terminal t : ts) {\r
+ if (t instanceof ResourceTerminal) {\r
+ ResourceTerminal rt = (ResourceTerminal) t;\r
+ Resource binds = DiagramGraphUtil.getConnectionPointOfTerminal(graph, rt.getResource());\r
+ if (DebugPolicy.DEBUG_TERMINAL_SEARCH) {\r
+ System.out.println("connection relation: "\r
+ + NameUtils.getSafeName(graph, terminalRelation, true));\r
+ System.out.println(" terminal: " + NameUtils.getSafeName(graph, rt.getResource(), true));\r
+ System.out.println(" binds: " + NameUtils.getSafeName(graph, binds, true));\r
+ }\r
+ if (graph.isSubrelationOf(terminalRelation, binds)) {\r
+ return new DesignatedTerminal(e, t);\r
+ }\r
+ }\r
+ }\r
+\r
+ throw new ValidationException("terminal connection statement ("\r
+ + NameUtils.getSafeName(graph, elementResource) + ", "\r
+ + NameUtils.getSafeName(graph, terminalRelation) + ", "\r
+ + NameUtils.getSafeName(graph, connector) + ")"\r
+ + " is using using a terminal relation that is not its own: "\r
+ + NameUtils.getSafeName(graph, terminalRelation));\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public static TerminalMap getElementTerminals(ReadGraph graph, Resource element)\r
+ throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ Resource elementType = graph.getPossibleType(element, DIA.Element);\r
+ return elementType != null ? getElementTypeTerminals(graph, elementType) : TerminalMap.EMPTY;\r
+ }\r
+\r
+ private static final boolean DEBUG_GET_ELEMENT_TYPE_TERMINALS = false;\r
+\r
+ /**\r
+ * @param graph\r
+ * @param elementType\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public static TerminalMap getElementTypeTerminals(ReadGraph graph, Resource elementType) throws DatabaseException {\r
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ if (DEBUG_GET_ELEMENT_TYPE_TERMINALS)\r
+ System.out.println("getElementTypeTerminals: " + NameUtils.getSafeName(graph, elementType));\r
+ Resource definedBy = graph.getSingleObject(elementType, STR.IsDefinedBy);\r
+ Collection<Resource> parts = OrderedSetUtils.toList(graph, definedBy);\r
+ if (DEBUG_GET_ELEMENT_TYPE_TERMINALS)\r
+ System.out.println("\tdefining part count: " + parts.size());\r
+ TerminalMap result = null;\r
+ for (Resource part : parts) {\r
+ if (DEBUG_GET_ELEMENT_TYPE_TERMINALS)\r
+ System.out.println("\t\tpart: " + NameUtils.getSafeName(graph, part));\r
+ if (graph.isInstanceOf(part, DIA.Terminal)) {\r
+ Resource binds = DiagramGraphUtil.getConnectionPointOfTerminal(graph, part);\r
+ if (result == null)\r
+ result = new TerminalMap(parts.size());\r
+ if (DEBUG_GET_ELEMENT_TYPE_TERMINALS)\r
+ System.out.println("\t\t\tFOUND TERMINAL <-> BINDING RELATION: " + NameUtils.getSafeName(graph, part) + " <-> " + NameUtils.getSafeName(graph, binds));\r
+ result.put(part, binds);\r
+ }\r
+ }\r
+ return result != null ? result : TerminalMap.EMPTY;\r
+ }\r
+\r
+ /**\r
+ * Get the value of a specified on/off diagram preference setting (=tag)\r
+ * where the tag may be stored in:\r
+ * <ol>\r
+ * <li>The diagram itself</li>\r
+ * <li>The model</li>\r
+ * <li>The project</li>\r
+ * </ol>\r
+ * \r
+ * @param graph database access\r
+ * @param diagram the diagram to look for the tag in\r
+ * @param preference the tag relation of the boolean preference to check for\r
+ * @return value of the preference\r
+ * @throws DatabaseException\r
+ */\r
+ public static boolean getDiagramTagPreference(ReadGraph graph, Resource diagram, Resource preference) throws DatabaseException {\r
+ boolean result = graph.hasStatement(diagram, preference);\r
+ if (!result) {\r
+ Resource model = graph.sync(new PossibleModel(diagram));\r
+ if (model != null)\r
+ result = graph.hasStatement(model, preference);\r
+ if (!result)\r
+ result = graph.hasStatement(Simantics.getProjectResource(), preference);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ public static void rotateConnection(WriteGraph graph, Resource r, \r
+ double cx, double cy, boolean clockwise) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ for(Resource node : graph.getObjects(r, DIA.HasInteriorRouteNode))\r
+ if(graph.isInstanceOf(node, DIA.RouteLine)) {\r
+ boolean isHorizontal = (Boolean)graph.getRelatedValue(node, DIA.IsHorizontal);\r
+ double position = (Double)graph.getRelatedValue(node, DIA.HasPosition);\r
+ \r
+ if(isHorizontal) {\r
+ position -= cy;\r
+ if(clockwise)\r
+ position = -position;\r
+ position += cx;\r
+ }\r
+ else {\r
+ position -= cx;\r
+ if(!clockwise)\r
+ position = -position;\r
+ position += cy;\r
+ }\r
+ isHorizontal = !isHorizontal; \r
+ \r
+ graph.claimLiteral(node, DIA.IsHorizontal, isHorizontal);\r
+ graph.claimLiteral(node, DIA.HasPosition, position);\r
+ }\r
+ }\r
+\r
+ public static void flipConnection(WriteGraph graph, Resource r,\r
+ boolean xAxis, double c) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ for(Resource node : graph.getObjects(r, DIA.HasInteriorRouteNode))\r
+ if(graph.isInstanceOf(node, DIA.RouteLine)) {\r
+ boolean isHorizontal = (Boolean)graph.getRelatedValue(node, DIA.IsHorizontal);\r
+\r
+ if(isHorizontal == xAxis) {\r
+ double position = (Double)graph.getRelatedValue(node, DIA.HasPosition);\r
+ position = 2*c-position;\r
+ graph.claimLiteral(node, DIA.HasPosition, position);\r
+ }\r
+ }\r
+ }\r
+ \r
+ /*public static void addConnectionPoint(WriteGraph g, Resource symbol, Resource terminal, \r
+ Resource diagramConnectionRelation) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ \r
+ Resource variable = g.newResource();\r
+ g.claim(variable, L0.InstanceOf, null, STR.ConnectionVariable);\r
+ g.claim(terminal, DIA.HasConnectionVariable, variable);\r
+ g.claim(variable, STR.Binds, diagramConnectionRelation);\r
+ g.claim(variable, STR.IsParameterOf, symbol);\r
+ }\r
+ \r
+\r
+ public static Resource getConnectionPointOfTerminal(ReadGraph g, Resource forTerminal) throws DatabaseException {\r
+ return g.getSingleObject(\r
+ g.getSingleObject(forTerminal, DiagramResource.getInstance(g).HasConnectionVariable),\r
+ StructuralResource2.getInstance(g).Binds);\r
+ }\r
+\r
+ public static Resource getPossibleConnectionPointOfTerminal(ReadGraph g, Resource forTerminal) throws DatabaseException {\r
+ Resource connectionVariable = g.getPossibleObject(forTerminal, DiagramResource.getInstance(g).HasConnectionVariable);\r
+ return (connectionVariable == null) ? null : g.getPossibleObject(connectionVariable, StructuralResource2.getInstance(g).Binds);\r
+ }*/\r
+ \r
+ public static void addConnectionPoint(WriteGraph g, Resource symbol, Resource terminal, \r
+ Resource diagramConnectionRelation) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ \r
+ g.claim(terminal, DIA.HasConnectionPoint, diagramConnectionRelation);\r
+ g.claim(diagramConnectionRelation, L0.HasDomain, symbol);\r
+ }\r
+ \r
+\r
+ public static Resource getConnectionPointOfTerminal(ReadGraph g, Resource forTerminal) throws DatabaseException {\r
+ return g.getSingleObject(forTerminal, DiagramResource.getInstance(g).HasConnectionPoint);\r
+ }\r
+\r
+ public static Resource getPossibleConnectionPointOfTerminal(ReadGraph g, Resource forTerminal) throws DatabaseException {\r
+ return g.getPossibleObject(forTerminal, DiagramResource.getInstance(g).HasConnectionPoint);\r
+ }\r
+\r
+ public static Collection<Resource> getTerminals(ReadGraph g, Resource symbol) throws DatabaseException {\r
+// Layer0 L0 = Layer0.getInstance(g);\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ List<Resource> terminals = null;\r
+ for (Resource definedBy : g.getObjects(symbol, STR.IsDefinedBy)) {\r
+ Collection<Resource> elements = g.syncRequest( new OrderedSet(definedBy) );\r
+ if (terminals == null)\r
+ terminals = new ArrayList<Resource>( elements.size() );\r
+ for (Resource element : elements)\r
+ if (g.isInstanceOf(element, DIA.Terminal))\r
+ terminals.add(element);\r
+ }\r
+// Collection<Resource> definedBy = g.getObjects(symbol, STR.IsDefinedBy);\r
+// if (!definedBy.isEmpty()) {\r
+// Collection<Resource> relations = g.getObjects(symbol, L0.DomainOf);\r
+// terminals = new ArrayList<Resource>(relations.size());\r
+// for(Resource relation : relations) {\r
+// for (Resource element : g.getObjects(relation, DIA.HasConnectionPoint_Inverse)) {\r
+// Collection<Resource> owners = OrderedSetUtils.getOwnerLists(g, element, DIA.Diagram);\r
+// if (!Collections.disjoint(definedBy, owners))\r
+// terminals.add(element);\r
+// }\r
+// }\r
+// }\r
+ return terminals == null ? Collections.<Resource>emptyList() : terminals;\r
+ }\r
+ \r
+ /**\r
+ * Determines the connection type of the given diagram connection. Uses the modeling rules\r
+ * specified in the diagram the connection belongs to.\r
+ */\r
+ public static Resource determineConnectionType(ReadGraph graph, Resource diagramConnection) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ Resource diagram = graph.getPossibleObject(diagramConnection, L0.PartOf);\r
+ if (diagram == null)\r
+ // Invalid diagram connection resource, not a part of any diagram.\r
+ return null;\r
+ IModelingRules modelingRules = graph.syncRequest(DiagramRequests.getModelingRules(diagram, null));\r
+ if (modelingRules == null)\r
+ return null;\r
+ return determineConnectionType(graph, diagramConnection, modelingRules);\r
+ }\r
+\r
+ /**\r
+ * Determines the connection type of the given diagram connection assuming the given modeling rules.\r
+ */\r
+ public static Resource determineConnectionType(ReadGraph graph, Resource diagramConnection, IModelingRules modelingRules) throws DatabaseException {\r
+\r
+ Set<IConnectionPoint> cps = new THashSet<IConnectionPoint>();\r
+ DiagramRequests.expandConnections(graph, diagramConnection, new THashSet<Resource>(), cps);\r
+ return modelingRules.computeConnectionType(graph, cps);\r
+ \r
+ }\r
+ \r
+ public static void defaultSymbolDropHandler(WriteGraph graph, List<WorkbenchSelectionElement> drop) throws DatabaseException {\r
+ System.err.println("dropped " + drop);\r
+ }\r
+ \r
+}\r