Improve PrettyPrintTG performance
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / representation / TransferableGraphQueries.java
1 package org.simantics.graph.representation;
2
3 import java.util.Comparator;
4 import java.util.Set;
5 import java.util.TreeMap;
6 import java.util.TreeSet;
7
8 import gnu.trove.impl.Constants;
9 import gnu.trove.list.array.TIntArrayList;
10 import gnu.trove.map.hash.TIntObjectHashMap;
11 import gnu.trove.map.hash.TObjectIntHashMap;
12 import gnu.trove.procedure.TObjectProcedure;
13
14 public class TransferableGraphQueries {
15
16     private static final int NOT_FOUND = TransferableGraphUtils.NOT_FOUND;
17
18     private final TransferableGraph1 tg;
19
20     private final TIntObjectHashMap<Identity> internalIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
21     private final TIntObjectHashMap<Identity> externalIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
22     private final TIntObjectHashMap<Identity> rootIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
23
24     private final TObjectIntHashMap<String> internalIdentitiesByURI = new TObjectIntHashMap<>();
25     private final TObjectIntHashMap<String> externalIdentitiesByURI = new TObjectIntHashMap<>();
26     private final TObjectIntHashMap<String> rootIdentitiesByURI = new TObjectIntHashMap<>();
27
28     private final TIntObjectHashMap<TIntArrayList> statementsCache = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
29     
30     public TransferableGraphQueries(TransferableGraph1 graph) {
31         this.tg = graph;
32         
33         // Calculate internals
34         initializeIdentities();
35     }
36
37     private void initializeIdentities() {
38         for (Identity identity : tg.identities) {
39             IdentityDefinition definition = identity.definition;
40             if (definition instanceof Internal) {
41                 Internal internal = (Internal) definition;
42                 internalIdentities.put(identity.resource, identity);
43                 internalIdentitiesByURI.put(getURI(identity), identity.resource);
44             } else if (definition instanceof External) {
45                 External external = (External) definition;
46                 externalIdentities.put(identity.resource, identity);
47                 externalIdentitiesByURI.put(getURI(identity), identity.resource);
48             } else if (definition instanceof Root) {
49                 Root root = (Root) definition;
50                 rootIdentities.put(identity.resource, identity);
51                 rootIdentitiesByURI.put(getURI(identity), identity.resource);
52             }
53         }
54     }
55
56     public String getURI(Identity identity) {
57         IdentityDefinition definition = identity.definition;
58         if(definition instanceof External) {
59             External def = (External)definition;
60             if(def.parent == -1) return "http:/";
61             else return getURI(def.parent) + "/" + def.name;
62         } else if(definition instanceof Root) {
63             Root def = (Root)definition;
64             if(def.name.isEmpty()) return "http:/";
65             return def.name;
66         } else if (definition instanceof Internal) {
67             Internal def = (Internal)definition;
68             return getURI(def.parent) + "/" + def.name;
69         } else {
70             return "";
71         }
72     }
73
74     public String getURI(int id) {
75         Identity identity = getIdentity(id);
76         if (identity == null)
77             return "<internal reference " + id + ">:";
78         return getURI(identity);
79     }
80
81     private static final Comparator<Identity> IDENTITY_NAME_COMPARATOR = new Comparator<Identity>() {
82         
83         @Override
84         public int compare(Identity o1, Identity o2) {
85             if (o1.definition instanceof Internal && o2.definition instanceof Internal) {
86                 Internal i1 = (Internal) o1.definition; 
87                 Internal i2 = (Internal) o2.definition;
88                 return i1.name.compareTo(i2.name);
89             } else if (o1.definition instanceof External && o2.definition instanceof External) {
90                 External e1 = (External) o1.definition;
91                 External e2 = (External) o2.definition;
92                 return e1.name.compareTo(e2.name);
93             } else {
94                 throw new IllegalArgumentException(o1 + " " + o2);
95             }
96         }
97     };
98
99     public Set<Identity> getChildren(Identity parent) {
100         TreeSet<Identity> children = new TreeSet<>(IDENTITY_NAME_COMPARATOR);
101         internalIdentities.forEachEntry((resource, identity) -> {
102             Internal internal = (Internal) identity.definition;
103             if (internal.parent == parent.resource)
104                 children.add(identity);
105             return true;
106         });
107         
108         return children;
109     }
110     
111     public Identity findInternalByName(String name) {
112         int internal = internalIdentitiesByURI.get(name);
113         if (internal == NOT_FOUND)
114             return null;
115         return internalIdentities.get(internal);
116     }
117
118     private Identity findExternalByName(String name) {
119         int external = externalIdentitiesByURI.get(name);
120         if (external == NOT_FOUND)
121             return null;
122         return externalIdentities.get(external);
123     }
124
125     private Identity findExternalByNameAndParent(String name, int parent) {
126         Identity external = findExternalByName(name);
127         if (external.resource == parent)
128             return external;
129         return null;
130     }
131
132     public Identity findExternalByURI(String uri) {
133         int v = externalIdentitiesByURI.get(uri);
134         if (v == NOT_FOUND)
135             return null;
136         return externalIdentities.get(v);
137     }
138
139     public Identity findRootByName(String name) {
140         int root = rootIdentitiesByURI.get(name);
141         if (root == NOT_FOUND)
142             return null;
143         return rootIdentities.get(root);
144     }
145     
146     public String getName(Identity identity) {
147         return TransferableGraphUtils.getName(identity);
148     }
149
150     public void forIdentities(TObjectProcedure<Identity> procedure) {
151         for (Identity identity : tg.identities) {
152             if (!procedure.execute(identity)) {
153                 break;
154             }
155         }
156     }
157
158     public Identity getIdentity(int resource) {
159         Identity result = rootIdentities.get(resource);
160         if (result == null)
161             result = externalIdentities.get(resource);
162         if (result == null)
163             result = internalIdentities.get(resource);
164         return result;
165     }
166
167     public Value findValue(int object) {
168         return TransferableGraphUtils.findValue(tg, object);
169     }
170
171     public TreeMap<String, TreeSet<Integer>> sortByPredicateUniqueStatements(int resource) {
172         TreeMap<String, TreeSet<Integer>> results = new TreeMap<>();
173         TIntArrayList statements = getStatements(resource);
174         for (int i = 0; i < statements.size(); i += 2) {
175             int predicate = statements.get(i);
176             String predicateURI = getURI(predicate);
177             TreeSet<Integer> objects = results.get(predicateURI);
178             if (objects == null) {
179                 objects = new TreeSet<>();
180             }
181             objects.add(statements.get(i + 1));
182             results.put(predicateURI, objects);
183         }
184         return results;
185     }
186
187     public TIntArrayList getStatements(int resource) {
188 //        System.out.println("getting statements with " + resource);
189         TIntArrayList statements = statementsCache.get(resource);
190         if (statements == null) {
191             statements = TransferableGraphUtils.getStatements(tg, resource);
192             statementsCache.put(resource, statements);
193         }
194         return statements;
195     }
196
197     public int getPossibleObject(int subject, Identity predicate) {
198         return TransferableGraphUtils.getPossibleObject2(tg, subject, predicate);
199     }
200
201     public TransferableGraph1 getGraph() {
202         return tg;
203     }
204     
205 }