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