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]
