JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
BuildComposablePipeline.java
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3 * Copyright (c) 2010 JogAmp Community. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * - Redistribution of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * - Redistribution in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of Sun Microsystems, Inc. or the names of
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * This software is provided "AS IS," without a warranty of any kind. ALL
21 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
22 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
23 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
24 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
25 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
26 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
27 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
28 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
29 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
30 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
31 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32 *
33 * You acknowledge that this software is not designed or intended for use
34 * in the design, construction, operation or maintenance of any nuclear
35 * facility.
36 *
37 * Sun gratefully acknowledges that this software was originally authored
38 * and developed by Kenneth Bradley Russell and Christopher John Kline.
39 */
40package com.jogamp.gluegen.opengl;
41
42import com.jogamp.gluegen.CodeGenUtils;
43import com.jogamp.gluegen.JavaType;
44
45import java.io.BufferedWriter;
46import java.io.File;
47import java.io.FileWriter;
48import java.io.IOException;
49import java.io.PrintWriter;
50import java.lang.reflect.Method;
51import java.nio.Buffer;
52import java.util.ArrayList;
53import java.util.Arrays;
54import java.util.Collections;
55import java.util.Comparator;
56import java.util.HashMap;
57import java.util.HashSet;
58import java.util.Iterator;
59import java.util.List;
60import java.util.Set;
61
63
64 /** <p>Default: true</p>. */
65 public static final int GEN_DEBUG = 1 << 0;
66 /** <p>Default: true</p>. */
67 public static final int GEN_TRACE = 1 << 1;
68 /** <p>Default: false</p>. */
69 public static final int GEN_CUSTOM = 1 << 2;
70 /**
71 * By extra command-line argument: <code>prolog_xor_downstream</code>.
72 * <p>
73 * If true, either prolog (if exist) is called or downstream's method, but not both.
74 * By default, both methods would be called.
75 * </p>
76 * <p>Default: false</p>
77 */
78 public static final int GEN_PROLOG_XOR_DOWNSTREAM = 1 << 3;
79 /**
80 * By extra command-line argument: <code>gl_identity_by_assignable_class</code>.
81 * <p>
82 * If true, implementation does not utilize downstream's <code>isGL*()</code>
83 * implementation, but determines whether the GL profile is matched by interface inheritance.
84 * </p>
85 * <p>Default: false</p>
86 */
87 public static final int GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS = 1 << 4;
88
89 private static final HashMap<String, String> addedGLHooks = new HashMap<String, String>();
90 private static final String[] addedGLHookMethodNames = new String[] {
91 "mapBuffer", "mapBufferRange",
92 "mapNamedBuffer", "mapNamedBufferRange" };
93 static {
94 for(int i=0; i<addedGLHookMethodNames.length; i++) {
95 addedGLHooks.put(addedGLHookMethodNames[i], addedGLHookMethodNames[i]);
96 }
97 }
98
99 int mode;
100 private final String outputDir;
101 private final String outputPackage;
102 private final String outputName;
103 private final Class<?> classToComposeAround;
104 private final Class<?> classPrologOpt;
105 private final Class<?> classDownstream;
106 // Only desktop OpenGL has immediate mode glBegin / glEnd
107 private boolean hasImmediateMode;
108 // Desktop OpenGL and GLES1 have GL_STACK_OVERFLOW and GL_STACK_UNDERFLOW errors
109 private boolean hasGL2ES1StackOverflow;
110
111 public static Class<?> getClass(final String name) {
112 Class<?> clazz = null;
113 try {
114 clazz = Class.forName(name);
115 } catch (final Exception e) {
116 throw new RuntimeException(
117 "Could not find class \"" + name + "\"", e);
118 }
119 return clazz;
120 }
121
122 public static Method getMethod(final Class<?> clazz, final Method m) {
123 Method res = null;
124 try {
125 res = clazz.getMethod(m.getName(), m.getParameterTypes());
126 } catch (final Exception e) {
127 }
128 return res;
129 }
130
131 public static void main(final String[] args) {
132 final String classToComposeAroundName = args[0];
133 Class<?> classPrologOpt, classDownstream;
134 final Class<?> classToComposeAround = getClass(classToComposeAroundName);
135
136 final String outputDir = args[1];
137 String outputPackage, outputName;
138 int mode;
139
140 if (args.length > 2) {
141 final String outputClazzName = args[2];
142 outputPackage = getPackageName(outputClazzName);
143 outputName = getBaseClassName(outputClazzName);
144 classPrologOpt = getClass(args[3]);
145 classDownstream = getClass(args[4]);
146 mode = GEN_CUSTOM;
147 if (args.length > 5) {
148 for(int i=5; i<args.length; i++) {
149 if (args[i].equals("prolog_xor_downstream")) {
151 } else if (args[i].equals("gl_identity_by_assignable_class")) {
153 }
154 }
155 }
156 } else {
157 outputPackage = getPackageName(classToComposeAroundName);
158 outputName = null; // TBD ..
159 classPrologOpt = null;
160 classDownstream = classToComposeAround;
161 mode = GEN_DEBUG | GEN_TRACE ;
162 }
163
164 final BuildComposablePipeline composer =
165 new BuildComposablePipeline(mode, outputDir, outputPackage, outputName, classToComposeAround, classPrologOpt, classDownstream);
166
167 try {
168 composer.emit();
169 } catch (final IOException e) {
170 throw new RuntimeException(
171 "Error generating composable pipeline source files", e);
172 }
173 }
174
175 protected BuildComposablePipeline(final int mode, final String outputDir, final String outputPackage, final String outputName,
176 final Class<?> classToComposeAround, final Class<?> classPrologOpt, final Class<?> classDownstream) {
177 this.mode = mode;
178 this.outputDir = outputDir;
179 this.outputPackage = outputPackage;
180 this.outputName = outputName;
181 this.classToComposeAround = classToComposeAround;
182 this.classPrologOpt = classPrologOpt;
183 this.classDownstream = classDownstream;
184
185 if (!classToComposeAround.isInterface()) {
186 throw new IllegalArgumentException(
187 classToComposeAround.getName() + " is not an interface class");
188 }
189
190 try {
191 // Keep assignment w/ null comparison for clarification.
192 // If no exception is thrown, return value is always non-null;
193 hasImmediateMode =
194 null != classToComposeAround.getMethod("glBegin", new Class<?>[]{Integer.TYPE});
195 } catch (final Exception e) {
196 }
197
198 try {
199 hasGL2ES1StackOverflow = hasImmediateMode &&
200 (classToComposeAround.getField("GL_STACK_OVERFLOW") != null);
201 } catch (final Exception e) {
202 }
203 }
204
205 /**
206 * Emit the java source code for the classes that comprise the composable
207 * pipeline.
208 */
209 public void emit() throws IOException {
210
211 final List<Method> publicMethodsRaw = Arrays.asList(classToComposeAround.getMethods());
212
213 final Set<PlainMethod> publicMethodsPlainSet = new HashSet<PlainMethod>();
214 for (final Iterator<Method> iter = publicMethodsRaw.iterator(); iter.hasNext();) {
215 final Method method = iter.next();
216 // Don't hook methods which aren't real GL methods,
217 // such as the synthetic "isGL2ES2" "getGL2ES2"
218 final String name = method.getName();
219 if ( !name.equals("getDownstreamGL") &&
220 !name.equals("toString") ) {
221 final boolean syntheticIsGL = name.startsWith("isGL");
222 final boolean syntheticGetGL = name.startsWith("getGL");
223 final boolean runHooks = name.startsWith("gl") || syntheticIsGL || syntheticGetGL || addedGLHooks.containsKey(name);
224 publicMethodsPlainSet.add(new PlainMethod(method, runHooks, syntheticIsGL, syntheticGetGL));
225 }
226 }
227
228 // sort methods to make them easier to find
229 final List<PlainMethod> publicMethodsPlainSorted = new ArrayList<PlainMethod>();
230 publicMethodsPlainSorted.addAll(publicMethodsPlainSet);
231 Collections.sort(publicMethodsPlainSorted, new Comparator<PlainMethod>() {
232 @Override
233 public int compare(final PlainMethod o1, final PlainMethod o2) {
234 return o1.getWrappedMethod().getName().compareTo(o2.getWrappedMethod().getName());
235 }
236 });
237
238 if (0 != (mode & GEN_DEBUG)) {
239 (new DebugPipeline(outputDir, outputPackage, classToComposeAround, classDownstream)).emit(publicMethodsPlainSorted.iterator());
240 }
241 if (0 != (mode & GEN_TRACE)) {
242 (new TracePipeline(outputDir, outputPackage, classToComposeAround, classDownstream)).emit(publicMethodsPlainSorted.iterator());
243 }
244 if (0 != (mode & GEN_CUSTOM)) {
245 (new CustomPipeline(mode, outputDir, outputPackage, outputName, classToComposeAround, classPrologOpt, classDownstream)).emit(publicMethodsPlainSorted.iterator());
246 }
247 }
248
249 public static String getPackageName(final String clazzName) {
250 final int lastDot = clazzName.lastIndexOf('.');
251 if (lastDot == -1) {
252 // no package, class is at root level
253 return null;
254 }
255 return clazzName.substring(0, lastDot);
256 }
257
258 public static String getBaseClassName(final String clazzName) {
259 final int lastDot = clazzName.lastIndexOf('.');
260 if (lastDot == -1) {
261 // no package, class is at root level
262 return clazzName;
263 }
264 return clazzName.substring(lastDot + 1);
265 }
266
267 //-------------------------------------------------------
268 protected static class PlainMethod {
269
270 final Method m;
271 final boolean runHooks;
272 final boolean isSynthethicIsGL;
273 final boolean isSynthethicGetGL;
274
275 PlainMethod(final Method m, final boolean runHooks, final boolean isSynthethicIsGL, final boolean isSynthethicGetGL) {
276 this.m = m;
277 this.runHooks = runHooks;
278 this.isSynthethicIsGL = isSynthethicIsGL;
279 this.isSynthethicGetGL = isSynthethicGetGL;
280 }
281
282 public Method getWrappedMethod() {
283 return m;
284 }
285
286 public boolean runHooks() {
287 return runHooks;
288 }
289
290 public boolean isSynthetic() { return isSynthethicIsGL || isSynthethicGetGL; }
291 public boolean isSyntheticIsGL() { return isSynthethicIsGL; }
292 public boolean isSyntheticGetGL() { return isSynthethicGetGL; }
293
294 @Override
295 public boolean equals(final Object obj) {
296 if (obj instanceof PlainMethod) {
297 final PlainMethod b = (PlainMethod) obj;
298 final boolean res =
299 m.getName().equals(b.m.getName())
300 && m.getModifiers() == b.m.getModifiers()
301 && m.getReturnType().equals(b.m.getReturnType())
302 && Arrays.equals(m.getParameterTypes(), b.m.getParameterTypes());
303 return res;
304 }
305 return false;
306 }
307
308 @Override
309 public int hashCode() {
310 int hash = m.getName().hashCode() ^ m.getModifiers() ^ m.getReturnType().hashCode();
311 final Class<?>[] args = m.getParameterTypes();
312 for (int i = 0; i < args.length; i++) {
313 hash ^= args[i].hashCode();
314 }
315 return hash;
316 }
317
318 @Override
319 public String toString() {
320 final Class<?>[] args = m.getParameterTypes();
321 final StringBuilder argsString = new StringBuilder();
322 argsString.append("(");
323 for (int i = 0; i < args.length; i++) {
324 if (i > 0) {
325 argsString.append(", ");
326 }
327 argsString.append(args[i].getName());
328 }
329 argsString.append(")");
330 return m.toString()
331 + "\n\tname: " + m.getName()
332 + "\n\tsynt: isGL " + isSynthethicIsGL+", getGL "+isSynthethicGetGL
333 + "\n\tmods: " + m.getModifiers()
334 + "\n\tretu: " + m.getReturnType()
335 + "\n\targs[" + args.length + "]: " + argsString.toString();
336 }
337 }
338
339 /**
340 * Emits a Java source file that represents one element of the composable
341 * pipeline.
342 */
343 protected abstract class PipelineEmitter {
344
345 private File file;
346 protected String basePackage;
347 protected String baseName; // does not include package!
348 protected String downstreamPackage;
349 protected String downstreamName; // does not include package!
350 protected String prologPackageOpt = null;
351 protected String prologNameOpt = null; // does not include package!
352 protected String outputDir;
353 protected String outputPackage;
354 protected Class<?> baseInterfaceClass;
355 protected Class<?> prologClassOpt = null;
356 protected Class<?> downstreamClass;
357
358 /**
359 * @param outputDir the directory into which the pipeline classes will be
360 * generated.
361 * @param baseInterfaceClassName the full class name (including package,
362 * e.g. "java.lang.String") of the interface that the pipeline wraps
363 * @exception IllegalArgumentException if classToComposeAround is not an
364 * interface.
365 */
366 PipelineEmitter(final String outputDir, final String outputPackage, final Class<?> baseInterfaceClass, final Class<?> prologClassOpt, final Class<?> downstreamClass) {
367 this.outputDir = outputDir;
368 this.outputPackage = outputPackage;
369 this.baseInterfaceClass = baseInterfaceClass;
370 this.prologClassOpt = prologClassOpt;
371 this.downstreamClass = downstreamClass;
372
377 if (null != prologClassOpt) {
380 }
381 }
382
383 public void emit(final Iterator<PlainMethod> methodsToWrap) throws IOException {
384 final String outputClassName = getOutputName();
385 this.file = new File(outputDir + File.separatorChar + outputClassName + ".java");
386 final String parentDir = file.getParent();
387 if (parentDir != null) {
388 final File pDirFile = new File(parentDir);
389 pDirFile.mkdirs();
390 }
391
392 final PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(file)));
393
394 final HashSet<Class<?>> importClazzList = new HashSet<Class<?>>();
395 importClazzList.add(baseInterfaceClass);
396 final String[] ifNames = new String[] { baseInterfaceClass.getName() };
397
398 final List<Class<?>> baseInterfaces = Arrays.asList(baseInterfaceClass.getInterfaces());
399 importClazzList.addAll(baseInterfaces);
400
401 importClazzList.add(downstreamClass);
402 if (null != prologClassOpt) {
403 importClazzList.add(prologClassOpt);
404 }
405
406 final ArrayList<String> imports = new ArrayList<String>();
407 imports.add("java.io.*");
408 imports.add("com.jogamp.opengl.*");
409 imports.add("com.jogamp.gluegen.runtime.*");
410 imports.add(Buffer.class.getPackage().getName()+".*");
411 for (final Class<?> clasS : importClazzList) {
412 imports.add(clasS.getName());
413 }
414
415 CodeGenUtils.emitJavaHeaders(output,
417 outputClassName,
418 true,
419 imports,
420 new String[]{"public"},
421 ifNames,
422 null,
423 new CodeGenUtils.EmissionCallback() {
424 @Override
425 public void emit(final PrintWriter w) {
427 }
428 });
429
430 preMethodEmissionHook(output);
431
432 constructorHook(output);
433
435
436 while (methodsToWrap.hasNext()) {
437 final PlainMethod pm = methodsToWrap.next();
438 final Method m = pm.getWrappedMethod();
439 emitMethodDocComment(output, m);
440 emitSignature(output, m);
441 emitBody(output, pm);
442 }
443
445
446 output.println();
447 output.print(" private " + downstreamName + " " + getDownstreamObjectName() + ";");
448
449 // end the class
450 output.println();
451 output.print("} // end class ");
452 output.println(outputClassName);
453
454 output.flush();
455 output.close();
456
457 System.out.println("wrote to file: " + file);
458 }
459
460 /** Get the name of the object through which API calls should be routed. */
461 protected String getDownstreamObjectName() {
462 return "downstream" + downstreamName;
463 }
464
465 /** Get the name of the object which shall be called as a prolog. */
466 protected String getPrologObjectNameOpt() {
467 if (null != prologNameOpt) {
468 return "prolog" + prologNameOpt;
469 }
470 return null;
471 }
472
473 protected void emitMethodDocComment(final PrintWriter output, final Method m) {
474 }
475
476 protected void emitSignature(final PrintWriter output, final Method m) {
477 output.format(" @Override%n public %s %s(%s)%n",
478 JavaType.createForClass(m.getReturnType()).getName(),
479 m.getName(),
480 getArgListAsString(m, true, true));
481 }
482
483 protected void emitBody(final PrintWriter output, final PlainMethod pm) {
484 final boolean runHooks = pm.runHooks();
485 final Method m = pm.getWrappedMethod();
486 output.println(" {");
487 final Class<?> retType = m.getReturnType();
488
489 final boolean callPreDownstreamHook = runHooks && hasPreDownstreamCallHook(pm);
490 final boolean callPostDownstreamHook = runHooks && hasPostDownstreamCallHook(pm);
491 final boolean callDownstream = (null != getMethod(downstreamClass, m))
492 && !(0 != (GEN_PROLOG_XOR_DOWNSTREAM & getMode()) && callPreDownstreamHook);
493 final boolean hasResult = (retType != Void.TYPE);
494
495 if (!callDownstream) {
496 if (!emptyDownstreamAllowed()) {
497 throw new RuntimeException("Method " + m + " has no downstream (" + downstreamName + ")");
498 }
499 }
500
501 if (!callPreDownstreamHook && !callPostDownstreamHook && !callDownstream) {
502 if (!emptyMethodAllowed()) {
503 throw new RuntimeException("Method " + m + " is empty, no downstream (" + downstreamName + ") nor prolog (" + prologNameOpt + ").");
504 } else {
505 output.print(" if(DEBUG) { System.out.println(\"WARNING: No prolog, no downstream, empty: \"+");
506 printFunctionCallString(output, m);
507 output.println("); } ");
508 }
509 }
510
511 if (callPreDownstreamHook) {
512 if (hasResult && !callDownstream) {
513 if (callPostDownstreamHook) {
514 output.print(" " + JavaType.createForClass(retType).getName());
515 output.print(" _res = ");
516 } else {
517 output.print(" return ");
518 }
519 }
520 preDownstreamCallHook(output, pm);
521 }
522
523 if (callDownstream) {
524 if( pm.isSyntheticIsGL() ) {
525 emitGLIsMethodBody(output, pm);
526 } else if( pm.isSyntheticGetGL() ) {
527 emitGLGetMethodBody(output, pm);
528 } else {
529 if (hasResult) {
530 if (callPostDownstreamHook) {
531 output.print(" " + JavaType.createForClass(retType).getName());
532 output.print(" _res = ");
533 } else {
534 output.print(" return ");
535 }
536 }
537 else {
538 output.print(" ");
539 }
540 output.print(getDownstreamObjectName());
541 output.print('.');
542 output.print(m.getName());
543 output.print('(');
544 output.print(getArgListAsString(m, false, true));
545 output.println(");");
546 }
547 }
548
549 if (callPostDownstreamHook) {
550 postDownstreamCallHook(output, pm);
551 }
552
553 if (hasResult && callDownstream && callPostDownstreamHook) {
554 output.println(" return _res;");
555 }
556
557 output.println(" }");
558 }
559
560 protected String getArgListAsString(final Method m, final boolean includeArgTypes, final boolean includeArgNames) {
561 final StringBuilder buf = new StringBuilder(256);
562 if (!includeArgNames && !includeArgTypes) {
563 throw new IllegalArgumentException(
564 "Cannot generate arglist without both arg types and arg names");
565 }
566
567 final Class<?>[] argTypes = m.getParameterTypes();
568 for (int i = 0; i < argTypes.length; ++i) {
569 if (includeArgTypes) {
570 buf.append(JavaType.createForClass(argTypes[i]).getName());
571 buf.append(' ');
572 }
573
574 if (includeArgNames) {
575 buf.append("arg");
576 buf.append(i);
577 }
578 if (i < argTypes.length - 1) {
579 buf.append(',');
580 }
581 }
582
583 return buf.toString();
584 }
585
586 /** The name of the class around which this pipeline is being
587 * composed. E.g., if this pipeline was constructed with
588 * "java.util.Set" as the baseInterfaceClassName, then this method will
589 * return "Set".
590 */
591 protected String getBaseInterfaceName() {
592 return baseName;
593 }
594
595 /** Get the output name for this pipeline class. */
596 protected abstract String getOutputName();
597
598 /**
599 * Called after the class headers have been generated, but before any
600 * method wrappers have been generated.
601 */
602 protected void preMethodEmissionHook(final PrintWriter output) {
603 output.println(" public static final boolean DEBUG = jogamp.opengl.Debug.debug(\"" + getOutputName() + "\");");
604 }
605
606 /**
607 * Emits the constructor for the pipeline; called after the preMethodEmissionHook.
608 */
609 protected abstract void constructorHook(PrintWriter output);
610
611 /**
612 * Called after the method wrappers have been generated, but before the
613 * closing parenthesis of the class is emitted.
614 */
615 protected void postMethodEmissionHook(final PrintWriter output) {
616 output.println(" @Override");
617 output.println(" public String toString() {");
618 output.println(" StringBuilder sb = new StringBuilder();");
619 output.println(" sb.append(\"" + getOutputName() + " [this 0x\"+Integer.toHexString(hashCode())+\" implementing " + baseInterfaceClass.getName() + ",\\n\\t\");");
620 if (null != prologClassOpt) {
621 output.println(" sb.append(\" prolog: \"+" + getPrologObjectNameOpt() + ".toString()+\",\\n\\t\");");
622 }
623 output.println(" sb.append(\" downstream: \"+" + getDownstreamObjectName() + ".toString()+\"\\n\\t]\");");
624 output.println(" return sb.toString();");
625 output.println(" }");
626 }
627
628 /**
629 * Called before the pipeline routes the call to the downstream object.
630 */
631 protected abstract void preDownstreamCallHook(PrintWriter output, PlainMethod pm);
632
633 protected abstract boolean hasPreDownstreamCallHook(PlainMethod pm);
634
635 /**
636 * Called after the pipeline has routed the call to the downstream object,
637 * but before the calling function exits or returns a value.
638 */
639 protected abstract void postDownstreamCallHook(PrintWriter output, PlainMethod pm);
640
641 protected abstract boolean hasPostDownstreamCallHook(PlainMethod pm);
642
643 protected abstract int getMode();
644
645 protected abstract boolean emptyMethodAllowed();
646
647 protected abstract boolean emptyDownstreamAllowed();
648
649 /** Emit a Javadoc comment for this pipeline class. */
650 protected abstract void emitClassDocComment(PrintWriter output);
651
652 /**
653 * Emits one of the isGL* methods.
654 */
655 protected void emitGLIsMethodBody(final PrintWriter output, final PlainMethod plainMethod) {
656 final String methodName = plainMethod.getWrappedMethod().getName();
657 final String type = methodName.substring(2);
658
659 if( type.equals("GL") ) {
660 output.println(" return true;");
661 } else if( 0 != ( GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS & getMode() ) &&
662 !type.equals("GLES") &&
663 !type.endsWith("core") &&
664 !type.endsWith("Compatible") )
665 {
666 final Class<?> clazz = BuildComposablePipeline.getClass("com.jogamp.opengl." + type);
667 if (clazz.isAssignableFrom(baseInterfaceClass)) {
668 output.println(" return true;");
669 } else {
670 output.println(" return false;");
671 }
672 } else {
673 output.println(" return " + getDownstreamObjectName() + ".is" + type + "();");
674 }
675 }
676
677 /**
678 * Emits one of the getGL* methods.
679 */
680 protected void emitGLGetMethodBody(final PrintWriter output, final PlainMethod plainMethod) {
681 final String methodName = plainMethod.getWrappedMethod().getName();
682 final String type = methodName.substring(3);
683
684 if( type.equals("GL") ) {
685 output.println(" return this;");
686 } else if( type.equals("GLProfile") ) {
687 output.println(" return " + getDownstreamObjectName() + ".getGLProfile();");
688 } else {
689 final Class<?> clazz = BuildComposablePipeline.getClass("com.jogamp.opengl." + type);
690 if (clazz.isAssignableFrom(baseInterfaceClass)) {
691 output.println(" if( is" + type + "() ) { return this; }");
692 output.println(" throw new GLException(\"Not a " + type + " implementation\");");
693 } else {
694 output.println(" throw new GLException(\"Not a " + type + " implementation\");");
695 }
696 }
697 }
698
699 /**
700 * Emits all synthetic GL* methods, but not isGL* nor getGL*
701 */
702 protected void emitSyntheticGLMethods(final PrintWriter output) {
703 output.println(" @Override");
704 output.println(" public final GL getDownstreamGL() throws GLException {");
705 output.println(" return " + getDownstreamObjectName() + ";");
706 output.println(" }");
707 }
708 } // end class PipelineEmitter
709
710 //-------------------------------------------------------
711 protected class CustomPipeline extends PipelineEmitter {
712
713 String className;
714 int mode;
715
716 CustomPipeline(final int mode, final String outputDir, final String outputPackage, final String outputName, final Class<?> baseInterfaceClass, final Class<?> prologClassOpt, final Class<?> downstreamClass) {
718 className = outputName;
719 this.mode = mode;
720 }
721
722 @Override
723 protected String getOutputName() {
724 return className;
725 }
726
727 @Override
728 protected int getMode() {
729 return mode;
730 }
731
732 @Override
733 protected boolean emptyMethodAllowed() {
734 return true;
735 }
736
737 @Override
738 protected boolean emptyDownstreamAllowed() {
739 return true;
740 }
741
742 @Override
743 protected void preMethodEmissionHook(final PrintWriter output) {
744 super.preMethodEmissionHook(output);
745 }
746
747 @Override
748 protected void constructorHook(final PrintWriter output) {
749 output.print(" public " + getOutputName() + "(");
750 output.print(downstreamName + " " + getDownstreamObjectName());
751 if (null != prologNameOpt) {
752 output.println(", " + prologNameOpt + " " + getPrologObjectNameOpt() + ")");
753 } else {
754 output.println(")");
755 }
756 output.println(" {");
757 output.println(" if (" + getDownstreamObjectName() + " == null) {");
758 output.println(" throw new IllegalArgumentException(\"null " + getDownstreamObjectName() + "\");");
759 output.println(" }");
760 output.print(" this." + getDownstreamObjectName());
761 output.println(" = " + getDownstreamObjectName() + ";");
762 if (null != prologNameOpt) {
763 output.print(" this." + getPrologObjectNameOpt());
764 output.println(" = " + getPrologObjectNameOpt() + ";");
765 }
766 output.println(" }");
767 output.println();
768 }
769
770 @Override
771 protected void postMethodEmissionHook(final PrintWriter output) {
772 super.postMethodEmissionHook(output);
773 if (null != prologNameOpt) {
774 output.print(" private " + prologNameOpt + " " + getPrologObjectNameOpt() + ";");
775 }
776 }
777
778 @Override
779 protected void emitClassDocComment(final PrintWriter output) {
780 output.println("/**");
781 output.println(" * Composable pipeline {@link " + outputPackage + "." + outputName + "}, implementing the interface");
782 output.println(" * {@link " + baseInterfaceClass.getName() + "}");
783 output.println(" * <p>");
784 output.println(" * Each method follows the call graph <ul>");
785 if (null != prologClassOpt) {
786 output.println(" * <li> call <em>prolog</em> {@link " + prologClassOpt.getName() + "} if available");
787 }
788 output.println(" * <li> call <em>downstream</em> {@link " + downstreamClass.getName() + "} if available");
789 if (null != prologClassOpt && 0 != (GEN_PROLOG_XOR_DOWNSTREAM & getMode())) {
790 output.println(" * <strong>and</strong> if no call to {@link " + prologClassOpt.getName() + "} is made");
791 }
792 output.println(" * </ul><p>");
793 output.println(" * ");
794 output.println(" * <ul>");
795 output.println(" * <li> <em>Interface</em> {@link " + baseInterfaceClass.getName() + "}");
796 if (null != prologClassOpt) {
797 output.println(" * <li> <em>Prolog</em> {@link " + prologClassOpt.getName() + "}");
798 }
799 output.println(" * <li> <em>Downstream</em> {@link " + downstreamClass.getName() + "}");
800 output.println(" * </ul><p>");
801 output.println(" * Sample code which installs this pipeline: </P>");
802 output.println(" * ");
803 output.println("<PRE>");
804 if (null != prologNameOpt) {
805 output.println(" GL gl = drawable.setGL( new " + className + "( drawable.getGL().getGL2ES2(), new " + prologNameOpt + "( drawable.getGL().getGL2ES2() ) ) );");
806 } else {
807 output.println(" GL gl = drawable.setGL( new " + className + "( drawable.getGL().getGL2ES2() ) );");
808 }
809 output.println("</PRE>");
810 output.println("*/");
811 }
812
813 @Override
814 protected boolean hasPreDownstreamCallHook(final PlainMethod pm) {
815 return null != getMethod(prologClassOpt, pm.getWrappedMethod());
816 }
817
818 @Override
819 protected void preDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
820 final Method m = pm.getWrappedMethod();
821 if (null != prologNameOpt) {
822 output.print(getPrologObjectNameOpt());
823 output.print('.');
824 output.print(m.getName());
825 output.print('(');
826 output.print(getArgListAsString(m, false, true));
827 output.println(");");
828 }
829 }
830
831 @Override
832 protected boolean hasPostDownstreamCallHook(final PlainMethod pm) {
833 return false;
834 }
835
836 @Override
837 protected void postDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
838 }
839 } // end class CustomPipeline
840
841 protected class DebugPipeline extends PipelineEmitter {
842
843 String className;
844
845 DebugPipeline(final String outputDir, final String outputPackage, final Class<?> baseInterfaceClass, final Class<?> downstreamClass) {
847 className = "Debug" + getBaseInterfaceName();
848 }
849
850 @Override
851 protected String getOutputName() {
852 return className;
853 }
854
855 @Override
856 protected int getMode() {
857 return 0;
858 }
859
860 @Override
861 protected boolean emptyMethodAllowed() {
862 return false;
863 }
864
865 @Override
866 protected boolean emptyDownstreamAllowed() {
867 return false;
868 }
869
870 @Override
871 protected void preMethodEmissionHook(final PrintWriter output) {
872 super.preMethodEmissionHook(output);
873 }
874
875 @Override
876 protected void constructorHook(final PrintWriter output) {
877 output.print(" public " + getOutputName() + "(");
878 output.println(downstreamName + " " + getDownstreamObjectName() + ")");
879 output.println(" {");
880 output.println(" if (" + getDownstreamObjectName() + " == null) {");
881 output.println(" throw new IllegalArgumentException(\"null " + getDownstreamObjectName() + "\");");
882 output.println(" }");
883 output.print(" this." + getDownstreamObjectName());
884 output.println(" = " + getDownstreamObjectName() + ";");
885 if (null != prologNameOpt) {
886 output.print(" this." + getPrologObjectNameOpt());
887 output.println(" = " + getPrologObjectNameOpt() + ";");
888 }
889 output.println(" // Fetch GLContext object for better error checking (if possible)");
890 output.println(" _context = " + getDownstreamObjectName() + ".getContext();");
891 output.println(" }");
892 output.println();
893 }
894
895 @Override
896 protected void postMethodEmissionHook(final PrintWriter output) {
897 super.postMethodEmissionHook(output);
898 output.println(" private int checkGLError() {");
899 if (hasImmediateMode) {
900 output.println(" if (insideBeginEndPair) return GL_NO_ERROR;");
901 output.println();
902 }
903 output.format(" return %s.glGetError();%n", getDownstreamObjectName());
904 output.println(" }");
905
906 output.println(" private void writeGLError(int err, String fmt, Object... args)");
907 output.println(" {");
908 output.println(" StringBuilder buf = new StringBuilder();");
909 output.println(" buf.append(Thread.currentThread().toString());");
910 output.println(" buf.append(\" glGetError() returned the following error codes after a call to \");");
911 output.println(" buf.append(String.format(fmt, args));");
912 output.println(" buf.append(\": \");");
913 output.println();
914 output.println(" // Loop repeatedly to allow for distributed GL implementations,");
915 output.println(" // as detailed in the glGetError() specification");
916 output.println(" int recursionDepth = 10;");
917 output.println(" do {");
918 output.println(" switch (err) {");
919 output.println(" case GL_INVALID_ENUM: buf.append(\"GL_INVALID_ENUM \"); break;");
920 output.println(" case GL_INVALID_VALUE: buf.append(\"GL_INVALID_VALUE \"); break;");
921 output.println(" case GL_INVALID_OPERATION: buf.append(\"GL_INVALID_OPERATION \"); break;");
922 if (hasGL2ES1StackOverflow) {
923 output.println(" case GL2ES1.GL_STACK_OVERFLOW: buf.append(\"GL_STACK_OVERFLOW \"); break;");
924 output.println(" case GL2ES1.GL_STACK_UNDERFLOW: buf.append(\"GL_STACK_UNDERFLOW \"); break;");
925 }
926 output.println(" case GL_OUT_OF_MEMORY: buf.append(\"GL_OUT_OF_MEMORY \"); break;");
927 output.println(" case GL_NO_ERROR: throw new InternalError(\"Should not be treating GL_NO_ERROR as error\");");
928 output.println(" default: buf.append(\"Unknown glGetError() return value: \");");
929 output.println(" }");
930 output.println(" buf.append(\"( \" + err + \" 0x\"+Integer.toHexString(err).toUpperCase() + \"), \");");
931 output.println(" } while ((--recursionDepth >= 0) && (err = "
933 + ".glGetError()) != GL_NO_ERROR);");
934 output.println(" throw new GLException(buf.toString());");
935 output.println(" }");
936 if (hasImmediateMode) {
937 output.println(" /** True if the pipeline is inside a glBegin/glEnd pair.*/");
938 output.println(" private boolean insideBeginEndPair = false;");
939 output.println();
940 }
941 output.println(" private void checkContext() {");
942 output.println(" GLContext currentContext = GLContext.getCurrent();");
943 output.println(" if (currentContext == null) {");
944 output.println(" throw new GLException(\"No OpenGL context is current on this thread\");");
945 output.println(" }");
946 output.println(" if ((_context != null) && (_context != currentContext)) {");
947 output.println(" throw new GLException(\"This GL object is being incorrectly used with a different GLContext than that which created it\");");
948 output.println(" }");
949 output.println(" }");
950 output.println(" private GLContext _context;");
951 }
952
953 @Override
954 protected void emitClassDocComment(final PrintWriter output) {
955 output.println("/**");
956 output.println(" * <p>");
957 output.println(" * Composable pipeline which wraps an underlying {@link GL} implementation,");
958 output.println(" * providing error checking after each OpenGL method call. If an error occurs,");
959 output.println(" * causes a {@link GLException} to be thrown at exactly the point of failure.");
960 output.println(" * </p>");
961 output.println(" * <p>");
962 output.println(" * Sample code which installs this pipeline:");
963 output.println(" * <pre>");
964 output.println(" * gl = drawable.setGL(new DebugGL(drawable.getGL()));");
965 output.println(" * </pre>");
966 output.println(" * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}");
967 output.println(" * </p>");
968 output.println(" */");
969 }
970
971 @Override
972 protected boolean hasPreDownstreamCallHook(final PlainMethod pm) {
973 return !pm.isSynthetic();
974 }
975
976 @Override
977 protected void preDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
978 output.println(" checkContext();");
979 }
980
981 @Override
982 protected boolean hasPostDownstreamCallHook(final PlainMethod pm) {
983 return !pm.isSynthetic();
984 }
985
986 @Override
987 protected void postDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
988 final Method m = pm.getWrappedMethod();
989 if (m.getName().equals("glBegin")) {
990 output.println(" insideBeginEndPair = true;");
991 output.println(" // NOTE: can't check glGetError(); it's not allowed inside glBegin/glEnd pair");
992 } else {
993 if (m.getName().equals("glEnd")) {
994 output.println(" insideBeginEndPair = false;");
995 }
996
997 output.println(" final int err = checkGLError();");
998 output.println(" if (err != GL_NO_ERROR) {");
999
1000 final StringBuilder fmtsb = new StringBuilder();
1001 final StringBuilder argsb = new StringBuilder();
1002
1003 fmtsb.append("\"%s(");
1004 argsb.append("\"").append(m.getName()).append("\"");
1005 final Class<?>[] params = m.getParameterTypes();
1006 for (int i = 0; i < params.length; i++) {
1007 if (i > 0) {
1008 fmtsb.append(", ");
1009 }
1010 fmtsb.append("<").append(params[i].getName()).append(">");
1011 if (params[i].isArray()) {
1012 //nothing
1013 } else if (params[i].equals(int.class)) {
1014 fmtsb.append(" 0x%X");
1015 argsb.append(", arg").append(i);
1016 } else {
1017 fmtsb.append(" %s");
1018 argsb.append(", arg").append(i);
1019 }
1020 }
1021 fmtsb.append(")\",");
1022 argsb.append(");");
1023
1024 // calls to glGetError() are only allowed outside of glBegin/glEnd pairs
1025 output.print(" writeGLError(err, ");
1026 output.println(fmtsb.toString());
1027 output.print(" ");
1028 output.println(argsb.toString());
1029 output.println(" }");
1030 }
1031 }
1032 } // end class DebugPipeline
1033
1034 //-------------------------------------------------------
1035 protected class TracePipeline extends PipelineEmitter {
1036
1037 String className;
1038
1039 TracePipeline(final String outputDir, final String outputPackage, final Class<?> baseInterfaceClass, final Class<?> downstreamClass) {
1041 className = "Trace" + getBaseInterfaceName();
1042 }
1043
1044 @Override
1045 protected String getOutputName() {
1046 return className;
1047 }
1048
1049 @Override
1050 protected int getMode() {
1051 return 0;
1052 }
1053
1054 @Override
1055 protected boolean emptyMethodAllowed() {
1056 return false;
1057 }
1058
1059 @Override
1060 protected boolean emptyDownstreamAllowed() {
1061 return false;
1062 }
1063
1064 @Override
1065 protected void preMethodEmissionHook(final PrintWriter output) {
1066 super.preMethodEmissionHook(output);
1067 }
1068
1069 @Override
1070 protected void constructorHook(final PrintWriter output) {
1071 output.print(" public " + getOutputName() + "(");
1072 output.println(downstreamName + " " + getDownstreamObjectName() + ", PrintStream " + getOutputStreamName() + ")");
1073 output.println(" {");
1074 output.println(" if (" + getDownstreamObjectName() + " == null) {");
1075 output.println(" throw new IllegalArgumentException(\"null " + getDownstreamObjectName() + "\");");
1076 output.println(" }");
1077 output.print(" this." + getDownstreamObjectName());
1078 output.println(" = " + getDownstreamObjectName() + ";");
1079 output.print(" this." + getOutputStreamName());
1080 output.println(" = " + getOutputStreamName() + ";");
1081 output.println(" }");
1082 output.println();
1083 }
1084
1085 @Override
1086 protected void postMethodEmissionHook(final PrintWriter output) {
1087 super.postMethodEmissionHook(output);
1088 output.println("private PrintStream " + getOutputStreamName() + ";");
1089 output.println("private int indent = 0;");
1090 output.println("protected String dumpArray(Object obj)");
1091 output.println("{");
1092 output.println(" if (obj == null) return \"[null]\";");
1093 output.println(" StringBuilder sb = new StringBuilder(\"[\");");
1094 output.println(" int len = java.lang.reflect.Array.getLength(obj);");
1095 output.println(" int count = Math.min(len,16);");
1096 output.println(" for ( int i =0; i < count; i++ ) {");
1097 output.println(" sb.append(java.lang.reflect.Array.get(obj,i));");
1098 output.println(" if (i < count-1)");
1099 output.println(" sb.append(',');");
1100 output.println(" }");
1101 output.println(" if ( len > 16 )");
1102 output.println(" sb.append(\"...\").append(len);");
1103 output.println(" sb.append(']');");
1104 output.println(" return sb.toString();");
1105 output.println("}");
1106 output.println("protected void print(String str)");
1107 output.println("{");
1108 output.println(" " + getOutputStreamName() + ".print(str);");
1109 output.println("}");
1110 output.println("protected void println(String str)");
1111 output.println("{");
1112 output.println(" " + getOutputStreamName() + ".println(str);");
1113 output.println("}");
1114 output.println("protected void printIndent()");
1115 output.println("{");
1116 output.println(" for( int i =0; i < indent; i++) {" + getOutputStreamName() + ".print(' ');}");
1117 output.println("}");
1118 }
1119
1120 @Override
1121 protected void emitClassDocComment(final PrintWriter output) {
1122 output.println("/**");
1123 output.println(" * <p>");
1124 output.println(" * Composable pipeline which wraps an underlying {@link GL} implementation,");
1125 output.println(" * providing tracing information to a user-specified {@link java.io.PrintStream}");
1126 output.println(" * before and after each OpenGL method call.");
1127 output.println(" * </p>");
1128 output.println(" * <p>");
1129 output.println(" * Sample code which installs this pipeline:");
1130 output.println(" * <pre>");
1131 output.println(" * gl = drawable.setGL(new TraceGL(drawable.getGL(), System.err));");
1132 output.println(" * </pre>");
1133 output.println(" * For automatic instantiation see {@link GLPipelineFactory#create(String, Class, GL, Object[])}");
1134 output.println(" * </p>");
1135 output.println(" */");
1136 }
1137
1138 @Override
1139 protected boolean hasPreDownstreamCallHook(final PlainMethod pm) {
1140 return !pm.isSynthetic();
1141 }
1142
1143 @Override
1144 protected void preDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
1145 final Method m = pm.getWrappedMethod();
1146 if (m.getName().equals("glEnd") || m.getName().equals("glEndList")) {
1147 output.println(" indent-=2;");
1148 output.println(" printIndent();");
1149 } else {
1150 output.println(" printIndent();");
1151 }
1152
1153 output.print(" print(");
1154 printFunctionCallString(output, m);
1155 output.println(");");
1156 }
1157
1158 @Override
1159 protected boolean hasPostDownstreamCallHook(final PlainMethod pm) {
1160 return !pm.isSynthetic();
1161 }
1162
1163 @Override
1164 protected void postDownstreamCallHook(final PrintWriter output, final PlainMethod pm) {
1165 final Method m = pm.getWrappedMethod();
1166 final Class<?> ret = m.getReturnType();
1167 if (ret != Void.TYPE) {
1168 output.println(" println(\" = \"+_res);");
1169 } else {
1170 output.println(" println(\"\");");
1171 }
1172
1173 if (m.getName().equals("glBegin"))
1174 output.println(" indent+=2;");
1175 }
1176
1177 private String getOutputStreamName() {
1178 return "stream";
1179 }
1180 } // end class TracePipeline
1181
1182 public static final void printFunctionCallString(final PrintWriter output, final Method m) {
1183 final Class<?>[] params = m.getParameterTypes();
1184 output.print(" \"" + m.getName() + "(\"");
1185 for (int i = 0; i < params.length; i++) {
1186 output.print("+\"<" + params[i].getName() + ">");
1187 if (params[i].isArray()) {
1188 output.print("\"");
1189 } else if (params[i].equals(int.class)) {
1190 output.print(" 0x\"+Integer.toHexString(arg" + i + ").toUpperCase()");
1191 } else {
1192 output.print(" \"+arg" + i);
1193 }
1194 if (i < params.length - 1) {
1195 output.print("+\", \"");
1196 }
1197 }
1198 output.print("+\")\"");
1199 }
1200}
void preMethodEmissionHook(final PrintWriter output)
Called after the class headers have been generated, but before any method wrappers have been generate...
void postDownstreamCallHook(final PrintWriter output, final PlainMethod pm)
Called after the pipeline has routed the call to the downstream object, but before the calling functi...
void emitClassDocComment(final PrintWriter output)
Emit a Javadoc comment for this pipeline class.
void preDownstreamCallHook(final PrintWriter output, final PlainMethod pm)
Called before the pipeline routes the call to the downstream object.
String getOutputName()
Get the output name for this pipeline class.
void constructorHook(final PrintWriter output)
Emits the constructor for the pipeline; called after the preMethodEmissionHook.
void postMethodEmissionHook(final PrintWriter output)
Called after the method wrappers have been generated, but before the closing parenthesis of the class...
void preDownstreamCallHook(final PrintWriter output, final PlainMethod pm)
Called before the pipeline routes the call to the downstream object.
void postMethodEmissionHook(final PrintWriter output)
Called after the method wrappers have been generated, but before the closing parenthesis of the class...
void postDownstreamCallHook(final PrintWriter output, final PlainMethod pm)
Called after the pipeline has routed the call to the downstream object, but before the calling functi...
void preMethodEmissionHook(final PrintWriter output)
Called after the class headers have been generated, but before any method wrappers have been generate...
String getOutputName()
Get the output name for this pipeline class.
void constructorHook(final PrintWriter output)
Emits the constructor for the pipeline; called after the preMethodEmissionHook.
void emitClassDocComment(final PrintWriter output)
Emit a Javadoc comment for this pipeline class.
Emits a Java source file that represents one element of the composable pipeline.
void emitMethodDocComment(final PrintWriter output, final Method m)
abstract void emitClassDocComment(PrintWriter output)
Emit a Javadoc comment for this pipeline class.
String getDownstreamObjectName()
Get the name of the object through which API calls should be routed.
abstract void postDownstreamCallHook(PrintWriter output, PlainMethod pm)
Called after the pipeline has routed the call to the downstream object, but before the calling functi...
void emitBody(final PrintWriter output, final PlainMethod pm)
abstract void preDownstreamCallHook(PrintWriter output, PlainMethod pm)
Called before the pipeline routes the call to the downstream object.
void emitGLIsMethodBody(final PrintWriter output, final PlainMethod plainMethod)
Emits one of the isGL* methods.
void postMethodEmissionHook(final PrintWriter output)
Called after the method wrappers have been generated, but before the closing parenthesis of the class...
String getBaseInterfaceName()
The name of the class around which this pipeline is being composed.
void emitGLGetMethodBody(final PrintWriter output, final PlainMethod plainMethod)
Emits one of the getGL* methods.
void emitSyntheticGLMethods(final PrintWriter output)
Emits all synthetic GL* methods, but not isGL* nor getGL*.
abstract void constructorHook(PrintWriter output)
Emits the constructor for the pipeline; called after the preMethodEmissionHook.
String getArgListAsString(final Method m, final boolean includeArgTypes, final boolean includeArgNames)
void preMethodEmissionHook(final PrintWriter output)
Called after the class headers have been generated, but before any method wrappers have been generate...
String getPrologObjectNameOpt()
Get the name of the object which shall be called as a prolog.
abstract String getOutputName()
Get the output name for this pipeline class.
void preDownstreamCallHook(final PrintWriter output, final PlainMethod pm)
Called before the pipeline routes the call to the downstream object.
void postDownstreamCallHook(final PrintWriter output, final PlainMethod pm)
Called after the pipeline has routed the call to the downstream object, but before the calling functi...
void postMethodEmissionHook(final PrintWriter output)
Called after the method wrappers have been generated, but before the closing parenthesis of the class...
void preMethodEmissionHook(final PrintWriter output)
Called after the class headers have been generated, but before any method wrappers have been generate...
String getOutputName()
Get the output name for this pipeline class.
void constructorHook(final PrintWriter output)
Emits the constructor for the pipeline; called after the preMethodEmissionHook.
void emitClassDocComment(final PrintWriter output)
Emit a Javadoc comment for this pipeline class.
static String getBaseClassName(final String clazzName)
void emit()
Emit the java source code for the classes that comprise the composable pipeline.
static final void printFunctionCallString(final PrintWriter output, final Method m)
static Method getMethod(final Class<?> clazz, final Method m)
static String getPackageName(final String clazzName)
static final int GEN_PROLOG_XOR_DOWNSTREAM
By extra command-line argument: prolog_xor_downstream.
BuildComposablePipeline(final int mode, final String outputDir, final String outputPackage, final String outputName, final Class<?> classToComposeAround, final Class<?> classPrologOpt, final Class<?> classDownstream)
static final int GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS
By extra command-line argument: gl_identity_by_assignable_class.