]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CodeGen.java
16af00b30ba0250725ae9d2107bb132d10f56e8f
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / CodeGen.java
1 package org.simantics.db.impl.query;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.UnsupportedEncodingException;
6 import java.net.MalformedURLException;
7 import java.net.URL;
8 import java.net.URLDecoder;
9
10 import org.simantics.db.ObjectResourceIdMap;
11 import org.simantics.utils.FileUtils;
12
13 public class CodeGen {
14         
15         int indent = 4;
16         
17         String[] signatureR1RelationInfo = { "int r", "r", "keyR", "long", "InternalProcedure<RelationInfo>", "entry.id" };
18         String[] signatureR1Bytes = { "int r", "r", "keyR", "long", "InternalProcedure<byte[]>", "entry.id" };
19         String[] signatureR1IntSet = { "int r", "r", "keyR", "long", "InternalProcedure<IntSet>", "entry.id" };
20         String[] signatureR1IP = { "int r", "r", "keyR", "long", "IntProcedure", "entry.id" };
21         String[] signatureR2IP = { "int r1, int r2", "r1,r2", "keyR2", "long", "IntProcedure", "entry.id" };
22         String[] signatureR2TIP = { "int r1, int r2", "r1,r2", "keyR2", "long", "TripleIntProcedure", "entry.id" };
23         String[] signatureID1 = { "String id", "id", "keyID", "String", "InternalProcedure<Integer>", "entry.id" };
24         String[] signatureID2 = { "String id", "id", "keyID", "String", "InternalProcedure<TObjectIntHashMap<String>>", "entry.id" };
25         String[] signatureChildMap = { "int r", "r", "keyR", "long", "InternalProcedure<ObjectResourceIdMap<String>>", "entry.id" };
26         String[] signatureRead = { "Read<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
27         String[] signatureAsyncRead = { "AsyncRead<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
28 <<<<<<< Upstream, based on branch 'private/antti_threads' of ssh://villberg@gerrit.simantics.org:29418/simantics/platform.git
29         String[] signatureMultiRead = { "MultiRead<?> r", "r", "id", "long", "AsyncMultiProcedure", "entry.request" };
30         String[] signatureAsyncMultiRead = { "AsyncMultiRead<?> r", "r", "id", "long", "AsyncMultiProcedure", "entry.request" };
31         String[] signatureExternalRead = { "ExternalRead<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
32
33         private void line(StringBuilder content, String line) {
34                 for(int i=0;i<indent;i++)
35                         content.append(" ");
36                 content.append(line);
37                 content.append("\n");
38         }
39         
40         public void generateQuery(StringBuilder content, String clazz, String[] signature, boolean runnerShortcut, boolean genAsync) {
41                 generateGetOrCreate(content, clazz, signature, genAsync);
42                 generateRemove(content, clazz, signature);
43                 generateRunner(content, clazz, signature, runnerShortcut, genAsync);
44         }
45         
46         public void generateRunner(StringBuilder content, String clazz, String[] signature, boolean shortcut, boolean genAsync) {
47                 
48                 line(content, "public static void runner" + clazz + "(ReadGraphImpl graph, " + signature[0] + ", CacheEntry parent, ListenerBase listener, final " + signature[4] + " procedure" + (genAsync ? ", boolean isSync" : "") + ") throws DatabaseException {");
49                 line(content, "    QueryCache cache  = graph.processor.cache;");
50                 if(shortcut) {
51                         line(content, "    if(parent == null && listener == null && !cache.shouldCache(graph.processor, " + signature[1] + ")) {");
52                         line(content, "        " + clazz + ".computeForEach(graph, " + signature[1] + ", null, procedure);");
53                         line(content, "        return;");
54                         line(content, "    }");
55                 }
56                 line(content, "    " + clazz + " entry = (" + clazz + ")cache.getOrCreate" + clazz + "(graph.processor, " + signature[1] + (genAsync ? ", isSync" : "") + ");");
57                 if(genAsync) {
58                         line(content, "    if(entry == null) {");
59                         line(content, "        graph.processor.schedule(new SessionTask(false) {");
60                         line(content, "            @Override");
61                         line(content, "            public void run(int thread) {");
62                         line(content, "                try {");
63                         line(content, "                    assert(!isSync);");
64                         line(content, "                    runner" + clazz + "(graph, r, parent, listener, procedure, isSync);");
65                         line(content, "                } catch (DatabaseException e) {");
66                         line(content, "                    Logger.defaultLogError(e);");
67                         line(content, "                }");
68                         line(content, "            }");
69                         line(content, "        });");
70                         line(content, "        return;");
71                         line(content, "    }");
72                 }
73                 line(content, "    " + signature[4] + " procedure_ = procedure != null ? procedure : emptyProcedure" + clazz + ";");
74                 line(content, "    ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);");
75                 line(content, "    if(entry.isReady()) entry.performFromCache(graph, procedure_);");
76                 line(content, "    else {");
77                 line(content, "      assert(entry.isPending());");
78                 if(shortcut) line(content, "        " + clazz + ".computeForEach(graph, " + signature[1] + ", entry, procedure_);");
79                 else line(content, "        entry.compute(graph, procedure_);"); 
80                 line(content, "        if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());");
81                 line(content, "    }");
82                 line(content, "}");
83                 line(content, "");
84
85         }
86         
87         public void generateRemove(StringBuilder content, String clazz, String[] signature) {
88
89                 String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
90
91                 line(content, "void remove(" + clazz + " entry) {");
92                 line(content, "    synchronized(" + lower + "Map) {");
93                 line(content, "        " + lower + "Map.remove(" + signature[5] + ");");
94                 line(content, "    }");
95                 line(content, "}");
96                 line(content, "");
97
98         }
99
100         public void generateGetOrCreate(StringBuilder content, String clazz, String[] signature, boolean genAsync) {
101                 
102                 String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
103                 
104                 line(content, "" + clazz + " getOrCreate" + clazz + "(QueryProcessor processor, " + signature[0] + (genAsync ? ", boolean isSync" : "") + ") throws DatabaseException {");
105                 line(content, "    " + clazz + " existing = null;");
106                 line(content, "    synchronized(" + lower + "Map) {");
107                 line(content, "        existing = (" + clazz + ")" + lower + "Map.get(" + signature[1] + ");");
108                 line(content, "        if(existing == null) {");
109                 line(content, "            existing = new " + clazz + "(" + signature[1] + ");");
110                 line(content, "            existing.clearResult(querySupport);");
111                 line(content, "            existing.setPending();");
112                 line(content, "            " + lower + "Map.put(" + signature[2] + "(" + signature[1] + "), existing);");
113                 line(content, "            size++;");
114                 line(content, "            return existing;");
115                 line(content, "        }");
116                 line(content, "        if(existing.requiresComputation()) {");
117                 line(content, "            existing.setPending();");
118                 line(content, "            return existing;");
119                 line(content, "        }");
120                 line(content, "    }");
121                 if(genAsync) {
122                         line(content, "    if(existing.isPending()) {");
123                         line(content, "      if(isSync) waitPending(processor, existing);");
124                         line(content, "      else return null;");
125                         line(content, "    }");
126                 } else {
127                         line(content, "    if(existing.isPending()) waitPending(processor, existing);");
128                 }
129                 line(content, "    return existing;");
130                 line(content, "}");
131                 line(content, "");
132                 
133         }
134         
135         public void generate() {
136
137         URL classLocation = CodeGen.class.getResource(".");
138         if (classLocation != null) {
139             if (classLocation.getProtocol().equals("file")) {
140                 try {
141                     URL resource = new URL(classLocation, ".");
142                     File path = new File(URLDecoder.decode(resource.getPath(), "UTF-8"));
143                     String target = path.getAbsolutePath().replace("\\", "/");
144                     target = target.replace("/bin/", "/src/") + "/QueryCache.java";
145                     System.err.println("target=" + target);
146                     File source = new File(target);
147                     StringBuilder content = new StringBuilder();
148                     content.append("package org.simantics.db.impl.query;\n");
149                     content.append("\n");
150                     
151                     content.append("import org.simantics.db.ObjectResourceIdMap;\n");
152                     content.append("import org.simantics.db.RelationInfo;\n");
153                     content.append("import org.simantics.db.common.utils.Logger;\n");
154                     content.append("import org.simantics.db.exception.DatabaseException;\n");
155                     content.append("import org.simantics.db.impl.graph.ReadGraphImpl;\n");
156                     content.append("import org.simantics.db.impl.procedure.InternalProcedure;\n");
157                     content.append("import org.simantics.db.impl.query.QueryProcessor.SessionTask;\n");
158                     content.append("import org.simantics.db.procedure.AsyncMultiProcedure;\n");
159                     content.append("import org.simantics.db.procedure.AsyncProcedure;\n");
160                     content.append("import org.simantics.db.procedure.ListenerBase;\n");
161                     content.append("import org.simantics.db.request.AsyncMultiRead;\n");
162                     content.append("import org.simantics.db.request.AsyncRead;\n");
163                     content.append("import org.simantics.db.request.ExternalRead;\n");
164                     content.append("import org.simantics.db.request.MultiRead;\n");
165                     content.append("import org.simantics.db.request.Read;\n");
166                     content.append("\n");
167                     content.append("import gnu.trove.map.hash.TObjectIntHashMap;\n");
168 =======
169         String[] signatureMultiRead = { "MultiRead<?> r", "r", "id", "long", "SyncMultiProcedure", "entry.request" };
170         String[] signatureAsyncMultiRead = { "AsyncMultiRead<?> r", "r", "id", "long", "AsyncMultiProcedure", "entry.request" };
171         String[] signatureExternalRead = { "ExternalRead<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
172
173         private void line(StringBuilder content, String line) {
174                 for(int i=0;i<indent;i++)
175                         content.append(" ");
176                 content.append(line);
177                 content.append("\n");
178         }
179         
180         public void generateQuery(StringBuilder content, String clazz, String[] signature, boolean runnerShortcut, boolean genAsync) {
181                 generateGetOrCreate(content, clazz, signature, genAsync);
182                 generateRemove(content, clazz, signature);
183                 generateRunner(content, clazz, signature, runnerShortcut, genAsync);
184         }
185         
186         public void generateRunner(StringBuilder content, String clazz, String[] signature, boolean shortcut, boolean genAsync) {
187                 
188                 line(content, "public static void runner" + clazz + "(ReadGraphImpl graph, " + signature[0] + ", CacheEntry parent, ListenerBase listener, final " + signature[4] + " procedure" + (genAsync ? ", boolean isSync" : "") + ") throws DatabaseException {");
189                 line(content, "    QueryCache cache  = graph.processor.cache;");
190                 if(shortcut) {
191                         line(content, "    if(parent == null && listener == null && !cache.shouldCache(graph.processor, " + signature[1] + ")) {");
192                         line(content, "        " + clazz + ".computeForEach(graph, " + signature[1] + ", null, procedure);");
193                         line(content, "        return;");
194                         line(content, "    }");
195                 }
196                 line(content, "    " + clazz + " entry = (" + clazz + ")cache.getOrCreate" + clazz + "(graph.processor, " + signature[1] + (genAsync ? ", isSync" : "") + ");");
197                 if(genAsync) {
198                         line(content, "    if(entry == null) {");
199                         line(content, "        graph.processor.schedule(new SessionTask(false) {");
200                         line(content, "            @Override");
201                         line(content, "            public void run(int thread) {");
202                         line(content, "                try {");
203                         line(content, "                    assert(!isSync);");
204                         line(content, "                    runner" + clazz + "(graph, r, parent, listener, procedure, isSync);");
205                         line(content, "                } catch (DatabaseException e) {");
206                         line(content, "                    Logger.defaultLogError(e);");
207                         line(content, "                }");
208                         line(content, "            }");
209                         line(content, "        });");
210                         line(content, "        return;");
211                         line(content, "    }");
212                 }
213                 line(content, "    " + signature[4] + " procedure_ = procedure != null ? procedure : emptyProcedure" + clazz + ";");
214                 line(content, "    ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure_, false);");
215                 line(content, "    if(entry.isReady()) entry.performFromCache(graph, procedure_);");
216                 line(content, "    else {");
217                 line(content, "      assert(entry.isPending());");
218                 if(shortcut) line(content, "        " + clazz + ".computeForEach(graph, " + signature[1] + ", entry, procedure_);");
219                 else line(content, "        entry.compute(graph, procedure_);"); 
220                 line(content, "        if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());");
221                 line(content, "    }");
222                 line(content, "}");
223                 line(content, "");
224
225         }
226         
227         public void generateRemove(StringBuilder content, String clazz, String[] signature) {
228
229                 String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
230
231                 line(content, "void remove(" + clazz + " entry) {");
232                 line(content, "    synchronized(" + lower + "Map) {");
233                 line(content, "        " + lower + "Map.remove(" + signature[5] + ");");
234                 line(content, "    }");
235                 line(content, "}");
236                 line(content, "");
237
238         }
239
240         public void generateGetOrCreate(StringBuilder content, String clazz, String[] signature, boolean genAsync) {
241                 
242                 String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
243                 
244                 line(content, "" + clazz + " getOrCreate" + clazz + "(QueryProcessor processor, " + signature[0] + (genAsync ? ", boolean isSync" : "") + ") throws DatabaseException {");
245                 line(content, "    " + clazz + " existing = null;");
246                 line(content, "    synchronized(" + lower + "Map) {");
247                 line(content, "        existing = (" + clazz + ")" + lower + "Map.get(" + signature[1] + ");");
248                 line(content, "        if(existing == null) {");
249                 line(content, "            existing = new " + clazz + "(" + signature[1] + ");");
250                 line(content, "            existing.clearResult(querySupport);");
251                 line(content, "            existing.setPending();");
252                 line(content, "            " + lower + "Map.put(" + signature[2] + "(" + signature[1] + "), existing);");
253                 line(content, "            size++;");
254                 line(content, "            return existing;");
255                 line(content, "        }");
256                 line(content, "        if(existing.requiresComputation()) {");
257                 line(content, "            existing.setPending();");
258                 line(content, "            return existing;");
259                 line(content, "        }");
260                 line(content, "    }");
261                 if(genAsync) {
262                         line(content, "    if(existing.isPending()) {");
263                         line(content, "      if(isSync) waitPending(processor, existing);");
264                         line(content, "      else return null;");
265                         line(content, "    }");
266                 } else {
267                         line(content, "    if(existing.isPending()) waitPending(processor, existing);");
268                 }
269                 line(content, "    return existing;");
270                 line(content, "}");
271                 line(content, "");
272                 
273         }
274         
275         public void generate() {
276
277         URL classLocation = CodeGen.class.getResource(".");
278         if (classLocation != null) {
279             if (classLocation.getProtocol().equals("file")) {
280                 try {
281                     URL resource = new URL(classLocation, ".");
282                     File path = new File(URLDecoder.decode(resource.getPath(), "UTF-8"));
283                     String target = path.getAbsolutePath().replace("\\", "/");
284                     target = target.replace("/bin/", "/src/") + "/QueryCache.java";
285                     System.err.println("target=" + target);
286                     File source = new File(target);
287                     StringBuilder content = new StringBuilder();
288                     content.append("package org.simantics.db.impl.query;\n");
289                     content.append("\n");
290                     
291                     content.append("import org.simantics.db.ObjectResourceIdMap;\n");
292                     content.append("import org.simantics.db.RelationInfo;\n");
293                     content.append("import org.simantics.db.common.utils.Logger;\n");
294                     content.append("import org.simantics.db.exception.DatabaseException;\n");
295                     content.append("import org.simantics.db.impl.graph.ReadGraphImpl;\n");
296                     content.append("import org.simantics.db.impl.procedure.InternalProcedure;\n");
297                     content.append("import org.simantics.db.impl.query.QueryProcessor.SessionTask;\n");
298                     content.append("import org.simantics.db.procedure.AsyncMultiProcedure;\n");
299                     content.append("import org.simantics.db.procedure.AsyncProcedure;\n");
300                     content.append("import org.simantics.db.procedure.ListenerBase;\n");
301                     content.append("import org.simantics.db.procedure.SyncMultiProcedure;\n");
302                     content.append("import org.simantics.db.request.AsyncMultiRead;\n");
303                     content.append("import org.simantics.db.request.AsyncRead;\n");
304                     content.append("import org.simantics.db.request.ExternalRead;\n");
305                     content.append("import org.simantics.db.request.MultiRead;\n");
306                     content.append("import org.simantics.db.request.Read;\n");
307 >>>>>>> 82fa68e Generate parts of db client query code
308                     content.append("\n");
309                     
310                     content.append("public class QueryCache extends QueryCacheBase {\n");                    
311                     content.append("\n");
312                     line(content,"public QueryCache(QuerySupport querySupport, int threads) {");
313                     line(content,"    super(querySupport, threads);");
314                     line(content,"}");
315                     content.append("\n");
316                     
317                     generateQuery(content, "Objects", signatureR2IP, true, false);
318                     generateQuery(content, "Statements", signatureR2TIP, true, false);
319                     generateQuery(content, "DirectObjects", signatureR2IP, true, false);
320                     generateQuery(content, "RelationInfoQuery", signatureR1RelationInfo, true, false);
321                     generateQuery(content, "URIToResource", signatureID1, true, false);
322                     generateQuery(content, "ValueQuery", signatureR1Bytes, true, false);
323                     generateQuery(content, "OrderedSet", signatureR1IP, true, false);
324                     generateQuery(content, "PrincipalTypes", signatureR1IP, true, false);
325                     generateQuery(content, "DirectPredicates", signatureR1IntSet, true, false);
326                     generateQuery(content, "Predicates", signatureR1IntSet, true, false);
327                     generateQuery(content, "ReadEntry", signatureRead, true, true);
328                     generateQuery(content, "AsyncReadEntry", signatureAsyncRead, true, true);
329                     generateQuery(content, "Types", signatureR1IntSet, true, false);
330                     generateQuery(content, "ChildMap", signatureChildMap, true, false);
331                     generateQuery(content, "TypeHierarchy", signatureR1IntSet, true, false);
332                     generateQuery(content, "SuperTypes", signatureR1IntSet, true, false);
333                     generateQuery(content, "SuperRelations", signatureR1IntSet, true, false);
334
335                     generateQuery(content, "AssertedPredicates", signatureR1IP, false, false);
336                     generateQuery(content, "AssertedStatements", signatureR2TIP, false, false);
337                     generateQuery(content, "DirectSuperRelations", signatureR1IP, false, false);
338                     generateQuery(content, "MultiReadEntry", signatureMultiRead, false, false);
339                     generateQuery(content, "AsyncMultiReadEntry", signatureAsyncMultiRead, false, false);
340                     generateQuery(content, "ExternalReadEntry", signatureExternalRead, false, false);
341                     content.append("}\n");
342                     FileUtils.writeFile(source, content.toString().getBytes());
343                 } catch (MalformedURLException e) {
344                     e.printStackTrace();
345                 } catch (UnsupportedEncodingException e) {
346                     e.printStackTrace();
347                 } catch (IOException e) {
348                                         e.printStackTrace();
349                                 }
350             }
351         }
352                 
353         }
354         
355         public static void main(String[] args) {
356                 new CodeGen().generate();
357         }
358         
359 }