]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CodeGen.java
Generate parts of db client query code
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / CodeGen.java
diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CodeGen.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CodeGen.java
new file mode 100644 (file)
index 0000000..3bceb12
--- /dev/null
@@ -0,0 +1,189 @@
+package org.simantics.db.impl.query;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+
+import org.simantics.utils.FileUtils;
+
+public class CodeGen {
+       
+       int indent = 4;
+       
+
+       
+       String[] signatureR1RelationInfo = { "int r", "r", "keyR", "long", "InternalProcedure<RelationInfo>", "entry.id" };
+       String[] signatureR1Bytes = { "int r", "r", "keyR", "long", "InternalProcedure<byte[]>", "entry.id" };
+       String[] signatureR1IntSet = { "int r", "r", "keyR", "long", "InternalProcedure<IntSet>", "entry.id" };
+       String[] signatureR1IP = { "int r", "r", "keyR", "long", "IntProcedure", "entry.id" };
+       String[] signatureR2IP = { "int r1, int r2", "r1,r2", "keyR2", "long", "IntProcedure", "entry.id" };
+       String[] signatureR2TIP = { "int r1, int r2", "r1,r2", "keyR2", "long", "TripleIntProcedure", "entry.id" };
+       String[] signatureID1 = { "String id", "id", "keyID", "String", "InternalProcedure<Integer>", "entry.id" };
+       String[] signatureID2 = { "String id", "id", "keyID", "String", "InternalProcedure<TObjectIntHashMap<String>>", "entry.id" };
+       String[] signatureRead = { "Read<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
+       String[] signatureAsyncRead = { "AsyncRead<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
+       String[] signatureMultiRead = { "MultiRead<?> r", "r", "id", "long", "AsyncMultiProcedure", "entry.request" };
+       String[] signatureAsyncMultiRead = { "AsyncMultiRead<?> r", "r", "id", "long", "AsyncMultiProcedure", "entry.request" };
+       String[] signatureExternalRead = { "ExternalRead<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
+
+       private void line(StringBuilder content, String line) {
+               for(int i=0;i<indent;i++)
+                       content.append(" ");
+               content.append(line);
+               content.append("\n");
+       }
+       
+       public void generateQuery(StringBuilder content, String clazz, String[] signature, boolean runnerShortcut) {
+               generateGetOrCreate(content, clazz, signature);
+               generateRemove(content, clazz, signature);
+               generateRunner(content, clazz, signature, runnerShortcut);
+       }
+       
+       public void generateRunner(StringBuilder content, String clazz, String[] signature, boolean shortcut) {
+               
+               line(content, "static void runner" + clazz + "(ReadGraphImpl graph, " + signature[0] + ", CacheEntry parent, ListenerBase listener, " + signature[4] + " procedure) throws DatabaseException {");
+               if(shortcut) {
+                       line(content, "    if(parent == null && listener == null) {");
+                       line(content, "        " + clazz + ".computeForEach(graph, " + signature[1] + ", null, procedure);");
+                       line(content, "        return;");
+                       line(content, "    }");
+               }
+               line(content, "    QueryCache cache  = graph.processor.cache;");
+               line(content, "    if(procedure == null) procedure = emptyProcedure" + clazz + ";");
+               line(content, "    " + clazz + " entry = (" + clazz + ")cache.getOrCreate" + clazz + "(" + signature[1] + ");");
+               line(content, "    ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);");
+               line(content, "    if(entry.isReady()) entry.performFromCache(graph, procedure);");
+               line(content, "    else {");
+               if(shortcut) line(content, "        " + clazz + ".computeForEach(graph, " + signature[1] + ", entry, procedure);");
+               else line(content, "        entry.compute(graph, procedure);"); 
+               line(content, "        if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());");
+               line(content, "    }");
+               line(content, "}");
+               line(content, "");
+
+       }
+       
+       public void generateRemove(StringBuilder content, String clazz, String[] signature) {
+
+               String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
+
+               line(content, "void remove(" + clazz + " entry) {");
+               line(content, "    synchronized(" + lower + "Map) {");
+               line(content, "        " + lower + "Map.remove(" + signature[5] + ");");
+               line(content, "    }");
+               line(content, "}");
+               line(content, "");
+
+       }
+
+       public void generateGetOrCreate(StringBuilder content, String clazz, String[] signature) {
+               
+               String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
+               
+               line(content, "" + clazz + " getOrCreate" + clazz + "(" + signature[0] + ") throws DatabaseException {");
+               line(content, "    " + clazz + " existing = null;");
+               line(content, "    synchronized(" + lower + "Map) {");
+               line(content, "        existing = (" + clazz + ")" + lower + "Map.get(" + signature[1] + ");");
+               line(content, "        if(existing == null) {");
+               line(content, "            existing = new " + clazz + "(" + signature[1] + ");");
+               line(content, "            existing.clearResult(querySupport);");
+               line(content, "            existing.setPending();");
+               line(content, "            " + lower + "Map.put(" + signature[2] + "(" + signature[1] + "), existing);");
+               line(content, "            return existing;");
+               line(content, "        }");
+               line(content, "        if(existing.requiresComputation()) {");
+               line(content, "            existing.setPending();");
+               line(content, "            return existing;");
+               line(content, "        }");
+               line(content, "    }");
+               line(content, "    if(existing.isPending()) waitPending(existing);");
+               line(content, "    return existing;");
+               line(content, "}");
+               line(content, "");
+               
+       }
+       
+       public void generate() {
+
+        URL classLocation = CodeGen.class.getResource(".");
+        if (classLocation != null) {
+            if (classLocation.getProtocol().equals("file")) {
+                try {
+                    URL resource = new URL(classLocation, ".");
+                    File path = new File(URLDecoder.decode(resource.getPath(), "UTF-8"));
+                    String target = path.getAbsolutePath().replace("\\", "/");
+                    target = target.replace("/bin/", "/src/") + "/QueryCache.java";
+                    System.err.println("target=" + target);
+                    File source = new File(target);
+                    StringBuilder content = new StringBuilder();
+                    content.append("package org.simantics.db.impl.query;\n");
+                    content.append("\n");
+                    content.append("import org.simantics.db.RelationInfo;\n");
+                    content.append("import org.simantics.db.exception.DatabaseException;\n");
+                    content.append("import org.simantics.db.impl.graph.ReadGraphImpl;\n");
+                    content.append("import org.simantics.db.impl.procedure.InternalProcedure;\n");
+                    content.append("import org.simantics.db.procedure.AsyncMultiProcedure;\n");
+                    content.append("import org.simantics.db.procedure.AsyncProcedure;\n");
+                    content.append("import org.simantics.db.procedure.ListenerBase;\n");
+                    content.append("import org.simantics.db.request.AsyncMultiRead;\n");
+                    content.append("import org.simantics.db.request.AsyncRead;\n");
+                    content.append("import org.simantics.db.request.ExternalRead;\n");
+                    content.append("import org.simantics.db.request.MultiRead;\n");
+                    content.append("import org.simantics.db.request.Read;\n");
+                    content.append("\n");
+                    content.append("import gnu.trove.map.hash.TObjectIntHashMap;\n");
+                    content.append("\n");
+                    
+                    content.append("public class QueryCache extends QueryCacheBase {\n");                    
+                    content.append("\n");
+                    line(content,"public QueryCache(QuerySupport querySupport, int threads) {");
+                    line(content,"    super(querySupport, threads);");
+                    line(content,"}");
+                    content.append("\n");
+                    
+                    generateQuery(content, "Objects", signatureR2IP, true);
+                    generateQuery(content, "Statements", signatureR2TIP, true);
+                    generateQuery(content, "DirectObjects", signatureR2IP, true);
+                    generateQuery(content, "RelationInfoQuery", signatureR1RelationInfo, true);
+                    generateQuery(content, "URIToResource", signatureID1, true);
+                    generateQuery(content, "ValueQuery", signatureR1Bytes, true);
+                    generateQuery(content, "OrderedSet", signatureR1IP, true);
+                    generateQuery(content, "PrincipalTypes", signatureR1IP, true);
+                    generateQuery(content, "DirectPredicates", signatureR1IntSet, true);
+                    generateQuery(content, "Predicates", signatureR1IntSet, true);
+                    generateQuery(content, "ReadEntry", signatureRead, true);
+                    generateQuery(content, "Types", signatureR1IntSet, true);
+
+                    generateQuery(content, "AssertedStatements", signatureR2TIP, false);
+                    generateQuery(content, "NamespaceIndex", signatureID2, false);
+                    generateQuery(content, "AssertedPredicates", signatureR1IP, false);
+                    generateQuery(content, "DirectSuperRelations", signatureR1IP, false);
+                    generateQuery(content, "SuperTypes", signatureR1IntSet, false);
+                    generateQuery(content, "TypeHierarchy", signatureR1IntSet, false);
+                    generateQuery(content, "SuperRelations", signatureR1IntSet, false);
+                    generateQuery(content, "AsyncReadEntry", signatureAsyncRead, false);
+                    generateQuery(content, "MultiReadEntry", signatureMultiRead, false);
+                    generateQuery(content, "AsyncMultiReadEntry", signatureAsyncMultiRead, false);
+                    generateQuery(content, "ExternalReadEntry", signatureExternalRead, false);
+                    content.append("}\n");
+                    FileUtils.writeFile(source, content.toString().getBytes());
+                } catch (MalformedURLException e) {
+                    e.printStackTrace();
+                } catch (UnsupportedEncodingException e) {
+                    e.printStackTrace();
+                } catch (IOException e) {
+                                       e.printStackTrace();
+                               }
+            }
+        }
+               
+       }
+       
+       public static void main(String[] args) {
+               new CodeGen().generate();
+       }
+       
+}