users@jaxb.java.net

Re: custom AnnotationReader

From: Aleksei Valikov <valikov_at_gmx.net>
Date: Tue, 14 Nov 2006 11:49:44 +0100

Hi.

>> Speaking of a "custom AnnotationReader to read annotations from an
>> external file", this might be the right approach for handling Java
>> sources the user cannot annotate. We had a discussion a few days ago
>> about marshalling JRE classes such as classes Point or Dimension in
>> java.awt package. For example, how can we specify that we'll use
>> attributes rather than elements? In the case of "non-annotable"
>> classes, some external file could be the answer.
>
> Yes. Indeed that was where this original idea came from.
>
> I'm still waiting for someone to volunteer for writing a custom
> AnnotationReader that reads from a file. I think all the hooks are there
> in the JAXB RI. We just need an implementation of it.

Seems to be an interesting task. :) I'll see what I can do. I think, a generic
mechanism must be possible here. Say, a resource name MyClass.ann.xml exist next
to the MyClass.class. When required, the annotation reader looks for the
corresponding file and reads annotations.

The ann.xml has a generic layout with elements like package, class, field,
method and property. These elements contain further annotation elements
associated with specific annotation classes via namespaces.

It could look like:

<class xmlns:jaxb="urn:some-special-prefix:javax.xml.bind.annotation">
        <jaxb:XMLAccessorType value="PROPERTY"/>
        <jaxb:XMLType name="B" propOrder="id version c"/>
        <property name="id">
                <jaxb:XMLAttribute/>
        </property>
        <property name="version">
                <jaxb:XMLAttribute/>
        </property>
</class>

Annotation classes javax.xml.bind.annotation.XMLAccessorType and so on are
inferred from the namespace plus element name. Alternatively they may be
explicitly declared.

Annotation fields are read from attributes or child elements of annotation
elements. It is relatively easy to detect types of fields via reflection, and
parse string values appropriately.

The only thing I miss right now is instantiation of annotations. Annotations are
essentially either abstract classes or enums. Enums are trivial. Abstract
classes need to be implemented first (I simply haven't done this before).

This can really be a generic mechanism which simply parallelizes
reflection-based annotation discovery. Maybe I miss something and the thing like
this already exists? AnnotationReader could the be implemented on top of this
mechanism.

BTW, I'm working on the "annotate" plugin which converts XML Schema annotations
into class/field annotations. For instance the XML:

<A
        xmlns="urn:org.jvnet.hyperjaxb3.plugin.annotate:org.jvnet.hyperjaxb3.plugin.annotate.tests"
        xmlns:n="urn:org.jvnet.hyperjaxb3.plugin.annotate"
        booleanField="false"
        byteField="0"
        charField="a"
        classField="java.lang.String"
        doubleField="1"
        enumField="ONE"
        floatField="2.3"
        intField="4"
        longField="5"
        shortField="6"
        stringField="7">
        <annotationField>
                <B
                        booleanArrayField="false true"
                        byteArrayField="0 1"
                        charArrayField="a b"
                        classArrayField="java.lang.String java.lang.Boolean"
                        doubleArrayField="2 3"
                        enumArrayField="ONE TWO"
                        floatArrayField="4.5 6.7"
                        intArrayField="8 9"
                        longArrayField="10 11"
                        shortArrayField="12 13"
                        stringArrayField="14 15">
                        <stringArrayField>16</stringArrayField>
                        <stringArrayField>17</stringArrayField>
                        <annotationArrayField>
                                <C n:class="org.jvnet.hyperjaxb3.plugin.annotate.tests.B$C"/>
                                <C n:class="org.jvnet.hyperjaxb3.plugin.annotate.tests.B$C"/>
                        </annotationArrayField>
                </B>
        </annotationField>
</A>

is converted into the following annotation:

package org.jvnet.hyperjaxb3.plugin.annotate.tests;


@A(longField = 5, intField = 4, shortField = 6, charField = 97, byteField = 0,
doubleField = 1, floatField = 2, booleanField = false, stringField = "7",
enumField = org.jvnet.hyperjaxb3.plugin.annotate.tests.AnnotateTest.E.ONE,
classField = String.class, annotationField = @B(longArrayField = {
     10,
     11
}, intArrayField = {
     8,
     9
}, shortArrayField = {
     12,
     13
}, charArrayField = {
     97,
     98
}, byteArrayField = {
     0,
     1
}, doubleArrayField = {
     2,
     3
}, floatArrayField = {
     4,
     6
}, booleanArrayField = {
     false,
     true
}, stringArrayField = {
     "14",
     "15",
     "16",
     "17"
}, enumArrayField = {

}, classArrayField = {
     String.class,
     Boolean.class
}, annotationArrayField = {
     @B.C,
     @B.C
}))
public class Demo {


}

This works already, so I think I'll try implementing this idea with ann.xml as well.

Bye.
/lexi