You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by le...@apache.org on 2003/12/28 21:40:29 UTC

cvs commit: jakarta-commons-sandbox/attributes/api/src/java/org/apache/commons/attributes RuntimeAttributeRepository.java

leosutic    2003/12/28 12:40:29

  Added:       attributes/api/src/java/org/apache/commons/attributes
                        RuntimeAttributeRepository.java
  Log:
  Added ability to programmatically define attributes
  for a class.
  
  Revision  Changes    Path
  1.1                  jakarta-commons-sandbox/attributes/api/src/java/org/apache/commons/attributes/RuntimeAttributeRepository.java
  
  Index: RuntimeAttributeRepository.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.commons.attributes;
  
  import java.lang.reflect.Field;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Method;
  import java.util.Set;
  import java.util.Map;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Class used to define attributes programmatically for a class.
   * It is recommended that this class is used in the static initializer for
   * a class:
   * <pre><code>
   * public class RuntimeSample extends SuperSample implements SampleIFJoin {
   *
   *     static {
   *         try {
   *             RuntimeAttributeRepository rar = 
   *                 new RuntimeAttributeRepository (RuntimeSample.class);
   *
   *             rar.addClassAttribute (new ThreadSafe ());
   *             
   *             rar.addFieldAttribute ("field", new ThreadSafe ());
   *             
   *             rar.addMethodAttribute ("someMethod", new Class[]{}, 
   *                 new Dependency ( SampleService.class, "sample-some-method1" ));
   *             
   *             rar.addParameterAttribute ("methodWithAttributes", 
   *                 new Class[]{ Integer.TYPE, Integer.TYPE }, 1, 
   *                 new ThreadSafe ());
   * 
   *             rar.addReturnAttribute ("methodWithAttributes", 
   *                 new Class[]{ Integer.TYPE, Integer.TYPE }, 
   *                 new Dependency ( SampleService.class, "sample-return" ));
   *             
   *             rar.addMethodAttribute ("someMethod", 
   *                 new Class[]{ Integer.TYPE },  
   *                 new Dependency ( SampleService.class, "sample-some-method2" ));
   *             
   *             Attributes.setAttributes (rar);
   *         } catch (Exception e) {
   *             throw new Error ("Unable to set attribute information: " + e.toString ());
   *         }
   *     }
   * </code></pre>
   */
  public class RuntimeAttributeRepository implements AttributeRepositoryClass {
      
      /**
       * Flag indicating whether this repository is modifiable.
       * Once sealed, a repository can't be un-sealed.
       */
      private boolean sealed = false;
      
      /**
       * Set of class attributes. See javadoc for <code>AttributeRepositoryClass</code> for structure.
       */
      private final Set classAttributes = new HashSet ();
      
      /**
       * Set of field attributes. See javadoc for <code>AttributeRepositoryClass</code> for structure.
       */
      private final Map fieldAttributes = new HashMap ();
      
      /**
       * Set of ctor attributes. See javadoc for <code>AttributeRepositoryClass</code> for structure.
       */
      private final Map constructorAttributes = new HashMap ();
      
      /**
       * Set of method attributes. See javadoc for <code>AttributeRepositoryClass</code> for structure.
       */
      private final Map methodAttributes = new HashMap ();
      
      /**
       * Class we are defining attributes for.
       */
      private final Class clazz;
      
      /**
       * Create a new runtime repository.
       */
      public RuntimeAttributeRepository (Class clazz) {
          this.clazz = clazz;
      }
      
      /**
       * Adds a new attribute to the class itself.
       */
      public void addClassAttribute (Object attribute) {
          classAttributes.add (attribute);
      }
      
      /**
       * Convenience function to check if the repository is sealed.
       * 
       * @throws IllegalStateException if sealed
       */
      private void checkSealed () throws IllegalStateException {
          if (sealed) {
              throw new IllegalStateException ("RuntimeAttributeRepository has been sealed.");
          }
      }
      
      /**
       * Convenience method to get and initialize an enry in the method or
       * constructor attribute map.
       */
      private List getMethodOrConstructorAttributeBundle (Map map, String signature, int numSlots) {
          List bundle = (List) map.get (signature);
          if (bundle == null) {
              bundle = new ArrayList ();
              map.put (signature, bundle);
              
              for (int i = 0; i < numSlots; i++) {
                  bundle.add (new HashSet ());
              }
          }
          
          return bundle;
      }
      
      /**
       * Convenience method to get and initialize an entry in the method map.
       *
       * @return a fully initialized List (as defined for the <code>AttributeRepositoryClass</code> interface)
       *         for the given method.
       */
      private List getMethodAttributeBundle (Method m) {
          String signature = Util.getSignature (m);
          if (m.getDeclaringClass () != clazz) {
              throw new IllegalArgumentException ("There is no " + signature + " in " + clazz.getName () + ". It is defined in " + 
                  m.getDeclaringClass ().getName ());
          }
          
          return getMethodOrConstructorAttributeBundle (methodAttributes, signature, m.getParameterTypes ().length + 2);
      }
      
      /**
       * Convenience method to get and initialize an entry in the constructor map.
       *
       * @return a fully initialized List (as defined for the <code>AttributeRepositoryClass</code> interface)
       *         for the given constructor.
       */
      private List getConstructorAttributeBundle (Constructor c) {
          String signature = Util.getSignature (c);
          if (c.getDeclaringClass () != clazz) {
              throw new IllegalArgumentException ("There is no " + signature + " in " + clazz.getName () + ". It is defined in " + 
                  c.getDeclaringClass ().getName ());
          }
          
          return getMethodOrConstructorAttributeBundle (constructorAttributes, signature, c.getParameterTypes ().length + 1);
      }
      
      /**
       * Adds an attribute to a field.
       */
      public void addFieldAttribute (String name, Object attribute) throws NoSuchFieldException, SecurityException {
          addFieldAttribute (clazz.getDeclaredField (name), attribute);
      }
      
      /**
       * Adds an attribute to a field.
       */
      public void addFieldAttribute (Field f, Object attribute) {
          checkSealed ();
          String signature = f.getName ();
          if (f.getDeclaringClass () != clazz) {
              throw new IllegalArgumentException ("There is no " + signature + " in " + clazz.getName () + ". It is defined in " + 
                  f.getDeclaringClass ().getName ());
          }
          
          Set attributeSet = (Set) fieldAttributes.get (signature);
          if (attributeSet == null) {
              attributeSet = new HashSet ();
              fieldAttributes.put (signature, attributeSet);
          }
          
          attributeSet.add (attribute);
      }
      
      /**
       * Adds an attribute to a constructor. The constructor is obtained via the getDeclaredConstrutor method 
       * of the class this repository defines.
       */
      public void addConstructorAttribute (Class[] parameters, Object attribute) throws NoSuchMethodException, SecurityException {
          addConstructorAttribute (clazz.getDeclaredConstructor (parameters), attribute);
      }
      
      /**
       * Adds an attribute to a constructor.
       */
      public void addConstructorAttribute (Constructor c, Object attribute) {
          checkSealed ();
          List bundle = getConstructorAttributeBundle (c);
          Set ctorAttrs = (Set) bundle.get (0);
          ctorAttrs.add (attribute);
      }
      
      /**
       * Adds an attribute to a method. The method is obtained via the getDeclaredMethod method 
       * of the class this repository defines.
       */
      public void addMethodAttribute (String name, Class[] parameters, Object attribute) throws NoSuchMethodException, SecurityException {
          addMethodAttribute (clazz.getDeclaredMethod (name, parameters), attribute);
      }
      
      public void addMethodAttribute (Method m, Object attribute) {
          checkSealed ();
          List bundle = getMethodAttributeBundle (m);
          Set methodAttrs = (Set) bundle.get (0);
          methodAttrs.add (attribute);
      }
      
      /**
       * Adds an attribute to a parameter of a constructor. The constructor is obtained via the getDeclaredConstrutor method 
       * of the class this repository defines.
       */
      public void addParameterAttribute (Class[] parameters, int parameterIndex, Object attribute) throws NoSuchMethodException, SecurityException {
          addParameterAttribute (clazz.getDeclaredConstructor (parameters), parameterIndex, attribute);
      }
      
      /**
       * Adds an attribute to a parameter of a constructor. 
       */
      public void addParameterAttribute (Constructor c, int parameterIndex, Object attribute) {
          checkSealed ();
          List bundle = getConstructorAttributeBundle (c);
          
          Set parameterAttrs = (Set) bundle.get (parameterIndex + 1);
          parameterAttrs.add (attribute);
      }
      
      
      /**
       * Adds an attribute to a parameter of a method. The method is obtained via the getDeclaredMethod method 
       * of the class this repository defines.
       */
      public void addParameterAttribute (String name, Class[] parameters, int parameterIndex, Object attribute) throws NoSuchMethodException, SecurityException {
          addParameterAttribute (clazz.getDeclaredMethod (name, parameters), parameterIndex, attribute);
      }
      
      /**
       * Adds an attribute to a parameter of a method. The method is obtained via the getDeclaredMethod method 
       * of the class this repository defines.
       */
      public void addParameterAttribute (Method m, int parameterIndex, Object attribute) {
          checkSealed ();
          List bundle = getMethodAttributeBundle (m);
          
          Set parameterAttrs = (Set) bundle.get (parameterIndex + 2);
          parameterAttrs.add (attribute);
      }
      
      /**
       * Adds an attribute to the return value of a method. The method is obtained via the getDeclaredMethod method 
       * of the class this repository defines.
       */
      public void addReturnAttribute (String name, Class[] parameters, Object attribute) throws NoSuchMethodException, SecurityException {
          addReturnAttribute (clazz.getDeclaredMethod (name, parameters), attribute);
      }
      
      /**
       * Adds an attribute to the return value of a method. The method is obtained via the getDeclaredMethod method 
       * of the class this repository defines.
       */
      public void addReturnAttribute (Method m, Object attribute) {
          checkSealed ();
          
          List bundle = getMethodAttributeBundle (m);
          
          Set returnAttrs = (Set) bundle.get (1);
          returnAttrs.add (attribute);
      }
      
      /**
       * Gets the class this repository defines attributes for.
       */
      public Class getDefinedClass () {
          return clazz;
      }
      
      public Set getClassAttributes () {
          return classAttributes;
      }
      
      public Map getFieldAttributes () {
          return fieldAttributes;
      }
      
      public Map getMethodAttributes () {
          return methodAttributes;
      }
      
      public Map getConstructorAttributes () {
          return constructorAttributes;
      }
      
      /**
       * Seals this repository. A sealed repository can't be modified.
       */
      public void seal () {
          sealed = true;
      }
  }
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org