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]

Reply via email to