Hi, I have reactivated my code for restricted/roled types.
The basic idea is that one can define a type that can only be used as a nested element in a type container. The type may not be used at the top-level.
The main usecase is to remove the need for type containers to implement all the allXX methods for current conditions/selectors etc.
For example there is an "or" condition, and an "or" selector.
The patch allows these two to be defined as restricted typedefs:
<typedef name="or" contract="org.apache.tools.ant.taskdefs.condition.Condition" classname="org.apache.tools.ant.taskdefs.condition.Or"/>
<typedef name="or" contract="org.apache.tools.ant.types.selectors.FileSelector" classname="org.apache.tools.ant.types.selectors.OrSelector"/>
These may be placed in a antlib.
The idea would be to make an Ant antlib.xml containing all the conditions. selectors,
mappers and filters.
The user-level issues would be:
Is the attribute "contact" a good name for this attribute (use "role", "restrict", "instanceof" or ?).
Should this be a separate task and not typedef.
For example:
<nestedtype name="or" instanceof="org.apache.tools.ant.taskdefs.condition.Condition"
classname="org.apache.tools.ant.taskdefs.condition.Or"/>
Peter
Index: src/main/org/apache/tools/ant/taskdefs/Definer.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Definer.java,v retrieving revision 1.50 diff -u -r1.50 Definer.java --- src/main/org/apache/tools/ant/taskdefs/Definer.java 9 Feb 2004 21:05:19 -0000 1.50 +++ src/main/org/apache/tools/ant/taskdefs/Definer.java 12 Feb 2004 16:31:55 -0000 @@ -48,17 +48,20 @@ public abstract class Definer extends DefBase { private String name; private String classname; - private File file; - private String resource; + private String contract; - private int format = Format.PROPERTIES; - private boolean definerSet = false; - private int onError = OnError.FAIL; - private String adapter; - private String adaptTo; + private File file; + private String resource; - private Class adapterClass; - private Class adaptToClass; + private int format = Format.PROPERTIES; + private boolean definerSet = false; + private int onError = OnError.FAIL; + private String adapter; + private String adaptTo; + + private Class adapterClass; + private Class adaptToClass; + private Class contractClass; /** * Enumerated type for onError attribute @@ -414,6 +417,21 @@ this.adaptToClass = adaptToClass; } + /** + * Set the classname of the class that the definition + * is restricted to. + * + * @param contract the name of the contract class + */ + public void setContract(String contract) { + this.contract = contract; + } + + /** + */ + protected void setContractClass(Class contractClass) { + this.contractClass = contractClass; + } /** * Add a definition using the attributes of Definer @@ -442,6 +460,10 @@ adaptToClass = Class.forName(adaptTo, true, al); } + if (contract != null) { + contractClass = Class.forName(contract, true, al); + } + AntTypeDefinition def = new AntTypeDefinition(); def.setName(name); def.setClassName(classname); @@ -449,6 +471,7 @@ def.setAdapterClass(adapterClass); def.setAdaptToClass(adaptToClass); def.setClassLoader(al); + def.setContractClass(contractClass); if (cl != null) { def.checkClass(getProject()); } Index: src/main/org/apache/tools/ant/IntrospectionHelper.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/IntrospectionHelper.java,v retrieving revision 1.77 diff -u -r1.77 IntrospectionHelper.java --- src/main/org/apache/tools/ant/IntrospectionHelper.java 9 Feb 2004 21:05:16 -0000 1.77 +++ src/main/org/apache/tools/ant/IntrospectionHelper.java 12 Feb 2004 16:31:55 -0000 @@ -1285,15 +1285,36 @@ Object addedObject = null; Method addMethod = null; - Class clazz = helper.getComponentClass(elementName); - if (clazz == null) { - return null; + AntTypeDefinition restrictedDefinition = + findRestrictedDefinition(helper, elementName, addTypeMethods); + if (restrictedDefinition != null) { + addMethod = findMatchingMethod( + restrictedDefinition.getContractClass(), addTypeMethods); + if (addMethod == null) { + throw new BuildException( + "Ant Internal Error - contract mismatch for " + + elementName); + } + addedObject = restrictedDefinition.create(project); + if (addedObject == null) { + throw new BuildException( + "Failed to create object " + elementName + + " of type " + restrictedDefinition.getTypeClass(project)); + } } - addMethod = findMatchingMethod(clazz, addTypeMethods); - if (addMethod == null) { - return null; + + if (addedObject == null) { + Class clazz = helper.getComponentClass(elementName); + if (clazz == null) { + return null; + } + addMethod = findMatchingMethod(clazz, addTypeMethods); + if (addMethod == null) { + return null; + } + addedObject = helper.createComponent(elementName); } - addedObject = helper.createComponent(elementName); + if (addedObject == null) { return null; } @@ -1388,4 +1409,33 @@ return matchedMethod; } + /** + * + */ + private AntTypeDefinition findRestrictedDefinition( + ComponentHelper helper, String componentName, List methods) { + AntTypeDefinition definition = null; + Class matchedDefinition = null; + + List definitions = helper.getRestrictedDefinitions(componentName); + if (definitions == null) { + return null; + } + for (int i = 0; i < definitions.size(); ++i) { + AntTypeDefinition d = (AntTypeDefinition) definitions.get(i); + Method method = findMatchingMethod(d.getContractClass(), methods); + if (method != null) { + if (matchedDefinition == null) { + matchedDefinition = d.getContractClass(); + definition = d; + } else if (!d.getContractClass().isAssignableFrom(matchedDefinition)) { + throw new BuildException( + "ambiguous: roles for " + componentName + " " + + matchedDefinition.getClass() + " and " + + d.getContractClass()); + } + } + } + return definition; + } } Index: src/main/org/apache/tools/ant/AntTypeDefinition.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/AntTypeDefinition.java,v retrieving revision 1.10 diff -u -r1.10 AntTypeDefinition.java --- src/main/org/apache/tools/ant/AntTypeDefinition.java 9 Feb 2004 21:05:16 -0000 1.10 +++ src/main/org/apache/tools/ant/AntTypeDefinition.java 12 Feb 2004 16:31:55 -0000 @@ -34,6 +34,7 @@ private Class adapterClass; private Class adaptToClass; private String className; + private Class contractClass; private ClassLoader classLoader; /** @@ -84,6 +85,23 @@ */ public String getClassName() { return className; + } + + /** + * for restricted types set the contract class + * that this type matches. + * @param contractClass the class that this type matches + */ + public void setContractClass(Class contractClass) { + this.contractClass = contractClass; + } + + /** + * @return the class that this type matches, null if not + * restricted. + */ + Class getContractClass() { + return contractClass; } /** Index: src/main/org/apache/tools/ant/ComponentHelper.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/ComponentHelper.java,v retrieving revision 1.33 diff -u -r1.33 ComponentHelper.java --- src/main/org/apache/tools/ant/ComponentHelper.java 9 Feb 2004 21:05:16 -0000 1.33 +++ src/main/org/apache/tools/ant/ComponentHelper.java 12 Feb 2004 16:31:56 -0000 @@ -17,10 +17,14 @@ package org.apache.tools.ant; +import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; import java.util.HashSet; import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.HashMap; import java.util.Properties; import java.util.Set; import java.util.Stack; @@ -53,6 +57,9 @@ * @since Ant1.6 */ public class ComponentHelper { + /** Map of component name to lists of restricted definitions */ + private Map restrictedDefinitions = new HashMap(); + /** Map from component name to anttypedefinition */ private AntTypeTable antTypeTable; @@ -158,6 +165,12 @@ for (Iterator i = helper.checkedNamespaces.iterator(); i.hasNext();) { checkedNamespaces.add(i.next()); } + // Add the restricted definitions + for (Iterator i = helper.restrictedDefinitions.entrySet().iterator(); + i.hasNext();) { + Map.Entry entry = (Map.Entry) i.next(); + restrictedDefinitions.put(entry.getKey(), entry.getValue()); + } } /** Factory method to create the components. @@ -411,7 +424,11 @@ * @param def an <code>AntTypeDefinition</code> value */ public void addDataTypeDefinition(AntTypeDefinition def) { - updateDataTypeDefinition(def); + if (def.getContractClass() == null) { + updateDataTypeDefinition(def); + } else { + updateRestrictedDefinition(def); + } } /** @@ -614,6 +631,49 @@ return def.sameDefinition(old, project); } + /** + * This returns a list of definitions for + * @param componentName the + * @return the list of restricted definitions for a particular name. + */ + public List getRestrictedDefinitions(String componentName) { + return (List) restrictedDefinitions.get(componentName); + } + + /** + * update the role definition table with a new or + * modified definition. + */ + private void updateRestrictedDefinition(AntTypeDefinition def) { + String name = def.getName(); + synchronized (restrictedDefinitions) { + List list = (List) restrictedDefinitions.get(name); + if (list == null) { + list = new ArrayList(); + restrictedDefinitions.put(name, list); + } + // place the role in the correct place in the list + for (int i = 0; i < list.size(); ++i) { + AntTypeDefinition d = (AntTypeDefinition) list.get(i); + if (d.getContractClass().equals(def.getContractClass())) { + // already present - replace + list.set(i, def); + def = null; + break; + } else if (d.getContractClass().isAssignableFrom( + def.getContractClass())) { + // higher derived + list.add(i, def); + def = null; + break; + } + } + if (def != null) { + list.add(def); + } + } + } + /** * update the component definition table with a new or
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]