Interesting... So how come DynamicTag is not compatible with Ant 1.6, when it compiles and works fine with 1.5.1??? Sounds like an incompatible API change to me, which hopefully will be fixed.
I have a few remarks: 1) I favor composition over inheritance. DynamicTag is designed to be composed, either directly, or has a helper (my latest email). But your implementation could easily be refactored a bit to also favor composition instead of inheritance. 2) DynamicTag is lazy, thanks to UnknownElement. Your rewrite is creating the element at parse-time, my implementation does it only at runtime. Again, I favor delaying the instantiation and configuration. Ant should never have mingled parsing of the XML and instantiation of the model in the first place. 3) I'm not sure what your point #2 would not be addresses by DynamicTag. Thanks to UnknownElement, all nested elements of a DynamicTag are resolved according to the same exact semantic as everything in Ant. I much prefer to rely on Ant's (much convoluted black-box) existing mechanism than invent my own, partly because I didn't want to go into reflection (I'm a bit adverse to it), and partly because it makes it more difficult to be adopted by Ant. 4) DynamicTag enforces the cardinality of the nested dynamic elements for free. That's a nice goodie, but granted, more sugar than real useful. 5) Your point #4 is the new feature over DynamicTag as I understand it. I'm not too sure it's better syntactically than explicitly having (composing) several nested elements, each being a dynamic tag of a different type. Your rewrite does add new reflection 'rules', making stuff happen auto-magically thru reflection. I'm not saying it's bad, I'm pointing out it adds some, when DynamicTag doesn't. All that said, you achieve a similar effect, which is what I really care about. If Ant wants to implement this feature still a third way, I'll all for it, provided the feature is available. At least now there are two proposals for it ;-) Something that I wish Ant added was the notion of 'role', to partition the task/type namespace. Both our proposals rely on <taskdef>/<typedef> to register the extension points. But a custom selector, a custom filter, a custom mapper, a custom buildpath (in my case) all share the same type or task namespace (the mapping from element name to class name). There are currently two distinct namespaces, one for tasks, and one for types, and Costin says I'd like to merge the two, when I actually would prefer to have N namespaces, each indexed/keyed by a 'role' string. When a task explicitly declares to accept within it selectors for example, it simply declares it wants instances implementing FileSelector.class from the "selectors" namespace. So the namespace used to resolve the element name to the classname is explicit, rather than implicit, first trying the "tasks" namespace, and then trying the "types" namespace. Classes can of course belong to more than one namespace; <tahoeresolver> could be both a type ("types" namespace), so it can be declared outside <buildpath> and refid'd, but it's also a BuildPathResolver.class, of the "buildpath/resolvers" user-defined (and documented) namespace). I believe one (or both) of the Ant2 proposals had the notion of role, and it's also well defined in Avalon Phoenix, so this is nothing new indeed. Thanks Peter for your interest in this area. I hope others will also look into it. Cheers, --DD -----Original Message----- From: peter reilly [mailto:[EMAIL PROTECTED] Sent: Monday, April 14, 2003 6:50 PM To: [EMAIL PROTECTED] Subject: RE: DynamicTag Hi, I am on holidays, but have followed this thread. I have been playing with DynamicTag and it is quite neat, but there are some issues with it.. I have made some modifications (well rewrite...) 1) DynamicTag uses UnknownElement. This part of ant code is undergoing a number of changes at the moment, and currently DynamicTag does not work with cvs ant. I extracted the stuff that unknownelement does and placed them in a method, this is compatible with apr12 ant cvs and with ant 1.5.x (tested with 1.5.2). 2) I would like to have dynamic tag behavior on the the current task as well as nested elements. 3) I would like to use reflection in the same way as ant uses reflection for setters and creators. 4) I would like to support multiple dynamic types in the same class. I initially considered using only datatypes, but on consideration it does make sense to have tasks as well. The problems with this are: a) tasks that do not extend ant.task get wrapped by ant.taskadapter which may not be what is expected b) tasks have a more complex life cycle that datatypes (init, perform, execute methods) Attached are two files : DynamicElementHelper and DynamicElementTask. Tasks and Datatypes/Sub-elements extend DynamicElementTask. The signature dynamicElement(Type) is used to indicate the type that this method will handle. DynamicElementTask implements DynamicConfigurator, and calls DynamicElementHelper, which looks up the tag name in the projects tasks and datatypes, if found that, the method uses reflection to see if the calling object has a matching dynamicElement method for the type. DynamicElementHelper is written so that if this idea is considered useful, it can be used by IntrospectionHelper, It that case, there would be no need for DynamicElementTask. To do the original example: <buildpath id="tahoebuildpath"> <tahoeresolver destdir="${destdir}" dependencies="${dependencies}" </buildpath> BuildPath.java extends DynamicElementTask and adds a dynamic element handler: // Creates a nested resolver public void dynamicElement(BuildPathResolver resolver) { if (this.resolver != null) throw new BuildException("resolver already defined"); this.resolver = resolver; } And the xml filters: <target name="test" depends="-init" > <xmlchain toDir="./build/chain" extension=".xxx"> <fileset refid="workOnStuf" /> <filter1 attr1="v1" attr2="v2"> <mysubelement .../> </filter1> <xincludefilter .../> <xmlfilter refid="other-filter"/> </xmlchain> </target> and in xml chain: public void dynamicElement(XmlFilter filter) { filters.addElement(filter) } One may also nest the custom filters in the same way as dynamictag by writing a new class public class CustomFilters extends DynamicElementTask { private Vector filters = new Vector(); public void dynamicElement(XmlFilter filter) { filters.addElement(filter); } public Vector getFilters() { return filters;} } and in XmlChain: public void addCustomFilters(CustomFilters customFilters) { this.customFilters = customFilters; } Cheers, Peter Dominique Devienne wrote: >>Two comments: >>1) DynamicTag is fully Ant 1.5.x compatible. No need for 1.6. Just use it >>along side your own classes, and you're good to go. >>2) DynamicTag *relies* on <taskdef> or <typedef> (you can declare your >>custom extension either way), which takes care of all the classloading, >>already has all the special stuff like loaderref. Any enhancement to these >>tasks automatically benefit DynamicTag.