A while ago I suggested that using attributes may be a way out of the
problems we're having with meta models. The response then was that
the idea sure seemed nice, but the implementation of the idea sure
seemed nonexistent.

I have now whacked together a proof-of-concept for my idea. This is what
it
does:

 1. You start off by defining your attributes:

    import org.apache.avalon.attributes.Inheritable;

    /**
     * Declares a dependency.
     * 
     * @Inheritable ()
     */
    public class Dependency {
    
        private final Class clazz;
        private final String name;
    
        public Dependency (Class clazz, String name) {
            this.clazz = clazz;
            this.name = name;
        }
    
        public Class getDependencyClass () { return clazz; }
    
        public String getDependencyName () { return name; }
    
        public String toString () {
            return "[Dependency on " + clazz.getName () + " via name \""
+ name + "\"]";
        }
    }

    Note that the class doesn't have to be serializable. Also note the
@Inheritable attribute
    that this attribute has. This means that Dependency attributes are
inherited.

 2. You mark your classes:

    /**
     * @Dependency ( SampleService.class, "super-sample" )
     */
    public class SuperClass { ... }

    /**
     * @Dependency ( SampleService.class, "sample" )
     */
    public class Sample extends SuperClass { ... }

 3. Use the attribute compiler before compiling:

        <taskdef
            name="attributes"
 
classname="org.apache.avalon.attributes.compiler.AttributeCompiler"
 
classpath="bin/xdoclet-xjavadoc-1.0.jar;bin/commons-collections-2.1.jar;
../compiler/target/classes/"
            />
                
        <!-- Precompile. -->
        <attributes destDir="temp/">
            <fileset dir="src/test/" includes="**/*.java"/>
        </attributes>
                
        <!-- Compile everything, including the classes generated above.
-->
        <mkdir dir="target/classes/"/>
        <javac destdir="target/classes/"
            classpath="api/target/classes"
            debug="true"
            deprecation="true">
            <src> 
                <pathelement path="src/test/"/>
                <pathelement path="temp/"/>
            </src>
        </javac>
                
 4. Run it:

    Getting attributes for class Sample...
    Sample has the following class attributes:
    [
        [Dependency on org.apache.avalon.attributes.test.SampleService
via name "super-sample"], 
        [Dependency on org.apache.avalon.attributes.test.SampleService
via name "sample"], 
    ]

    Note that Sample inherited an attribuet from its superclass.

The code is in avalon-sandbox/attributes. You should be able to check it
out and run
maven to compile everything. Since I'm not very good with Maven, the
demo, and the
compiler, are written for Ant. I hope to change this.

   ... check out ...

   c:\home>maven && ant


Dependencies
------------
The compiler is dependent on Ant (since it is an Ant task) and on
XJavadoc-1.0. I tried XJavadoc-1.2b2,
but there were some methods missing, and I couldn't for the life of me
figure out how to adapt my
source.

The runtime package is 9kB and has no dependencies beyond the standard
Java Runtime. No XML parser,
no nothing.

Why not Attrib4J?
-----------------
I spent some time with Attrib4J, and I wasn't satisfied, so I decided
to write my own attribute compiler. At the very least I wanted to
know how I would like to modify Attrib4J, should I decide to go
that way instead.

My issues with Attrib4J are:

 + Stores attributes as serialized objects. This means that we have
   to deal with serial version incompatibilities. You can have two
   classes that are compile-time compatible, and runtime-compatible,
   but not serial-version compatible.

 + Not quite so good API. Requires attributes to implement an Attribute
   interface, be serializable and so on. We know where marker interfaces
   lead. (Now we do, at least!)

Berin's Question
----------------
Berin asked something like this sometime:

  "How can I get a list (or collection) of all classes with a certain
attribute?"

The academic answer is:

  "You can't. Since classes are loaded on demand, and may even be
generated
   dynamically, there is no way to get a list of all classes, let alone
filter
   that non-existent list based on attributes."

The shorter answer is:

  "Iterate over all jars, for each class found, ask for its attributes."


My Question
-----------
When attaching an Inheritable attribute to a class, it means that any
subclass
will also have that attribute attached to it. This is fairly obvious.

When attaching an Inheritable attribute to a method, it means that any
method
in a subclass that overrides the method will also have that attribute
attached 
to it. This is also fairly obvious.

But: What happens if you attach an inheritable attribute to a field or a
Constructor?

Fields aren't inherited in the same way as methods:

    public class Test {

        public static class Super {
            protected int v = 0;
        
            public void sup () {
                System.out.println ("v = " + v);
            }
        }
    
        public static class Sub extends Super {
            protected int v = 1;
        
            public void sub () {
                System.out.println ("v = " + v);
            }
        }
    
        public static void main (String[] args) throws Exception {
            Sub sub = new Sub ();
            sub.sup ();
            sub.sub ();
        }
    }

Output is:

    v = 0
    v = 1

Constructors aren't inherited, so their attributes shouldn't either, or?
Fields are inherited, but not in the same way as methods, so their
attributes
shouldn't follow as well, or?

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to