[all pages:] introduction message / location / muli format dtd xantlr tdom ops paisley metajava umod option auxiliaries d2d downloads & licenses people bibliography APPENDICES:: white papers white papers 2 white papers 3 project struct proposal cygwin tips SOURCE:option.dtd SOURCE:dtd.umod DOC:deliverables.ddf DOC-DE:deliverables.ddf DOC:mtdocpage.ddf DOC-DE:mtdocpage.ddf SOURCE:basic.dd2 SOURCE:xslt.dd2
paisley | bandm meta_tools | umod |
metajava
(related API documentation: package metajava )
1
Principles of metajava
2
Upper Layer: Explicitly Manipulated metajava Classes
2.1
Classes, Types and Instantiations
2.2
Creation Methods
2.3
Inquiry Methods
2.4
Update Methods
3
Lower Layer: Generating Statements and Expressions with FormatClosure
3.1
The Format Closure Parser
3.2
Storing Expressions and Statements to metajava Objects
3.3
Parametrization and Class References
4
Writing out to Source Files
In the context of meta_tools , metajava is the central means for generating java source text.
It supports esp. a widely type-safe interaction of newly generated source code with already existing classes. These must be accessible in compiled, binary form and serve often as "runtime", "third-party", "library" or "environmental" classes.
metajava is a two-layer architecture:
The fundamental idea of the top layer of metajava is that pre-existing binary code and the newly created code are accessible by the same class structure.
The classes of this common abstraction is called "Meta...", i.e. MetaPackage, MetaClass, MetaMethod, etc.
One kind of sub-classes of these classes now describes the existing class code, the newly generated sources shall co-operate with. These existing classes need to be accessible as binaries. The interface offered by the modeling objects is similar to the well-known reflection interface as defined in java.lang.reflect
These classes are called EnvironmentPackage, EnvironmentClass, EnvironmentMethod, etc.
Contrarily, sub-classes of the other kind represent newly generated structures. They are called GeneratedPackage, GeneratedClass, GeneratedMethod, etc.
Both kinds of classes offer identical interfaces for inquiriesIn case of Environment..., this is realized as a wrapper around java.lang.reflect
The construction and the update interface is, naturally, only offered by the Generated... side, but its operations and parameter values also closely follow the conventions from java.lang.reflect.
Please refer also to the API doc
The following diagram illustrates these relations:
+-----------------+ +-----------------+| | MetaPackage || | ..Class || | ..Method || | (etc.) | +-----------------+ | INQUIRY METHODS | | | +-----------------+ ^ /_\ | +-----------------+---------------+ | | +------------------+ +--------------------+ +------------------+| +--------------------+| |EnvironmentPackage|| | GeneratedPackage || | ..Class || | ..Class || | ..Method | | ..Method | | (etc.) | | (etc.) | +------------------+ +--------------------+ |(mostly just | | CREATION METHODS | | wrappers) | | (+few update meth.)| +------------------* +--------------------+ ^ / \ \ / | | +--------------------+ |java.lang.reflection| | .Package | | .Class | | .Method | | (etc.) | +--------------------+ |
The interface and class hierarchy in detail reads (in a symbolic, umod-like notation) as ...
INTERFACE TREE MetaImportable | MetaPackage | MetaClass MetaField MetaConstructor MetaMethod CLASS TREE EnvironmentPackage IMPLEMENTS MetaPackage EnvironmentClass IMPLEMENTS MetaClass EnvironmentField IMPLEMENTS MetaField EnvironmentConstructor IMPLEMENTS MetaConstructor EnvironmentMethod IMPLEMENTS MetaMethod CLASS TREE GeneratedPackage IMPLEMENTS MetaPackage GeneratedDeclaration ABSTRACT | GeneratedClass IMPLEMENTS MetaClass | | AnonymousClass | GeneratedMember | | GeneratedField IMPLEMENTS MetaField | | GeneratedProcedure | | | GeneratedConstructor IMPLEMENTS MetaConstructor | | | GeneratedMethod IMPLEMENTS MetaMethod | GeneratedBlock | GeneratedDirt GeneratedFile GeneratedParameter |
The creation methods of metajava work top-down, by enhancing an already existing object with a new component. Due to this strategy a newly created object is forced to exist in a type correct context 1 .
The methods are named <existingGeneratedObject>.add<newObject's Class>(...).
This naming is a little bit misleading, because most if them not just modify the containing object, but are factory methods which create a new sub-object (Read "addClass()" as "addNewClass()"). They return the newly created object as their result, while the true update methods, which only link an existing object to a container, return void.
The following table gives a survey on this interfaces in symbolic notations. Please note that there are also convenience methods, e.g. which substitute parameters. This table and the following tables in this user documenation file are only intended to give an overall impression. The method signatures may be substantially enhanced, and their current concrete form should always be looked-up in the API doc.
GeneratedPackage(String name) | GeneratedClass addClass(int modifiers, String name, MetaClass superclass) | GeneratedFile addAuxiliaryFile(String name) GeneratedDeclaration (= GeneratedClass+..Field+..Constructor+..Method+..Block+..Dirt) | void addComment (Format) GeneratedClass (MetaPackage p, int modifiers, String name, MetaClass superClass) | void addImport (MetaImportable) | void addInterface (MetaClass metaInterface) | GeneratedClass addInnerClass (int modifiers, String name, MetaClass superClass) | AnonymousClass addAnonymousClass (MetaClass superClass) | GeneratedConstructor addConstructor (int modifiers) | GeneratedField addField (int modifiers, MetaClass type, String name) | GeneratedMethod addMethod (int modifiers, MetaClass returnType, String name) | GeneratedBlock addBlock (int modifiers) | (GeneratedDirt) addDirt (Format) GeneratedProcedure (= GeneratedConstructor + GeneratedMethod) | GeneratedParameter addParameter(int modifiers, MetaClass type, String name) | void addParameter(GeneratedParameter) | void addExceptionType(MetaClass) | void addStatement(Format) GeneratedBlock | void addStatement(Format) |
Please note that for your convenience all methods are overloaded: Whenever an argument of type MetaClass/Field/... is required, you can directly supply a native java.lang.Class/java.lang.reflect.Field/... object instead. The required wrapping will be performed automatically.
For explicit creation, there are static methods with the correspondig wrapper class :
EnvironmentPackage STATIC METHODS | EnvironmentPackage wrap (java.util.Package (???) ) | EnvironmentPackage wrap (String name) EnvironmentClass STATIC METHODS | EnvironmentClass wrap (java.lang.Class) | EnvironmentClass[] wrap (java.lang.Class[]) EnvironmentField STATIC METHDODS | EnvironmentField wrap(java.lang.reflect.Field) | EnvironmentField[] wrap(java.lang.reflect.Field[]) EnvironmentConstructor STATIC METHDODS | EnvironmentConstructor wrap(java.lang.reflect.Constructor) | EnvironmentConstructor[] wrap(java.lang.reflect.Constructor[]) EnvironmentMethod STATIC METHODS | EnvironmentMethod wrap (java.lang.Method) | EnvironmentMethod[] wrap (java.lang.Method[]) |
ODER / UND / ???
metajava "GeneratedMember parseDeclaration(String)" to get class level declarations parsed like static public final int INT = 42 !!
MetaPackage | String getName() EnvironmentPackage | String getImportPattern() GeneratedPackage | MetaClass[] getClasses() | GeneratedFile[] getAuxiliaryFiles() | String getImportPattern() | String qualifyClassName(String classname) MetaImportable | String getImportPattern() MetaClass | MetaPackage getPackage() | String getSimpleName()/..QualifiedName()/..PackageName() | MetaClass getSuperClass()/..EnclosingClass() | MetaClass[] getInnerClasses()/getInterfaces() | MetaField[] getFields() | MetaConstructor[] getConstructors() | MetaMethod[] getMethods() | GeneratedDeclaration[] getOrderedMembers() | boolean isArray() | MetaClass getElementClass() GeneratedDeclaration (= GeneratedClass+..Field+..Constructor+..Method+..Block+..Dirt) | Format getComments() | int getModifiers() GeneratedClass | MetaImportable[] getImports() AnonymousClass | Format instantiationFormat(Format[]) GeneratedMember (= GeneratedField + ..Constructor + ..Method) | MetaClass getEnclosingClass | String getName MetaField | int getModifiers() | MetaClass getType() | String getName() GeneratedField | Format getInitializer() GeneratedProcedure (= GeneratedConstructor + GeneratedMethod) | GeneratedParameter[] getParameters() | GeneratedParameter getParameter(int index) | MetaClass[] getParameterTypes() | MetaClass[] getExceptionTypes() | Format[] getStatements() | Format getCode() MetaMethod | int getModifiers() | MetaClass getReturnType() | String getName() | MetaClass[] getParameterTypes() | MetaClass[] getExceptionTypes() GeneratedMethod.java | MetaClass getReturnType() GeneratedBlock | Format getStatements() GeneratedDirt | Format getFormat() GeneratedFile | String getName() | java.io.OutputStream getOutoputStream() | byte[] getBytes() GeneratedParameter | int getModifiers() | MetaClass getType() | String getName() |
GeneratedPackage | removeClass(String) GeneratedDeclaration (= GeneratedClass+..Field+..Constructor+..Method+..Block+..Dirt) | setModifiers (int) GeneratedClass | setSuperClass(MetaClass) GeneratedField | setInitializer(Format) GeneratedProcedure (= GeneratedConstructor + GeneratedMethod) | clearStatements() GeneratedMethod | setReturnType(MetaClass) GeneratedParameter | setModifiers (int) |
As mentioned above, the lower level of metajava deals with expressions and statements. These are no longer mapped to typed objects inidividually, but realized evenly by Formats .
That means, that there are no special java classes for things like "if-statement", "for-loop", "int-expression", etc.
Only references to classes can are treated specially, which is a pre-requisite for automated conversion from logical to textual references, as described in section Section 3.3.
The class metajava.FormatClosure offers different parsing methods. Each of them takes the textual representation of a sentence, corresponding to a certain non-terminal of the java grammar, and returns a format object which represents the parsed text. In case of syntax errors, these will be signaled.
ATTENTION The textual input parameter is checked by
metajava to be correct java syntax not before executing the
selected parsing method (like statement(), statements() etc.)
Therefore error messages concerning the correctness of your source are
not delivered until run-time, even if the string argument is constant!
The best way is not to create a FormatClosure locally, but to assign it to a final static class variable. Then, since fields of this kind are initialized at class loading time, the possible syntactic errors in the java source fragments are detected as early as possible, at program start-up, and not during later program exection.
Of course this also has benefits for the execution speed, since the parsing process for each formatClosure is only performed once.
What you finally do with a fully instantiated format, which represents one expression or a sequence of expressions, or a statement, etc. is to assign it to a parameter of a certain object of the "upper layer" of metajava, as described above.
At the end of the day, when these generated objects will be written out ot some source file, these formats will appear at the correct place in the source text. E.g.
final GeneratedClass cl = ... final GeneratedBlock bl = cl.addBlock(Modifier.PUBLIC); bl.addStatement(FormatClosure.statement("init(12);"); final GeneratedField fi = cl.addField(Modifier.PUBLIC, int.class, "myfield"); fi.setInitializer(FormatClosure.expression("init(12)"); |
Please notethat, as already mentioned above, the type of syntactic structure is (currently !?!?) not reflected in the type of the Format object. So if you use a statement sequence as an initializer of a field, you generate code which will not compile.
This class (and sometimes those delivered results) are called
"format closure", because the parametrization mechanism (as defined
already with the format library as such) is in most cases
heavily employed:
When generating source code, you oftenly need templates with a
constant skeleton structure, into which varying arguments shall be inserted.
this is easiy accomplisehd with this
parametrization mechanism of the format
library.
To make this feature accessible out of java source syntax, the
underlying parser is significantly modified: At
each position the java syntax permits an "identifier",a parameter sign "#<n>" may appear.
Please note that this has turned out to be sufficient in nearly all cases,
but indeed not all kinds of parametrization are feasible, e.g.
As always, the instantiation of such a closure is done by calling applyTo(), as described in the format library documentation. The arguments may be Format objects, or anything implementing format.Formattable .
Whenever a class or type is inserted as a parameter into
such a format closure, a provisonary "full path name" will be created
by its format() function (and thus inserted into the point of application),
but the semantic information, ie. the reference
to the class or type as a metajava object, will additionally be memoized.
Therefore, as a last step before writing out generated source files,
a
metajava.ReferenceRewritercan be mapped over the generated formats. This replaces
the full, trivial name of a refered classes
by a more readable adressing, according to the
source file's import statements and to the java shadowing rules.
1 This is in contrast to the run-time code-generation API of "micro-soft" (designed approx. at the same time as ours), which heavily relies on a undocumented stateful protocol, what is always a nice exercise in reverse-engineering for students. But even the GNU "lib-bfd" is no better!
[all pages:] introduction message / location / muli format dtd xantlr tdom ops paisley metajava umod option auxiliaries d2d downloads & licenses people bibliography APPENDICES:: white papers white papers 2 white papers 3 project struct proposal cygwin tips SOURCE:option.dtd SOURCE:dtd.umod DOC:deliverables.ddf DOC-DE:deliverables.ddf DOC:mtdocpage.ddf DOC-DE:mtdocpage.ddf SOURCE:basic.dd2 SOURCE:xslt.dd2
paisley | bandm meta_tools | umod |
made
2018-12-30_10h55 by
lepper on
linux-q699.site
produced with
eu.bandm.metatools.d2d
and
XSLT
FYI view
page d2d source text