Improve PrettyPrintTG performance
[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, token);
74             if (identity == null) {
75                 return null;
76             }
77         }
78         return identity;
79         
80     }
81     
82     public static Identity getIdentity(TransferableGraph1 tg, int resource) {
83         for(Identity id : tg.identities) {
84             if(id.resource == resource) return id;
85         }
86         return null;
87     }
88     
89     public static TIntArrayList getStatements(TransferableGraph1 tg, int resource) {
90         TIntArrayList result = new TIntArrayList();
91         for(int i=0;i<tg.statements.length;i+=4) {
92             if(tg.statements[i] == resource) {
93                 result.add(tg.statements[i+1]);
94                 result.add(tg.statements[i+3]);
95             }
96         }
97         return result;
98     }
99
100     public static Collection<Identity> getChildren2(TransferableGraph1 tg, Identity parent) {
101         return getChildren2(tg, parent.resource);
102     }
103     
104     public static Collection<Identity> getChildren2(TransferableGraph1 tg, int parentResource) {
105         TreeMap<String, Identity> result = new TreeMap<>();
106         for (Identity id : tg.identities) {
107             if (id.definition instanceof Internal) {
108                 Internal internal = (Internal) id.definition;
109                 if (internal.parent == parentResource)
110                     result.put(internal.name, id);
111             }
112         }
113         Identity consistsOf = findExternal(tg, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
114         Identity hasName = findExternal(tg, "http://www.simantics.org/Layer0-1.1/HasName");
115         for (int i = 0; i < tg.statements.length; i += 4) {
116             if (tg.statements[i] == parentResource) {
117                 if (tg.statements[i + 1] == consistsOf.resource) {
118                     Identity identity = getIdentity(tg, tg.statements[i + 3]);
119                     if (identity != null) {
120                         if (identity.definition instanceof Internal) {
121                             Internal internal = (Internal) identity.definition;
122                             result.put(internal.name, identity);
123                         }
124                     } else {
125                         int possibleNameResource = getPossibleObject2(tg, tg.statements[i + 3], hasName);
126                         if (possibleNameResource != NOT_FOUND) {
127                             Value value = findValue(tg, possibleNameResource);
128                             if (value != null) {
129                                 try {
130                                     String name = (String) value.value.getValue(Bindings.STRING);
131                                     result.put(name, new Identity(tg.statements[i + 3], new Internal(tg.statements[i], name)));
132                                 } catch (AdaptException e) {
133                                     e.printStackTrace();
134                                 }
135                             }
136                         }
137                     }
138                 }
139             }
140         }
141         return result.values();
142     }
143
144     /**
145      * This implementation is no longer advised to use because it returns 0 as
146      * NOT_FOUND which is in fact a valid ID for resource in graph
147      */
148     @Deprecated
149     public static Collection<Identity> getChildren(TransferableGraph1 tg, Identity parent) {
150         TreeMap<String,Identity> result = new TreeMap<>();
151         for(Identity id : tg.identities) {
152             if(id.definition instanceof Internal) {
153                 Internal internal = (Internal)id.definition;
154                 if(internal.parent == parent.resource) 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] == parent.resource) {
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 = getPossibleObject(tg, tg.statements[i+3], hasName);
170                         if(possibleNameResource != 0) {
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     public static TIntArrayList getObjects(TransferableGraph1 tg, int subject, Identity predicate) {
189         TIntArrayList result = new TIntArrayList();
190         for(int i=0;i<tg.statements.length;i+=4) {
191             if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
192                 result.add(tg.statements[i+3]);
193             }
194         }
195         return result;
196     }
197     
198     /**
199      * This implementation is no longer advised to use because it returns 0 as
200      * NOT_FOUND which is in fact a valid ID for resource in graph
201      */
202     @Deprecated
203     public static int getPossibleObject(TransferableGraph1 tg, int subject, Identity predicate) {
204         int result = 0;
205         for(int i=0;i<tg.statements.length;i+=4) {
206             if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
207                 if(result != 0 && tg.statements[i+3] != result) return 0;
208                 result = tg.statements[i+3];
209             }
210         }
211         return result;
212     }
213
214     public static final int NOT_FOUND = -2;
215
216     public static int getPossibleObject2(TransferableGraph1 tg, int subject, Identity predicate) {
217         int result = NOT_FOUND;
218         for(int i=0;i<tg.statements.length;i+=4) {
219             if(tg.statements[i] == subject && tg.statements[i+1] == predicate.resource) {
220                 if(result != NOT_FOUND && tg.statements[i+3] != result)
221                     return NOT_FOUND;
222                 result = tg.statements[i+3];
223             }
224         }
225         return result;
226     }
227     
228     /**
229      * @return 0 for presenting not found which is BAD
230      * @see getPossibleObject2
231      */
232     @Deprecated
233     public static int getPossibleObject(TransferableGraph1 tg, Identity subject, String predicate) {
234         Identity p = findExternal(tg, predicate);
235         if(p == null) return 0;
236         return getPossibleObject(tg, subject.resource, p);
237     }
238     
239     public static int getPossibleObject2(TransferableGraph1 tg, Identity subject, String predicate) {
240         Identity p = findExternal(tg, predicate);
241         if (p == null)
242             return NOT_FOUND;
243         return getPossibleObject2(tg, subject.resource, p);
244     }
245
246     public static Map<Identity, String> getNames(TransferableGraph1 tg, Collection<Identity> ids) {
247         Map<Identity, String> result = new HashMap<Identity, String>();
248         for(Identity id : ids) {
249             if(id.definition instanceof Internal) {
250                 Internal internal = (Internal)id.definition;
251                 result.put(id, internal.name);
252             }
253         }
254         return result;
255     }
256
257     public static String getName(TransferableGraph1 tg, Identity id) {
258         return getName(id);
259     }
260
261     public static String getName(Identity id) {
262         if(id.definition instanceof Internal) {
263             Internal internal = (Internal)id.definition;
264             return internal.name;
265         } else if(id.definition instanceof External) {
266             External external = (External)id.definition;
267             return external.name;
268         } else if(id.definition instanceof Root) {
269             Root root = (Root)id.definition;
270             return root.name;
271         } else  {
272             Optional optional = (Optional)id.definition;
273             return optional.name;
274         }
275     }
276
277     public static String getRootType(Identity id) {
278         if(id.definition instanceof Root) {
279             Root root = (Root)id.definition;
280             return root.type;
281         } else  {
282             throw new IllegalArgumentException("Expected root, got " + id);
283         }
284     }
285
286     public static Value findValue(TransferableGraph1 tg, int subject) {
287         for(Value v : tg.values) {
288             if(v.resource == subject) return v;
289         }
290         return null;
291     }
292     
293     public static String getURI(TransferableGraph1 tg, int id) {
294         return getURI(tg.identities, id);
295     }
296     
297     public static String getURI(Identity[] identities, int id) {
298         for(Identity identity : identities) {
299             if(identity.resource == id) {
300                 IdentityDefinition definition = identity.definition;
301                 if(definition instanceof External) {
302                     External def = (External)definition;
303                     if(def.parent == -1) return "http:/";
304                     else return getURI(identities, def.parent) + "/" + def.name;
305                 } else if(definition instanceof Root) {
306                     Root def = (Root)definition;
307                     if(def.name.isEmpty()) return "http:/";
308                     return def.name;
309                 } else if (definition instanceof Internal) {
310                     Internal def = (Internal)definition;
311                     return getURI(identities, def.parent) + "/" + def.name;
312                 } else {
313                     return "";
314                 }
315             }
316         }       
317         return "<internal reference " + id + ">:";
318     }
319
320     public static TIntObjectMap<Identity> mapIdentities(TransferableGraph1 tg) {
321         return mapIdentities(tg.identities);
322     }
323
324     public static TIntObjectMap<Identity> mapIdentities(Identity[] identities) {
325         // Integer.MIN_VALUE cannot be the value of Identity.resource
326         TIntObjectMap<Identity> map = new TIntObjectHashMap<>(identities.length, 0.5f, Integer.MIN_VALUE);
327         for (Identity id : identities)
328             map.put(id.resource, id);
329         return map;
330     }
331
332     public static String getURI(int resourceCount, TIntObjectMap<Identity> identities, int id) {
333         Identity identity = identities.get(id);
334         if(identity != null) {
335             IdentityDefinition definition = identity.definition;
336             if(definition instanceof External) {
337                 External def = (External)definition;
338                 if(def.parent == -1) return "http:/";
339                 else return getURI(resourceCount, identities, def.parent) + "/" + URIStringUtils.escape(def.name);
340             } else if(definition instanceof Root) {
341                 Root def = (Root)definition;
342                 if(def.name.isEmpty()) return "http:/";
343                 return def.name;
344             } else if (definition instanceof Internal) {
345                 Internal def = (Internal)definition;
346                 return getURI(resourceCount, identities, def.parent) + "/" + URIStringUtils.escape(def.name);
347             } else {
348                 return "";
349             }
350         }
351         return "<internal reference " + id + ">:";
352     }
353
354 }