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