Handle SelectionOutline interface implementation in SCLScenegraph
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / representation / TransferableGraphUtils.java
1 package org.simantics.graph.representation;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashMap;
6 import java.util.Map;
7 import java.util.TreeMap;
8
9 import org.simantics.databoard.Bindings;
10 import org.simantics.databoard.adapter.AdaptException;
11 import org.simantics.databoard.util.URIStringUtils;
12
13 import gnu.trove.list.array.TIntArrayList;
14 import gnu.trove.map.TIntObjectMap;
15 import gnu.trove.map.hash.TIntObjectHashMap;
16
17 public class TransferableGraphUtils {
18
19     public static Collection<Identity> getRoots(TransferableGraph1 tg) {
20         
21         ArrayList<Identity> result = new ArrayList<Identity>();
22         for(Identity id : tg.identities) {
23             if(id.definition instanceof Root) result.add(id);
24         }
25         return result;
26         
27     }
28     
29     public static Identity findRootWithName(TransferableGraph1 tg, String name) {
30         
31         for(Identity id : tg.identities) {
32             if(id.definition instanceof Root) {
33                 Root ext = (Root)id.definition;
34                 if(ext.name.equals(name)) return id;
35             }
36         }
37         return null;
38         
39     }
40
41     public static Identity findExternalWithName(TransferableGraph1 tg, String name) {
42         
43         for(Identity id : tg.identities) {
44             if(id.definition instanceof External) {
45                 External ext = (External)id.definition;
46                 if(ext.name.equals(name)) return id;
47             }
48         }
49         return null;
50         
51     }
52
53     public static Identity findExternalWithNameAndParent(TransferableGraph1 tg, int parent, String name) {
54         
55         for(Identity id : tg.identities) {
56             if(id.definition instanceof External) {
57                 External ext = (External)id.definition;
58                 if(ext.name.equals(name) && ext.parent == parent) return id;
59             }
60         }
61         return null;
62         
63     }
64     
65     public static Identity findExternal(TransferableGraph1 tg, String uri) {
66         
67         Identity identity = findExternalWithName(tg, "http:/");
68         if(identity == null) identity = findExternalWithName(tg, "");
69         if(identity == null) identity = findRootWithName(tg, "");
70         if("http:/".equals(uri)) return identity;
71         String[] tokens = uri.substring("http://".length()).split("/");
72         for(String token : tokens) {
73             identity = findExternalWithNameAndParent(tg, identity.resource, URIStringUtils.unescape(token));
74             if (identity == null) {
75                 return null;
76             }
77         }
78         return identity;
79         
80     }
81
82     /**
83      * Provided a tg and a resource uri, returns the identity of the tg if the uri_ matches the tg exactly
84      * @param tg
85      * @param uri_
86      * @return
87      */
88     public static Identity getIdentity2(TransferableGraph1 tg, String uri_) {
89         Collection<Identity> identities = TransferableGraphUtils.getRoots(tg);
90         for (Identity i : identities) {
91             Identity id = getIdentity2(tg, uri_, i);
92             if (id != null) {
93                 return id;
94             }
95         }
96         return null;
97     }
98
99     /**
100      *
101      * @param tg
102      * @param uri_
103      * @param id
104      * @return
105      */
106     public static Identity getIdentity2(TransferableGraph1 tg, String uri_, Identity id) {
107         String uri = TransferableGraphUtils.getURI(tg, id.resource);
108
109         if (uri_.equals(uri)) {
110             return id;
111         }
112
113         if (uri_.startsWith(uri)) {
114             Collection<Identity> childIdentitiesOfRoot = TransferableGraphUtils.getChildren2(tg, id);
115             for (Identity i2 : childIdentitiesOfRoot) {
116                 Identity id2 = getIdentity2(tg, uri_, i2);
117                 if (id2 != null) {
118                     return id2;
119                 }
120             }
121         }
122
123         return null;
124     }
125
126     public static Identity getIdentity(TransferableGraph1 tg, int resource) {
127         for(Identity id : tg.identities) {
128             if(id.resource == resource) return id;
129         }
130         return null;
131     }
132     
133     public static TIntArrayList getStatements(TransferableGraph1 tg, int resource) {
134         TIntArrayList result = new TIntArrayList();
135         for(int i=0;i<tg.statements.length;i+=4) {
136             if(tg.statements[i] == resource) {
137                 result.add(tg.statements[i+1]);
138                 result.add(tg.statements[i+3]);
139             }
140         }
141         return result;
142     }
143
144     public static Collection<Identity> getChildren2(TransferableGraph1 tg, Identity parent) {
145         return getChildren2(tg, parent.resource);
146     }
147     
148     public static Collection<Identity> getChildren2(TransferableGraph1 tg, int parentResource) {
149         TreeMap<String, Identity> result = new TreeMap<>();
150         for (Identity id : tg.identities) {
151             if (id.definition instanceof Internal) {
152                 Internal internal = (Internal) id.definition;
153                 if (internal.parent == parentResource)
154                     result.put(internal.name, id);
155             }
156         }
157         Identity consistsOf = findExternal(tg, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
158         Identity hasName = findExternal(tg, "http://www.simantics.org/Layer0-1.1/HasName");
159         for (int i = 0; i < tg.statements.length; i += 4) {
160             if (tg.statements[i] == parentResource) {
161                 if (tg.statements[i + 1] == consistsOf.resource) {
162                     Identity identity = getIdentity(tg, tg.statements[i + 3]);
163                     if (identity != null) {
164                         if (identity.definition instanceof Internal) {
165                             Internal internal = (Internal) identity.definition;
166                             result.put(internal.name, identity);
167                         }
168                     } else {
169                         int possibleNameResource = getPossibleObject2(tg, tg.statements[i + 3], hasName);
170                         if (possibleNameResource != NOT_FOUND) {
171                             Value value = findValue(tg, possibleNameResource);
172                             if (value != null) {
173                                 try {
174                                     String name = (String) value.value.getValue(Bindings.STRING);
175                                     result.put(name, new Identity(tg.statements[i + 3], new Internal(tg.statements[i], name)));
176                                 } catch (AdaptException e) {
177                                     e.printStackTrace();
178                                 }
179                             }
180                         }
181                     }
182                 }
183             }
184         }
185         return result.values();
186     }
187
188     /**
189      * This implementation is no longer advised to use because it returns 0 as
190      * NOT_FOUND which is in fact a valid ID for resource in graph
191      */
192     @Deprecated
193     public static Collection<Identity> getChildren(TransferableGraph1 tg, Identity parent) {
194         TreeMap<String,Identity> result = new TreeMap<>();
195         for(Identity id : tg.identities) {
196             if(id.definition instanceof Internal) {
197                 Internal internal = (Internal)id.definition;
198                 if(internal.parent == parent.resource) result.put(internal.name, id);
199             }
200         }
201         Identity consistsOf = findExternal(tg, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
202         Identity hasName = findExternal(tg, "http://www.simantics.org/Layer0-1.1/HasName");
203         for(int i=0;i<tg.statements.length;i+=4) {
204             if(tg.statements[i] == parent.resource) {
205                 if(tg.statements[i+1] == consistsOf.resource) {
206                     Identity identity = getIdentity(tg, tg.statements[i+3]);
207                     if(identity != null) {
208                         if(identity.definition instanceof Internal) {
209                             Internal internal = (Internal)identity.definition;
210                             result.put(internal.name, identity);
211                         }
212                     } else {
213                         int possibleNameResource = getPossibleObject(tg, tg.statements[i+3], hasName);
214                         if(possibleNameResource != 0) {
215                             Value value = findValue(tg, possibleNameResource);
216                             if(value != null) {
217                                 try {
218                                     String name = (String)value.value.getValue(Bindings.STRING);
219                                     result.put(name, new Identity(tg.statements[i+3], new Internal(tg.statements[i], name)));
220                                 } catch (AdaptException e) {
221                                     e.printStackTrace();
222                                 }
223                             }
224                         }
225                     }
226                 }
227             }
228         }
229         return result.values();
230     }
231     
232     public static TIntArrayList getObjects(TransferableGraph1 tg, int subject, Identity predicate) {
233         TIntArrayList result = new TIntArrayList();
234         for(int i=0;i<tg.statements.length;i+=4) {
235             if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
236                 result.add(tg.statements[i+3]);
237             }
238         }
239         return result;
240     }
241     
242     /**
243      * This implementation is no longer advised to use because it returns 0 as
244      * NOT_FOUND which is in fact a valid ID for resource in graph
245      */
246     @Deprecated
247     public static int getPossibleObject(TransferableGraph1 tg, int subject, Identity predicate) {
248         int result = 0;
249         for(int i=0;i<tg.statements.length;i+=4) {
250             if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
251                 if(result != 0 && tg.statements[i+3] != result) return 0;
252                 result = tg.statements[i+3];
253             }
254         }
255         return result;
256     }
257
258     public static final int NOT_FOUND = -2;
259
260     public static int getPossibleObject2(TransferableGraph1 tg, int subject, Identity predicate) {
261         int result = NOT_FOUND;
262         for(int i=0;i<tg.statements.length;i+=4) {
263             if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
264                 if(result != NOT_FOUND && tg.statements[i+3] != result)
265                     return NOT_FOUND;
266                 result = tg.statements[i+3];
267             }
268         }
269         return result;
270     }
271     
272     /**
273      * @return 0 for presenting not found which is BAD
274      * @see getPossibleObject2
275      */
276     @Deprecated
277     public static int getPossibleObject(TransferableGraph1 tg, Identity subject, String predicate) {
278         Identity p = findExternal(tg, predicate);
279         if(p == null) return 0;
280         return getPossibleObject(tg, subject.resource, p);
281     }
282     
283     public static int getPossibleObject2(TransferableGraph1 tg, Identity subject, String predicate) {
284         Identity p = findExternal(tg, predicate);
285         if (p == null)
286             return NOT_FOUND;
287         return getPossibleObject2(tg, subject.resource, p);
288     }
289
290     public static Map<Identity, String> getNames(TransferableGraph1 tg, Collection<Identity> ids) {
291         Map<Identity, String> result = new HashMap<Identity, String>();
292         for(Identity id : ids) {
293             if(id.definition instanceof Internal) {
294                 Internal internal = (Internal)id.definition;
295                 result.put(id, internal.name);
296             }
297         }
298         return result;
299     }
300
301     public static String getName(TransferableGraph1 tg, Identity id) {
302         return getName(id);
303     }
304
305     public static String getName(Identity id) {
306         if(id.definition instanceof Internal) {
307             Internal internal = (Internal)id.definition;
308             return internal.name;
309         } else if(id.definition instanceof External) {
310             External external = (External)id.definition;
311             return external.name;
312         } else if(id.definition instanceof Root) {
313             Root root = (Root)id.definition;
314             return root.name;
315         } else  {
316             Optional optional = (Optional)id.definition;
317             return optional.name;
318         }
319     }
320
321     public static String getRootType(Identity id) {
322         if(id.definition instanceof Root) {
323             Root root = (Root)id.definition;
324             return root.type;
325         } else  {
326             throw new IllegalArgumentException("Expected root, got " + id);
327         }
328     }
329
330     public static Value findValue(TransferableGraph1 tg, int subject) {
331         for(Value v : tg.values) {
332             if(v.resource == subject) return v;
333         }
334         return null;
335     }
336     
337     public static String getURI(TransferableGraph1 tg, int id) {
338         return getURI(tg.identities, id);
339     }
340     
341     public static String getURI(Identity[] identities, int id) {
342         for(Identity identity : identities) {
343             if(identity.resource == id) {
344                 IdentityDefinition definition = identity.definition;
345                 if(definition instanceof External) {
346                     External def = (External)definition;
347                     if(def.parent == -1) return "http:/";
348                     else return getURI(identities, def.parent) + "/" + URIStringUtils.escape(def.name);
349                 } else if(definition instanceof Root) {
350                     Root def = (Root)definition;
351                     if(def.name.isEmpty()) return "http:/";
352                     return def.name;
353                 } else if (definition instanceof Internal) {
354                     Internal def = (Internal)definition;
355                     return getURI(identities, def.parent) + "/" + URIStringUtils.escape(def.name);
356                 } else {
357                     return "";
358                 }
359             }
360         }       
361         return "<internal reference " + id + ">:";
362     }
363
364     public static TIntObjectMap<Identity> mapIdentities(TransferableGraph1 tg) {
365         return mapIdentities(tg.identities);
366     }
367
368     public static TIntObjectMap<Identity> mapIdentities(Identity[] identities) {
369         // Integer.MIN_VALUE cannot be the value of Identity.resource
370         TIntObjectMap<Identity> map = new TIntObjectHashMap<>(identities.length, 0.5f, Integer.MIN_VALUE);
371         for (Identity id : identities)
372             map.put(id.resource, id);
373         return map;
374     }
375
376     public static String getURI(int resourceCount, TIntObjectMap<Identity> identities, int id) {
377         Identity identity = identities.get(id);
378         if(identity != null) {
379             IdentityDefinition definition = identity.definition;
380             if(definition instanceof External) {
381                 External def = (External)definition;
382                 if(def.parent == -1) return "http:/";
383                 else return getURI(resourceCount, identities, def.parent) + "/" + URIStringUtils.escape(def.name);
384             } else if(definition instanceof Root) {
385                 Root def = (Root)definition;
386                 if(def.name.isEmpty()) return "http:/";
387                 return def.name;
388             } else if (definition instanceof Internal) {
389                 Internal def = (Internal)definition;
390                 return getURI(resourceCount, identities, def.parent) + "/" + URIStringUtils.escape(def.name);
391             } else {
392                 return "";
393             }
394         }
395         return "<internal reference " + id + ">:";
396     }
397
398 }