]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/ElementIdentification.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / synchronization / graph / ElementIdentification.java
1 package org.simantics.diagram.synchronization.graph;
2
3 import gnu.trove.set.hash.THashSet;
4
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.Collections;
8 import java.util.List;
9
10 import org.simantics.db.ReadGraph;
11 import org.simantics.db.Resource;
12 import org.simantics.db.Statement;
13 import org.simantics.db.exception.DatabaseException;
14 import org.simantics.db.layer0.util.RelativeReference;
15 import org.simantics.diagram.stubs.DiagramResource;
16 import org.simantics.layer0.Layer0;
17 import org.simantics.modeling.ModelingResources;
18 import org.simantics.structural.stubs.StructuralResource2;
19
20 public class ElementIdentification {
21
22     /**
23      * Browses from given resource to neighbor resources by connectors.
24      * @param g
25      * @param r
26      * @return
27      */
28     private static ArrayList<Statement> browseConnectors(ReadGraph g, Resource r) throws DatabaseException {
29         ArrayList<Statement> result = new ArrayList<Statement>(2);
30         StructuralResource2 STR = StructuralResource2.getInstance(g);
31         for(Resource connector : g.getObjects(r, STR.IsConnectedTo))
32             for(Statement other : g.getStatements(connector, STR.Connects))
33                 if(!other.getObject().equals(r))
34                     result.add(other);
35         return result;
36     }
37     
38     private static Resource getJoinedFlag(ReadGraph g, Resource r) throws DatabaseException {
39         DiagramResource DIA = DiagramResource.getInstance(g);
40         for(Resource join : g.getObjects(r, DIA.FlagIsJoinedBy))
41             for(Resource flag : g.getObjects(join, DIA.JoinsFlag))
42                 if(!flag.equals(r))
43                     return flag;
44         return null;
45     }
46     
47     /**
48      * Returns an identifier of the flag or null if the procedure fails.
49      */
50     private static RelativeReference getSimpleFlagIdentifier(ReadGraph g, Resource flag) throws DatabaseException {
51         DiagramResource DIA = DiagramResource.getInstance(g);        
52         if(!g.isInstanceOf(flag, DIA.Flag))
53             return null;
54         ArrayList<Statement> connections = browseConnectors(g, flag);
55         if(connections.size() != 1)
56             return null;        
57         Resource connection = connections.get(0).getObject();
58         ArrayList<Statement> connections2 = browseConnectors(g, connection);
59         for(Statement stat : connections2) {
60             Resource element = stat.getObject();
61             if(!g.isInstanceOf(element, DIA.Flag)) {   
62                 Resource relation = g.getInverse(stat.getPredicate());                
63                 RelativeReference ref = getElementIdentifier(g, element);
64                 if(ref != null) {
65                     Layer0 L0 = Layer0.getInstance(g);
66                     return new RelativeReference(ref.base, ref.path + "#" + 
67                             g.getRelatedValue(relation, L0.HasName) 
68                             );
69                 }
70             }            
71         }
72         return null;
73     }
74     
75     private static RelativeReference getFlagIdentifier(ReadGraph g, Resource flag) throws DatabaseException {
76         RelativeReference ref1 = getSimpleFlagIdentifier(g, flag);
77         if(ref1 == null)
78             return null;
79         Resource otherFlag = getJoinedFlag(g, flag);
80         if(otherFlag == null)
81             return new RelativeReference(ref1.base, "UNJOINED_FLAG|" + ref1.path);
82         else {
83             RelativeReference ref2 = getSimpleFlagIdentifier(g, otherFlag);
84             if(ref2 == null)
85                 return new RelativeReference(ref1.base, "UNJOINED_FLAG|" + ref1.path);
86             return new RelativeReference(ref1.base, "FLAG|" + ref1.path + "|" + ref2.path);
87         }
88     }
89     
90     public static RelativeReference getElementIdentifier(ReadGraph g, Resource element) throws DatabaseException {
91         DiagramResource DIA = DiagramResource.getInstance(g);
92         ModelingResources MOD = ModelingResources.getInstance(g);
93         if(g.isInstanceOf(element, DIA.Flag)) {
94             return getFlagIdentifier(g, element);            
95         }
96         else if(g.isInstanceOf(element, MOD.ReferenceElement)) {
97             Resource parent = g.getPossibleObject(element, MOD.HasParentComponent);
98             if(parent == null)
99                 return null;
100             RelativeReference parentRef = 
101                     RelativeReference.createReference(g, MOD.StructuralModel, parent);
102             if(parentRef == null)
103                 return null;
104             Resource referenceRelation = 
105                     g.getPossibleObject(element, MOD.HasReferenceRelation);
106             if(referenceRelation == null)
107                 return null;
108             Layer0 L0 = Layer0.getInstance(g);
109             return new RelativeReference(parentRef.base, 
110                     "REFERENCE#"+parentRef.path+"#"+
111                     g.getRelatedValue(referenceRelation, L0.HasName));
112         }
113         else {        
114             Resource component = g.getPossibleObject(element, MOD.ElementToComponent);
115             if(component == null)
116                 return null;
117             return RelativeReference.createReference(g, MOD.StructuralModel, component);
118         }        
119     }
120     
121     public static RelativeReference getConnectorIdentifier(ReadGraph g, Resource connector) throws DatabaseException {
122         StructuralResource2 STR = StructuralResource2.getInstance(g);
123         DiagramResource DIA = DiagramResource.getInstance(g);
124         Layer0 L0 = Layer0.getInstance(g);
125         
126         for(Statement stat : g.getStatements(connector, STR.Connects)) {
127             if(!g.isInstanceOf(stat.getObject(), DIA.Connection)) {
128                 RelativeReference ref = getElementIdentifier(g, stat.getObject());
129                 if(ref == null || ref.path == null)
130                     continue;
131                 if(ref.path.contains("#"))
132                     return ref;
133                 else
134                     return new RelativeReference(ref.base, ref.path + "#" + 
135                             g.getRelatedValue(g.getInverse(stat.getPredicate()), L0.HasName));
136             }
137         }
138         return new RelativeReference(null, "UNK");
139     } 
140     
141     private static Resource resolveElementFromComponent(ReadGraph graph, Resource model, String path) throws DatabaseException {
142         Resource component = RelativeReference.resolve(graph, model, path);
143         if(component == null) {
144             System.err.println("Didn't find component " + path);
145             return null;
146         }
147         
148         ModelingResources MOD = ModelingResources.getInstance(graph);
149         Resource element = graph.getPossibleObject(component, MOD.ComponentToElement);
150         if(element == null) {
151             System.err.println("Didn't find element for component " + path);
152             return null;
153         }            
154         return element;
155     }
156     
157     private static ArrayList<Resource> findRelatedFlags(ReadGraph graph, Resource model, String path) throws DatabaseException {
158         ArrayList<Resource> result = new ArrayList<Resource>();
159         String[] parts = path.split("#");
160         Resource element;
161         String attributeName;
162         if(parts[0].equals("REFERENCE")) {
163             element = resolveReference(graph, model, path);
164             attributeName = parts[3];
165         }
166         else {
167             element = resolveElementFromComponent(graph, model, parts[0]);
168             attributeName = parts[1];
169         }
170         if(element == null)
171             return result;
172         StructuralResource2 STR = StructuralResource2.getInstance(graph);
173         DiagramResource DIA = DiagramResource.getInstance(graph);
174         Layer0 L0 = Layer0.getInstance(graph);
175         for(Statement stat : graph.getStatements(element, STR.IsConnectedTo)) {
176             if(attributeName.equals(graph.getRelatedValue(stat.getPredicate(), L0.HasName))) {
177                 Resource connector1 = stat.getObject();
178                 for(Resource connection : graph.getObjects(connector1, STR.Connects)) {
179                     for(Resource connector2 : graph.getObjects(connection, STR.IsConnectedTo))
180                         if(!connector2.equals(connector1)) {
181                             for(Resource flag : graph.getObjects(connector2, STR.Connects)) {
182                                 if(graph.isInstanceOf(flag, DIA.Flag))
183                                     result.add(flag);
184                             }
185                         }
186                 }
187             }
188         }
189         return result;
190     }
191     
192     public static Resource resolveElement(ReadGraph graph, Resource model, String path) throws DatabaseException {
193         String[] parts = path.split("\\|");
194         
195         if(parts[0].equals("UNJOINED_FLAG")) {
196             ArrayList<Resource> flags = findRelatedFlags(graph, model, parts[1]);
197             if(flags.isEmpty()) {
198                 System.err.println("Didn't find any flag " + path);
199                 return null;
200             }
201             // TODO filter multiple found flags
202             return flags.get(0);
203         }
204         else if(parts[0].equals("FLAG")) {
205             ArrayList<Resource> flags = findRelatedFlags(graph, model, parts[1]);
206             if(flags.isEmpty()) {
207                 System.err.println("Didn't find any flag " + path);
208                 return null;
209             }
210             if(flags.size() == 1)
211                 return flags.get(0);
212             THashSet<Resource> flagSet = new THashSet<Resource>(findRelatedFlags(graph, model, parts[2]));
213             DiagramResource DIA = DiagramResource.getInstance(graph);
214             for(Resource f : flags)
215                 for(Resource join : graph.getObjects(f, DIA.FlagIsJoinedBy))
216                     for(Resource otherFlag : graph.getObjects(join, DIA.JoinsFlag))
217                         if(flagSet.contains(otherFlag))
218                             return f;
219             System.err.println("Ambiguous flag reference " + path);
220             return null;
221         }
222         else if(path.startsWith("REFERENCE#")) {
223             return resolveReference(graph, model, path);
224         }
225         else {
226             return resolveElementFromComponent(graph, model, path);
227         }
228     }
229     
230     private static Resource resolveReference(ReadGraph graph, Resource model, String path) throws DatabaseException {
231         String[] parts = path.split("#");
232         Resource component = RelativeReference.resolve(graph, model, parts[1]);
233         if(component == null) {
234             System.err.println("Didn't find component " + path);
235             return null;
236         }
237         
238         ModelingResources MOD = ModelingResources.getInstance(graph);
239         Layer0 L0 = Layer0.getInstance(graph);
240         for(Resource element : graph.getObjects(component, MOD.HasParentComponent_Inverse)) {
241             Resource referenceRelation = graph.getSingleObject(element, MOD.HasReferenceRelation);
242             if(parts[2].equals(graph.getRelatedValue(referenceRelation, L0.HasName)))
243                 return element;
244         }
245
246         System.err.println("Didn't find element for " + path);
247         return null;
248     }
249     
250     public static List<Resource> resolveConnector(ReadGraph g, Resource model,
251             String name) throws DatabaseException {
252         if(name.equals("UNK"))
253             return Collections.emptyList();
254         if(name.startsWith("FLAG|") || name.startsWith("UNKNOWN_FLAG|")) {
255             Resource element = resolveElement(g, model, name);
256             return Arrays.asList(g.getSingleObject(element, 
257                     DiagramResource.getInstance(g).Flag_ConnectionPoint));
258         }
259         String[] parts = name.split("#");
260         Resource element = resolveElement(g, model, parts[0]);
261         if (element == null)
262             return Collections.emptyList();
263         StructuralResource2 STR = StructuralResource2.getInstance(g);
264         Layer0 L0 = Layer0.getInstance(g);
265         ArrayList<Resource> result = new ArrayList<Resource>(2);
266         for(Statement stat : g.getStatements(element, STR.IsConnectedTo))
267             if(g.getRelatedValue(stat.getPredicate(), L0.HasName).equals(parts[1]))
268                 result.add(stat.getObject());
269         return result;
270     }
271     
272 }