1 package org.simantics.db.impl.query;
4 import java.io.IOException;
5 import java.io.UnsupportedEncodingException;
6 import java.net.MalformedURLException;
8 import java.net.URLDecoder;
10 import org.simantics.db.ObjectResourceIdMap;
11 import org.simantics.utils.FileUtils;
13 public class CodeGen {
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" };
33 private void line(StringBuilder content, String line) {
34 for(int i=0;i<indent;i++)
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);
46 public void generateRunner(StringBuilder content, String clazz, String[] signature, boolean shortcut, boolean genAsync) {
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;");
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;");
56 line(content, " " + clazz + " entry = (" + clazz + ")cache.getOrCreate" + clazz + "(graph.processor, " + signature[1] + (genAsync ? ", isSync" : "") + ");");
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);");
69 line(content, " });");
70 line(content, " return;");
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());");
87 public void generateRemove(StringBuilder content, String clazz, String[] signature) {
89 String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
91 line(content, "void remove(" + clazz + " entry) {");
92 line(content, " synchronized(" + lower + "Map) {");
93 line(content, " " + lower + "Map.remove(" + signature[5] + ");");
100 public void generateGetOrCreate(StringBuilder content, String clazz, String[] signature, boolean genAsync) {
102 String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
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;");
116 line(content, " if(existing.requiresComputation()) {");
117 line(content, " existing.setPending();");
118 line(content, " return existing;");
122 line(content, " if(existing.isPending()) {");
123 line(content, " if(isSync) waitPending(processor, existing);");
124 line(content, " else return null;");
127 line(content, " if(existing.isPending()) waitPending(processor, existing);");
129 line(content, " return existing;");
135 public void generate() {
137 URL classLocation = CodeGen.class.getResource(".");
138 if (classLocation != null) {
139 if (classLocation.getProtocol().equals("file")) {
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");
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");
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" };
173 private void line(StringBuilder content, String line) {
174 for(int i=0;i<indent;i++)
176 content.append(line);
177 content.append("\n");
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);
186 public void generateRunner(StringBuilder content, String clazz, String[] signature, boolean shortcut, boolean genAsync) {
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;");
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;");
196 line(content, " " + clazz + " entry = (" + clazz + ")cache.getOrCreate" + clazz + "(graph.processor, " + signature[1] + (genAsync ? ", isSync" : "") + ");");
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);");
209 line(content, " });");
210 line(content, " return;");
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());");
227 public void generateRemove(StringBuilder content, String clazz, String[] signature) {
229 String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
231 line(content, "void remove(" + clazz + " entry) {");
232 line(content, " synchronized(" + lower + "Map) {");
233 line(content, " " + lower + "Map.remove(" + signature[5] + ");");
240 public void generateGetOrCreate(StringBuilder content, String clazz, String[] signature, boolean genAsync) {
242 String lower = Character.toLowerCase(clazz.charAt(0)) + clazz.substring(1);
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;");
256 line(content, " if(existing.requiresComputation()) {");
257 line(content, " existing.setPending();");
258 line(content, " return existing;");
262 line(content, " if(existing.isPending()) {");
263 line(content, " if(isSync) waitPending(processor, existing);");
264 line(content, " else return null;");
267 line(content, " if(existing.isPending()) waitPending(processor, existing);");
269 line(content, " return existing;");
275 public void generate() {
277 URL classLocation = CodeGen.class.getResource(".");
278 if (classLocation != null) {
279 if (classLocation.getProtocol().equals("file")) {
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");
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");
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);");
315 content.append("\n");
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);
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) {
345 } catch (UnsupportedEncodingException e) {
347 } catch (IOException e) {
355 public static void main(String[] args) {
356 new CodeGen().generate();