--- /dev/null
+package org.simantics.diagram.synchronization.graph;\r
+\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.util.RelativeReference;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+\r
+public class ElementIdentification {\r
+\r
+ /**\r
+ * Browses from given resource to neighbor resources by connectors.\r
+ * @param g\r
+ * @param r\r
+ * @return\r
+ */\r
+ private static ArrayList<Statement> browseConnectors(ReadGraph g, Resource r) throws DatabaseException {\r
+ ArrayList<Statement> result = new ArrayList<Statement>(2);\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+ for(Resource connector : g.getObjects(r, STR.IsConnectedTo))\r
+ for(Statement other : g.getStatements(connector, STR.Connects))\r
+ if(!other.getObject().equals(r))\r
+ result.add(other);\r
+ return result;\r
+ }\r
+ \r
+ private static Resource getJoinedFlag(ReadGraph g, Resource r) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ for(Resource join : g.getObjects(r, DIA.FlagIsJoinedBy))\r
+ for(Resource flag : g.getObjects(join, DIA.JoinsFlag))\r
+ if(!flag.equals(r))\r
+ return flag;\r
+ return null;\r
+ }\r
+ \r
+ /**\r
+ * Returns an identifier of the flag or null if the procedure fails.\r
+ */\r
+ private static RelativeReference getSimpleFlagIdentifier(ReadGraph g, Resource flag) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(g); \r
+ if(!g.isInstanceOf(flag, DIA.Flag))\r
+ return null;\r
+ ArrayList<Statement> connections = browseConnectors(g, flag);\r
+ if(connections.size() != 1)\r
+ return null; \r
+ Resource connection = connections.get(0).getObject();\r
+ ArrayList<Statement> connections2 = browseConnectors(g, connection);\r
+ for(Statement stat : connections2) {\r
+ Resource element = stat.getObject();\r
+ if(!g.isInstanceOf(element, DIA.Flag)) { \r
+ Resource relation = g.getInverse(stat.getPredicate()); \r
+ RelativeReference ref = getElementIdentifier(g, element);\r
+ if(ref != null) {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ return new RelativeReference(ref.base, ref.path + "#" + \r
+ g.getRelatedValue(relation, L0.HasName) \r
+ );\r
+ }\r
+ } \r
+ }\r
+ return null;\r
+ }\r
+ \r
+ private static RelativeReference getFlagIdentifier(ReadGraph g, Resource flag) throws DatabaseException {\r
+ RelativeReference ref1 = getSimpleFlagIdentifier(g, flag);\r
+ if(ref1 == null)\r
+ return null;\r
+ Resource otherFlag = getJoinedFlag(g, flag);\r
+ if(otherFlag == null)\r
+ return new RelativeReference(ref1.base, "UNJOINED_FLAG|" + ref1.path);\r
+ else {\r
+ RelativeReference ref2 = getSimpleFlagIdentifier(g, otherFlag);\r
+ if(ref2 == null)\r
+ return new RelativeReference(ref1.base, "UNJOINED_FLAG|" + ref1.path);\r
+ return new RelativeReference(ref1.base, "FLAG|" + ref1.path + "|" + ref2.path);\r
+ }\r
+ }\r
+ \r
+ public static RelativeReference getElementIdentifier(ReadGraph g, Resource element) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ ModelingResources MOD = ModelingResources.getInstance(g);\r
+ if(g.isInstanceOf(element, DIA.Flag)) {\r
+ return getFlagIdentifier(g, element); \r
+ }\r
+ else if(g.isInstanceOf(element, MOD.ReferenceElement)) {\r
+ Resource parent = g.getPossibleObject(element, MOD.HasParentComponent);\r
+ if(parent == null)\r
+ return null;\r
+ RelativeReference parentRef = \r
+ RelativeReference.createReference(g, MOD.StructuralModel, parent);\r
+ if(parentRef == null)\r
+ return null;\r
+ Resource referenceRelation = \r
+ g.getPossibleObject(element, MOD.HasReferenceRelation);\r
+ if(referenceRelation == null)\r
+ return null;\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ return new RelativeReference(parentRef.base, \r
+ "REFERENCE#"+parentRef.path+"#"+\r
+ g.getRelatedValue(referenceRelation, L0.HasName));\r
+ }\r
+ else { \r
+ Resource component = g.getPossibleObject(element, MOD.ElementToComponent);\r
+ if(component == null)\r
+ return null;\r
+ return RelativeReference.createReference(g, MOD.StructuralModel, component);\r
+ } \r
+ }\r
+ \r
+ public static RelativeReference getConnectorIdentifier(ReadGraph g, Resource connector) throws DatabaseException {\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ \r
+ for(Statement stat : g.getStatements(connector, STR.Connects)) {\r
+ if(!g.isInstanceOf(stat.getObject(), DIA.Connection)) {\r
+ RelativeReference ref = getElementIdentifier(g, stat.getObject());\r
+ if(ref == null || ref.path == null)\r
+ continue;\r
+ if(ref.path.contains("#"))\r
+ return ref;\r
+ else\r
+ return new RelativeReference(ref.base, ref.path + "#" + \r
+ g.getRelatedValue(g.getInverse(stat.getPredicate()), L0.HasName));\r
+ }\r
+ }\r
+ return new RelativeReference(null, "UNK");\r
+ } \r
+ \r
+ private static Resource resolveElementFromComponent(ReadGraph graph, Resource model, String path) throws DatabaseException {\r
+ Resource component = RelativeReference.resolve(graph, model, path);\r
+ if(component == null) {\r
+ System.err.println("Didn't find component " + path);\r
+ return null;\r
+ }\r
+ \r
+ ModelingResources MOD = ModelingResources.getInstance(graph);\r
+ Resource element = graph.getPossibleObject(component, MOD.ComponentToElement);\r
+ if(element == null) {\r
+ System.err.println("Didn't find element for component " + path);\r
+ return null;\r
+ } \r
+ return element;\r
+ }\r
+ \r
+ private static ArrayList<Resource> findRelatedFlags(ReadGraph graph, Resource model, String path) throws DatabaseException {\r
+ ArrayList<Resource> result = new ArrayList<Resource>();\r
+ String[] parts = path.split("#");\r
+ Resource element;\r
+ String attributeName;\r
+ if(parts[0].equals("REFERENCE")) {\r
+ element = resolveReference(graph, model, path);\r
+ attributeName = parts[3];\r
+ }\r
+ else {\r
+ element = resolveElementFromComponent(graph, model, parts[0]);\r
+ attributeName = parts[1];\r
+ }\r
+ if(element == null)\r
+ return result;\r
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ for(Statement stat : graph.getStatements(element, STR.IsConnectedTo)) {\r
+ if(attributeName.equals(graph.getRelatedValue(stat.getPredicate(), L0.HasName))) {\r
+ Resource connector1 = stat.getObject();\r
+ for(Resource connection : graph.getObjects(connector1, STR.Connects)) {\r
+ for(Resource connector2 : graph.getObjects(connection, STR.IsConnectedTo))\r
+ if(!connector2.equals(connector1)) {\r
+ for(Resource flag : graph.getObjects(connector2, STR.Connects)) {\r
+ if(graph.isInstanceOf(flag, DIA.Flag))\r
+ result.add(flag);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ public static Resource resolveElement(ReadGraph graph, Resource model, String path) throws DatabaseException {\r
+ String[] parts = path.split("\\|");\r
+ \r
+ if(parts[0].equals("UNJOINED_FLAG")) {\r
+ ArrayList<Resource> flags = findRelatedFlags(graph, model, parts[1]);\r
+ if(flags.isEmpty()) {\r
+ System.err.println("Didn't find any flag " + path);\r
+ return null;\r
+ }\r
+ // TODO filter multiple found flags\r
+ return flags.get(0);\r
+ }\r
+ else if(parts[0].equals("FLAG")) {\r
+ ArrayList<Resource> flags = findRelatedFlags(graph, model, parts[1]);\r
+ if(flags.isEmpty()) {\r
+ System.err.println("Didn't find any flag " + path);\r
+ return null;\r
+ }\r
+ if(flags.size() == 1)\r
+ return flags.get(0);\r
+ THashSet<Resource> flagSet = new THashSet<Resource>(findRelatedFlags(graph, model, parts[2]));\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ for(Resource f : flags)\r
+ for(Resource join : graph.getObjects(f, DIA.FlagIsJoinedBy))\r
+ for(Resource otherFlag : graph.getObjects(join, DIA.JoinsFlag))\r
+ if(flagSet.contains(otherFlag))\r
+ return f;\r
+ System.err.println("Ambiguous flag reference " + path);\r
+ return null;\r
+ }\r
+ else if(path.startsWith("REFERENCE#")) {\r
+ return resolveReference(graph, model, path);\r
+ }\r
+ else {\r
+ return resolveElementFromComponent(graph, model, path);\r
+ }\r
+ }\r
+ \r
+ private static Resource resolveReference(ReadGraph graph, Resource model, String path) throws DatabaseException {\r
+ String[] parts = path.split("#");\r
+ Resource component = RelativeReference.resolve(graph, model, parts[1]);\r
+ if(component == null) {\r
+ System.err.println("Didn't find component " + path);\r
+ return null;\r
+ }\r
+ \r
+ ModelingResources MOD = ModelingResources.getInstance(graph);\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ for(Resource element : graph.getObjects(component, MOD.HasParentComponent_Inverse)) {\r
+ Resource referenceRelation = graph.getSingleObject(element, MOD.HasReferenceRelation);\r
+ if(parts[2].equals(graph.getRelatedValue(referenceRelation, L0.HasName)))\r
+ return element;\r
+ }\r
+\r
+ System.err.println("Didn't find element for " + path);\r
+ return null;\r
+ }\r
+ \r
+ public static List<Resource> resolveConnector(ReadGraph g, Resource model,\r
+ String name) throws DatabaseException {\r
+ if(name.equals("UNK"))\r
+ return Collections.emptyList();\r
+ if(name.startsWith("FLAG|") || name.startsWith("UNKNOWN_FLAG|")) {\r
+ Resource element = resolveElement(g, model, name);\r
+ return Arrays.asList(g.getSingleObject(element, \r
+ DiagramResource.getInstance(g).Flag_ConnectionPoint));\r
+ }\r
+ String[] parts = name.split("#");\r
+ Resource element = resolveElement(g, model, parts[0]);\r
+ if (element == null)\r
+ return Collections.emptyList();\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ ArrayList<Resource> result = new ArrayList<Resource>(2);\r
+ for(Statement stat : g.getStatements(element, STR.IsConnectedTo))\r
+ if(g.getRelatedValue(stat.getPredicate(), L0.HasName).equals(parts[1]))\r
+ result.add(stat.getObject());\r
+ return result;\r
+ }\r
+ \r
+}\r