Merge "All tgs do not reference L0.ConsistsOf and L0.HasName"
[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         if(consistsOf != null && hasName != null) {
160             for (int i = 0; i < tg.statements.length; i += 4) {
161                 if (tg.statements[i] == parentResource) {
162                     if (tg.statements[i + 1] == consistsOf.resource) {
163                         Identity identity = getIdentity(tg, tg.statements[i + 3]);
164                         if (identity != null) {
165                             if (identity.definition instanceof Internal) {
166                                 Internal internal = (Internal) identity.definition;
167                                 result.put(internal.name, identity);
168                             }
169                         } else {
170                             int possibleNameResource = getPossibleObject2(tg, tg.statements[i + 3], hasName);
171                             if (possibleNameResource != NOT_FOUND) {
172                                 Value value = findValue(tg, possibleNameResource);
173                                 if (value != null) {
174                                     try {
175                                         String name = (String) value.value.getValue(Bindings.STRING);
176                                         result.put(name, new Identity(tg.statements[i + 3], new Internal(tg.statements[i], name)));
177                                     } catch (AdaptException e) {
178                                         e.printStackTrace();
179                                     }
180                                 }
181                             }
182                         }
183                     }
184                 }
185             }
186         }
187         return result.values();
188     }
189
190     /**
191      * This implementation is no longer advised to use because it returns 0 as
192      * NOT_FOUND which is in fact a valid ID for resource in graph
193      */
194     @Deprecated
195     public static Collection<Identity> getChildren(TransferableGraph1 tg, Identity parent) {
196         TreeMap<String,Identity> result = new TreeMap<>();
197         for(Identity id : tg.identities) {
198             if(id.definition instanceof Internal) {
199                 Internal internal = (Internal)id.definition;
200                 if(internal.parent == parent.resource) result.put(internal.name, id);
201             }
202         }
203         Identity consistsOf = findExternal(tg, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
204         Identity hasName = findExternal(tg, "http://www.simantics.org/Layer0-1.1/HasName");
205         for(int i=0;i<tg.statements.length;i+=4) {
206             if(tg.statements[i] == parent.resource) {
207                 if(tg.statements[i+1] == consistsOf.resource) {
208                     Identity identity = getIdentity(tg, tg.statements[i+3]);
209                     if(identity != null) {
210                         if(identity.definition instanceof Internal) {
211                             Internal internal = (Internal)identity.definition;
212                             result.put(internal.name, identity);
213                         }
214                     } else {
215                         int possibleNameResource = getPossibleObject(tg, tg.statements[i+3], hasName);
216                         if(possibleNameResource != 0) {
217                             Value value = findValue(tg, possibleNameResource);
218                             if(value != null) {
219                                 try {
220                                     String name = (String)value.value.getValue(Bindings.STRING);
221                                     result.put(name, new Identity(tg.statements[i+3], new Internal(tg.statements[i], name)));
222                                 } catch (AdaptException e) {
223                                     e.printStackTrace();
224                                 }
225                             }
226                         }
227                     }
228                 }
229             }
230         }
231         return result.values();
232     }
233     
234     public static TIntArrayList getObjects(TransferableGraph1 tg, int subject, Identity predicate) {
235         TIntArrayList result = new TIntArrayList();
236         for(int i=0;i<tg.statements.length;i+=4) {
237             if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
238                 result.add(tg.statements[i+3]);
239             }
240         }
241         return result;
242     }
243     
244     /**
245      * This implementation is no longer advised to use because it returns 0 as
246      * NOT_FOUND which is in fact a valid ID for resource in graph
247      */
248     @Deprecated
249     public static int getPossibleObject(TransferableGraph1 tg, int subject, Identity predicate) {
250         int result = 0;
251         for(int i=0;i<tg.statements.length;i+=4) {
252             if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
253                 if(result != 0 && tg.statements[i+3] != result) return 0;
254                 result = tg.statements[i+3];
255             }
256         }
257         return result;
258     }
259
260     public static final int NOT_FOUND = -2;
261
262     public static int getPossibleObject2(TransferableGraph1 tg, int subject, Identity predicate) {
263         int result = NOT_FOUND;
264         for(int i=0;i<tg.statements.length;i+=4) {
265             if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
266                 if(result != NOT_FOUND && tg.statements[i+3] != result)
267                     return NOT_FOUND;
268                 result = tg.statements[i+3];
269             }
270         }
271         return result;
272     }
273     
274     /**
275      * @return 0 for presenting not found which is BAD
276      * @see getPossibleObject2
277      */
278     @Deprecated
279     public static int getPossibleObject(TransferableGraph1 tg, Identity subject, String predicate) {
280         Identity p = findExternal(tg, predicate);
281         if(p == null) return 0;
282         return getPossibleObject(tg, subject.resource, p);
283     }
284     
285     public static int getPossibleObject2(TransferableGraph1 tg, Identity subject, String predicate) {
286         Identity p = findExternal(tg, predicate);
287         if (p == null)
288             return NOT_FOUND;
289         return getPossibleObject2(tg, subject.resource, p);
290     }
291
292     public static Map<Identity, String> getNames(TransferableGraph1 tg, Collection<Identity> ids) {
293         Map<Identity, String> result = new HashMap<Identity, String>();
294         for(Identity id : ids) {
295             if(id.definition instanceof Internal) {
296                 Internal internal = (Internal)id.definition;
297                 result.put(id, internal.name);
298             }
299         }
300         return result;
301     }
302
303     public static String getName(TransferableGraph1 tg, Identity id) {
304         return getName(id);
305     }
306
307     public static String getName(Identity id) {
308         if(id.definition instanceof Internal) {
309             Internal internal = (Internal)id.definition;
310             return internal.name;
311         } else if(id.definition instanceof External) {
312             External external = (External)id.definition;
313             return external.name;
314         } else if(id.definition instanceof Root) {
315             Root root = (Root)id.definition;
316             return root.name;
317         } else  {
318             Optional optional = (Optional)id.definition;
319             return optional.name;
320         }
321     }
322
323     public static String getRootType(Identity id) {
324         if(id.definition instanceof Root) {
325             Root root = (Root)id.definition;
326             return root.type;
327         } else  {
328             throw new IllegalArgumentException("Expected root, got " + id);
329         }
330     }
331
332     public static Value findValue(TransferableGraph1 tg, int subject) {
333         for(Value v : tg.values) {
334             if(v.resource == subject) return v;
335         }
336         return null;
337     }
338     
339     public static String getURI(TransferableGraph1 tg, int id) {
340         return getURI(tg.identities, id);
341     }
342     
343     public static String getURI(Identity[] identities, int id) {
344         for(Identity identity : identities) {
345             if(identity.resource == id) {
346                 IdentityDefinition definition = identity.definition;
347                 if(definition instanceof External) {
348                     External def = (External)definition;
349                     if(def.parent == -1) return "http:/";
350                     else return getURI(identities, def.parent) + "/" + URIStringUtils.escape(def.name);
351                 } else if(definition instanceof Root) {
352                     Root def = (Root)definition;
353                     if(def.name.isEmpty()) return "http:/";
354                     return def.name;
355                 } else if (definition instanceof Internal) {
356                     Internal def = (Internal)definition;
357                     return getURI(identities, def.parent) + "/" + URIStringUtils.escape(def.name);
358                 } else {
359                     return "";
360                 }
361             }
362         }       
363         return "<internal reference " + id + ">:";
364     }
365
366     public static TIntObjectMap<Identity> mapIdentities(TransferableGraph1 tg) {
367         return mapIdentities(tg.identities);
368     }
369
370     public static TIntObjectMap<Identity> mapIdentities(Identity[] identities) {
371         // Integer.MIN_VALUE cannot be the value of Identity.resource
372         TIntObjectMap<Identity> map = new TIntObjectHashMap<>(identities.length, 0.5f, Integer.MIN_VALUE);
373         for (Identity id : identities)
374             map.put(id.resource, id);
375         return map;
376     }
377
378     public static String getURI(int resourceCount, TIntObjectMap<Identity> identities, int id) {
379         Identity identity = identities.get(id);
380         if(identity != null) {
381             IdentityDefinition definition = identity.definition;
382             if(definition instanceof External) {
383                 External def = (External)definition;
384                 if(def.parent == -1) return "http:/";
385                 else return getURI(resourceCount, identities, def.parent) + "/" + URIStringUtils.escape(def.name);
386             } else if(definition instanceof Root) {
387                 Root def = (Root)definition;
388                 if(def.name.isEmpty()) return "http:/";
389                 return def.name;
390             } else if (definition instanceof Internal) {
391                 Internal def = (Internal)definition;
392                 return getURI(resourceCount, identities, def.parent) + "/" + URIStringUtils.escape(def.name);
393             } else {
394                 return "";
395             }
396         }
397         return "<internal reference " + id + ">:";
398     }
399
400 }