[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


go one page back go to start go to start go one page ahead
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

^ToC 1 Principles of metajava

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:

  1. on the top layer the "more coarse" java notions like package, file, class, down to field and method, are modelled as java objects.
  2. on the lower layer the "finer" structures like expressions and statements can conveniently be generated, abstracted and instantiated, but are not longer mapped to typed data structures individually.

^ToC 2 Upper Layer: Explicitly Manipulated metajava Classes

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

^ToC 2.1 Classes, Types and Instantiations

^ToC 2.2 Creation Methods

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 !!

^ToC 2.3 Inquiry Methods

  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()

^ToC 2.4 Update Methods

  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)

^ToC 3 Lower Layer: Generating Statements and Expressions with FormatClosure

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.

^ToC 3.1 The Format Closure Parser

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.

^ToC 3.2 Storing Expressions and Statements to metajava Objects

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.

^ToC 3.3 Parametrization and Class References

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.

^ToC 4 Writing out to Source Files



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


go one page back go to start go to start go one page ahead
paisley bandm meta_tools umod

made    2018-12-30_10h55   by    lepper   on    linux-q699.site        Valid XHTML 1.0 Transitional Valid CSS 2.1

produced with eu.bandm.metatools.d2d    and    XSLT    FYI view page d2d source text