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]