home | career | drupal | java | mac | mysql | perl | scala | uml | unix

Commons Attributes example source code file (Attributes.java)

This example Commons Attributes source code file (Attributes.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Commons Attributes tags/keywords

cachedrepository, class, class, collection, collection, constructor, field, method, multipleattributeserror, nullpointerexception, object, object, reflection, repositoryerror, repositoryerror, util

The Commons Attributes Attributes.java source code

/*
 * Copyright 2003-2004 The Apache Software Foundation
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.attributes;

import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

/**
 * API for accessing attributes.
 *
 * <h3>General Notes on Errors
 * 
 * All Methods in this class may throw <code>RepositoryError or subclasses thereof.
 * This Error is thrown if an attribute repository can not be loaded for some Exceptional
 * reason.
 * 
 * <h4>Rationale for Errors instead of Exceptions
 *
 * The methods in this class throws <code>Errors instead of Exceptions.
 * This rationale behind this is that:
 *
 * <ul> 
 * <li>The programmer should not have to wrap all accesses to 
 *     the Attributes API in a try/catch clause.
 * <li>An Exception being thrown here is caused by missing classes
 *     or other "Error-like" conditions.
 * </ul>
 *
 * <h3>Null References
 *
 * <p>If a parameter to a method may not be null, and a null is passed to the
 * method, a {@link java.lang.NullPointerException} will be thrown, with the
 * parameter name in the message.
 *
 * <p>Rationale for using this instead of {@link java.lang.IllegalArgumentException}
 * is that it is more precise - the reference was null.
 *
 * <h3>Performance Notes
 * <p>The process of loading attributes for a class is a
 * (relatively) time-consuming process, as it involves some dynamic linking 
 * in the form of inheritable attributes, a lot of reflection and so on. However,
 * once loaded the attributes are cached, so repeated access to them are fast.
 * But despite this the process of finding one attribute of a given type
 * or such operations does involve some iteration of HashSets that <b>runs in linear
 * time in the number of attributes associated with the program element</b>, and you should
 * avoid accessing attributes in your innermost loops if you can avoid it. For 
 * example, instead of:
 *
 * <pre>
 * Class myClass = ...;
 * for (int i = 0; i < 10000; i++) {
 *     if (Attributes.hasAttributeType (myClass, MyAttribute.class)) {
 *         doThis(myClass);
 *     } else {
 *         doThat(myClass);
 *     }
 * }
 * </code>
* * do: * * <pre> * Class myClass = ...; * boolean shouldDoThis = Attributes.hasAttributeType (myClass, MyAttribute.class); * for (int i = 0; i < 10000; i++) { * if (shouldDoThis) { * doThis(myClass); * } else { * doThat(myClass); * } * } * </code> * * if the loop should run at maximum speed. * * @since 2.1 */ public class Attributes { /** * A cache of attribute repositories. The map used is a WeakHashMap keyed on the * Class owning the attribute repository. This works because Class objects use * the identity function to compare for equality - i.e. if the two classes * have the same name, and are loaded from the same two ClassLoaders, then * <code>class1 == class2. Also, (class1.equals(class2)) == (class1 == * class2)</code>. This means that a once a Class reference has been garbage-collected, * it can't be re-created. Thus we can treat the cache map as a normal map - the only * entries that will ever disappear are those we can't look up anyway because we * can't ever create the key for them! * * <p>Also, this will keep the cache from growing too big in environments where * classes are loaded and unloaded all the time (i.e. application servers). */ private final static Map classRepositories = new WeakHashMap (); /** * List used to keep track of the initialization list in getCachedRepository. * Since the method is synchronized static, we only need one list. */ private static List initList = new ArrayList (); private synchronized static CachedRepository getCachedRepository (Class clazz) throws RepositoryError, CircularDependencyError { if (initList.contains (clazz)) { List dependencyList = new ArrayList (); dependencyList.addAll (initList); dependencyList.add (clazz); throw new CircularDependencyError (clazz.getName (), dependencyList); } else if (classRepositories.containsKey (clazz)) { CachedRepository cr = (CachedRepository) classRepositories.get (clazz); return cr; } else { // Indicate that we're loading it. CachedRepository cached = null; initList.add (clazz); try { Class attributeRepo = null; AttributeRepositoryClass repo = EmptyAttributeRepositoryClass.INSTANCE; try { attributeRepo = Class.forName (clazz.getName () + "$__attributeRepository", true, clazz.getClassLoader ()); repo = (AttributeRepositoryClass) attributeRepo.newInstance (); } catch (ClassNotFoundException cnfe) { // OK, just means no repo available, so default to empty one. repo = EmptyAttributeRepositoryClass.INSTANCE; } catch (InstantiationException ie) { throw new RepositoryError (ie); } catch (IllegalAccessException iae) { throw new RepositoryError (iae); } cached = new DefaultCachedRepository (clazz, repo); classRepositories.put (clazz, cached); if (repo != null) { Util.validateRepository (clazz, repo); } } finally { initList.remove (initList.size () - 1); } return cached; } } /** * Selects from a collection of attributes one attribute with a given class. * * @param attrs the collection of attribute instances to select from. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * @return the attribute instance, or <code>null of none could be found. * @throws MultipleAttributesError if the collection contains more than one * instance of the specified class. */ private static Object getAttribute (Collection attrs, Class attributeClass) throws MultipleAttributesError { Object candidate = null; Iterator iter = attrs.iterator (); while (iter.hasNext ()) { Object attr = iter.next (); if (attr.getClass () == attributeClass) { if (candidate == null) { candidate = attr; } else { throw new MultipleAttributesError (attributeClass.getName ()); } } } return candidate; } /** * Get one attributes of a given type from a class. * * @param clazz the class. May not be <code>null. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * @return the attribute instance, or <code>null of none could be found. * @throws MultipleAttributesError if the collection contains more than one * instance of the specified class. * * @since 2.1 */ public static Object getAttribute (Class clazz, Class attributeClass) throws RepositoryError, MultipleAttributesError { return getAttribute (getAttributes (clazz), attributeClass); } /** * Get one attributes of a given type from a field. * * @param field the field. May not be <code>null. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * @return the attribute instance, or <code>null of none could be found. * @throws MultipleAttributesError if the collection contains more than one * instance of the specified class. * * @since 2.1 */ public static Object getAttribute (Field field, Class attributeClass) throws RepositoryError, MultipleAttributesError { return getAttribute (getAttributes (field), attributeClass); } /** * Get one attributes of a given type from a constructor. * * @param constructor the constructor. May not be <code>null. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * @return the attribute instance, or <code>null of none could be found. * @throws MultipleAttributesError if the collection contains more than one * instance of the specified class. * * @since 2.1 */ public static Object getAttribute (Constructor constructor, Class attributeClass) throws RepositoryError, MultipleAttributesError { return getAttribute (getAttributes (constructor), attributeClass); } /** * Get one attributes of a given type from a method. * * @param method the method. May not be <code>null. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * @return the attribute instance, or <code>null of none could be found. * @throws MultipleAttributesError if the collection contains more than one * instance of the specified class. * * @since 2.1 */ public static Object getAttribute (Method method, Class attributeClass) throws RepositoryError, MultipleAttributesError { return getAttribute (getAttributes (method), attributeClass); } /** * Get one attributes of a given type from a parameter. * * @param method the method. May not be <code>null. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * @param parameter index of the parameter in the method's parameter list. * @return the attribute instance, or <code>null of none could be found. * @throws MultipleAttributesError if the collection contains more than one * instance of the specified class. * @throws ParameterIndexOutOfBoundsException if the parameter index is < 0 or greater than the number * of parameters the method accepts. * * @since 2.1 */ public static Object getParameterAttribute (Method method, int parameter, Class attributeClass) throws RepositoryError, MultipleAttributesError { return getAttribute (getParameterAttributes (method, parameter), attributeClass); } /** * Get one attributes of a given type from a constructor's parameter. * * @param constructor the constructor. May not be <code>null. * @param parameter index of the parameter in the method's parameter list. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * @return the attribute instance, or <code>null of none could be found. * @throws MultipleAttributesError if the collection contains more than one * instance of the specified class. * @throws ParameterIndexOutOfBoundsException if the parameter index is < 0 or greater than the number * of parameters the constructor accepts. * * @since 2.1 */ public static Object getParameterAttribute (Constructor constructor, int parameter, Class attributeClass) throws RepositoryError, MultipleAttributesError { return getAttribute (getParameterAttributes (constructor, parameter), attributeClass); } /** * Get one attributes of a given type from a method's return value. * * @param method the method. May not be <code>null. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * @return the attribute instance, or <code>null of none could be found. * @throws MultipleAttributesError if the collection contains more than one * instance of the specified class. * * @since 2.1 */ public static Object getReturnAttribute (Method method, Class attributeClass) throws RepositoryError, MultipleAttributesError { return getAttribute (getReturnAttributes (method), attributeClass); } /** * Gets all attributes for a class. * * @param clazz the class. May not be <code>null. * * @since 2.1 */ public static Collection getAttributes (Class clazz) throws RepositoryError { if (clazz == null) { throw new NullPointerException ("clazz"); } return getCachedRepository (clazz).getAttributes (); } /** * Gets all attributes for a method. * * @param method the method. May not be <code>null. * * @since 2.1 */ public static Collection getAttributes (Method method) throws RepositoryError { if (method == null) { throw new NullPointerException ("method"); } return getCachedRepository (method.getDeclaringClass()).getAttributes (method); } /** * Gets all attributes for a parameter of a method. * * @param method the method. May not be <code>null. * @param parameter the index of the parameter in the method's parameter list. * @throws ParameterIndexOutOfBoundsException if the parameter index is < 0 or greater than the number * of parameters the method accepts. * * @since 2.1 */ public static Collection getParameterAttributes (Method method, int parameter) throws RepositoryError { if (method == null) { throw new NullPointerException ("method"); } return getCachedRepository (method.getDeclaringClass()).getParameterAttributes (method, parameter); } /** * Gets all attributes for a parameter of a constructor. * * @param constructor the constructor. May not be <code>null. * @param parameter the index of the parameter in the constructor's parameter list. * @throws ParameterIndexOutOfBoundsException if the parameter index is < 0 or greater than the number * of parameters the constructor accepts. * * @since 2.1 */ public static Collection getParameterAttributes (Constructor constructor, int parameter) throws RepositoryError { if (constructor == null) { throw new NullPointerException ("constructor"); } return getCachedRepository (constructor.getDeclaringClass()).getParameterAttributes (constructor, parameter); } /** * Gets all attributes for the return value of a method. * * @param method the method. May not be <code>null. * * @since 2.1 */ public static Collection getReturnAttributes (Method method) throws RepositoryError { if (method == null) { throw new NullPointerException ("method"); } return getCachedRepository (method.getDeclaringClass()).getReturnAttributes (method); } /** * Gets all attributes for a field. * * @param field the field. May not be <code>null. * * @since 2.1 */ public static Collection getAttributes (Field field) throws RepositoryError { if (field == null) { throw new NullPointerException ("field"); } return getCachedRepository (field.getDeclaringClass()).getAttributes (field); } /** * Gets all attributes for a constructor. * * @param constructor the constructor. May not be <code>null. * * @since 2.1 */ public static Collection getAttributes (Constructor constructor) throws RepositoryError { if (constructor == null) { throw new NullPointerException ("constructor"); } return getCachedRepository (constructor.getDeclaringClass()).getAttributes (constructor); } /** * Selects from a collection of attributes only those with a given class. * * @since 2.1 */ private static Collection getAttributes (Collection attrs, Class attributeClass) { HashSet result = new HashSet (); Iterator iter = attrs.iterator (); while (iter.hasNext ()) { Object attr = iter.next (); if (attr.getClass () == attributeClass) { result.add (attr); } } return Collections.unmodifiableCollection (result); } /** * Get all attributes of a given type from a class. For all objects o in the returned * collection, <code>o.getClass() == attributeClass. * * @param clazz the class. May not be <code>null. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * * @since 2.1 */ public static Collection getAttributes (Class clazz, Class attributeClass) throws RepositoryError { return getAttributes (getAttributes (clazz), attributeClass); } /** * Get all attributes of a given type from a field. For all objects o in the returned * collection, <code>o.getClass() == attributeClass. * * @param field the field. May not be <code>null. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * * @since 2.1 */ public static Collection getAttributes (Field field, Class attributeClass) throws RepositoryError { return getAttributes (getAttributes (field), attributeClass); } /** * Get all attributes of a given type from a constructor. For all objects o in the returned * collection, <code>o.getClass() == attributeClass. * * @param constructor the constructor. May not be <code>null. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * * @since 2.1 */ public static Collection getAttributes (Constructor constructor, Class attributeClass) throws RepositoryError { return getAttributes (getAttributes (constructor), attributeClass); } /** * Get all attributes of a given type from a method. For all objects o in the returned * collection, <code>o.getClass() == attributeClass. * * @param method the method. May not be <code>null. * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * * @since 2.1 */ public static Collection getAttributes (Method method, Class attributeClass) throws RepositoryError { return getAttributes (getAttributes (method), attributeClass); } /** * Get all attributes of a given type from a method's parameter. For all objects o in the returned * collection, <code>o.getClass() == attributeClass. * * @param method the method. May not be <code>null. * @param parameter index of the parameter in the method's parameter list * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * @throws ParameterIndexOutOfBoundsException if the parameter index is < 0 or greater than the number * of parameters the method accepts. * * @since 2.1 */ public static Collection getParameterAttributes (Method method, int parameter, Class attributeClass) throws RepositoryError { return getAttributes (getParameterAttributes (method, parameter), attributeClass); } /** * Get all attributes of a given type from a method's parameter. For all objects o in the returned * collection, <code>o.getClass() == attributeClass. * * @param constructor the constructor. May not be <code>null. * @param parameter index of the parameter in the constructor's parameter list * @param attributeClass the type of attribute. May be <code>null, but this will not match anything. * @throws ParameterIndexOutOfBoundsException if the parameter index is < 0 or greater than the number * of parameters the constructor accepts. * * @since 2.1 */ public static Collection getParameterAttributes (Constructor constructor, int parameter, Class attributeClass) throws RepositoryError { return getAttributes (getParameterAttributes (constructor, parameter), attributeClass); } /** * Get all attributes of a given type from a method's return value. For all objects o in the returned * collection, <code>o.getClass() == attributeClass. * * @param method the method * @param attributeClass the type of attribute wanted. May be <code>null, but this will not match anything. * * @since 2.1 */ public static Collection getReturnAttributes (Method method, Class attributeClass) throws RepositoryError { return getAttributes (getReturnAttributes (method), attributeClass); } /** * Convenience function to test whether a collection of attributes contain * an attribute of a given class. * * @since 2.1 */ private static boolean hasAttributeType (Collection attrs, Class attributeClass) { Iterator iter = attrs.iterator (); while (iter.hasNext ()) { Object attr = iter.next (); if (attr.getClass () == attributeClass) { return true; } } return false; } /** * Tests if a class has an attribute of a given type. That is, is there any attribute * <code>attr such that attr.getClass() == attributeClass? * * @param clazz the class. May not be <code>null. * @param attributeClass the type of attribute. May be <code>null, but this will not match anything. * * @since 2.1 */ public static boolean hasAttributeType (Class clazz, Class attributeClass) throws RepositoryError { return hasAttributeType (getAttributes (clazz), attributeClass); } /** * Tests if a field has an attribute of a given type. That is, is there any attribute * <code>attr such that attr.getClass() == attributeClass? * * @param field the field. May not be <code>null. * @param attributeClass the type of attribute. May be <code>null, but this will not match anything. * * @since 2.1 */ public static boolean hasAttributeType (Field field, Class attributeClass) throws RepositoryError { return hasAttributeType (getAttributes (field), attributeClass); } /** * Tests if a constructor has an attribute of a given type. That is, is there any attribute * <code>attr such that attr.getClass() == attributeClass? * * @param constructor the constructor. May not be <code>null. * @param attributeClass the type of attribute. May be <code>null, but this will not match anything. * * @since 2.1 */ public static boolean hasAttributeType (Constructor constructor, Class attributeClass) throws RepositoryError { return hasAttributeType (getAttributes (constructor), attributeClass); } /** * Tests if a method has an attribute of a given type. That is, is there any attribute * <code>attr such that attr.getClass() == attributeClass? * * @param method the method. May not be <code>null. * @param attributeClass the type of attribute. May be <code>null, but this will not match anything. * * @since 2.1 */ public static boolean hasAttributeType (Method method, Class attributeClass) throws RepositoryError { return hasAttributeType (getAttributes (method), attributeClass); } /** * Tests if a method's parameter has an attribute of a given type. That is, is there any attribute * <code>attr such that attr.getClass() == attributeClass? * * @param method the method. May not be <code>null. * @param parameter the index of the parameter in the method's parameter list. * @param attributeClass the type of attribute. May be <code>null, but this will not match anything. * @throws ParameterIndexOutOfBoundsException if the parameter index is < 0 or greater than the number * of parameters the method accepts. * * @since 2.1 */ public static boolean hasParameterAttributeType (Method method, int parameter, Class attributeClass) throws RepositoryError { return hasAttributeType (getParameterAttributes (method, parameter), attributeClass); } /** * Tests if a constructor's parameter has an attribute of a given type. That is, is there any attribute * <code>attr such that attr.getClass() == attributeClass? * * @param constructor the constructor. May not be <code>null. * @param parameter the index of the parameter in the constructor's parameter list. * @param attributeClass the type of attribute. May be <code>null, but this will not match anything. * @throws ParameterIndexOutOfBoundsException if the parameter index is < 0 or greater than the number * of parameters the constructor accepts. * * @since 2.1 */ public static boolean hasParameterAttributeType (Constructor constructor, int parameter, Class attributeClass) throws RepositoryError { return hasAttributeType (getParameterAttributes (constructor, parameter), attributeClass); } /** * Tests if a method's return value has an attribute of a given type. That is, is there any attribute * <code>attr such that attr.getClass() == attributeClass? * * @param method the method. May not be <code>null. * @param attributeClass the type of attribute. May be <code>null, but this will not match anything. * * @since 2.1 */ public static boolean hasReturnAttributeType (Method method, Class attributeClass) throws RepositoryError { return hasAttributeType (getReturnAttributes (method), attributeClass); } /** * Convenience function to test whether a collection of attributes contain * an attribute. * * @since 2.1 */ private static boolean hasAttribute (Collection attrs, Object attribute) throws RepositoryError { return attrs.contains (attribute); } /** * Tests if a class has an attribute. That is, is there any attribute * <code>attr such that attr.equals(attribute)? * * @param clazz the class. May not be <code>null. * @param attribute the attribute to compare to. * * @since 2.1 */ public static boolean hasAttribute (Class clazz, Object attribute) throws RepositoryError { return hasAttribute (getAttributes (clazz), attribute); } /** * Tests if a field has an attribute. That is, is there any attribute * <code>attr such that attr.equals(attribute)? * * @param field the field. May not be <code>null. * @param attribute the attribute to compare to. * * @since 2.1 */ public static boolean hasAttribute (Field field, Object attribute) throws RepositoryError { return hasAttribute (getAttributes (field), attribute); } /** * Tests if a constructor has an attribute. That is, is there any attribute * <code>attr such that attr.equals(attribute)? * * @param constructor the constructor. May not be <code>null. * @param attribute the attribute to compare to. * * @since 2.1 */ public static boolean hasAttribute (Constructor constructor, Object attribute) throws RepositoryError { return hasAttribute (getAttributes (constructor), attribute); } /** * Tests if a method has an attribute. That is, is there any attribute * <code>attr such that attr.equals(attribute)? * * @param method the method. May not be <code>null. * @param attribute the attribute to compare to. * * @since 2.1 */ public static boolean hasAttribute (Method method, Object attribute) throws RepositoryError { return hasAttribute (getAttributes (method), attribute); } /** * Tests if a method's parameter has an attribute. That is, is there any attribute * <code>attr such that attr.equals(attribute)? * * @param method the method. May not be <code>null. * @param parameter the index of the parameter in the method's parameter list. * @param attribute the attribute to compare to. * @throws ParameterIndexOutOfBoundsException if the parameter index is < 0 or greater than the number * of parameters the method accepts. * * @since 2.1 */ public static boolean hasParameterAttribute (Method method, int parameter, Object attribute) throws RepositoryError { return hasAttribute (getParameterAttributes (method, parameter), attribute); } /** * Tests if a constructor's parameter has an attribute. That is, is there any attribute * <code>attr such that attr.equals(attribute)? * * @param constructor the constructor. May not be <code>null. * @param parameter the index of the parameter in the constructor's parameter list. * @param attribute the attribute to compare to. * @throws ParameterIndexOutOfBoundsException if the parameter index is < 0 or greater than the number * of parameters the constructor accepts. * * @since 2.1 */ public static boolean hasParameterAttribute (Constructor constructor, int parameter, Object attribute) throws RepositoryError { return hasAttribute (getParameterAttributes (constructor, parameter), attribute); } /** * Tests if a method's return value has an attribute. That is, is there any attribute * <code>attr such that attr.equals(attribute)? * * @param method the method. May not be <code>null. * @param attribute the attribute to compare to. * * @since 2.1 */ public static boolean hasReturnAttribute (Method method, Object attribute) throws RepositoryError { return hasAttribute (getReturnAttributes (method), attribute); } /** * Set attributes for a given class. The class must not have attributes set for it already * (i.e. you can't redefine the attributes of a class at runtime). This because it * really messes up the concept of inheritable attributes, and because the attribute set * associated with a class is immutable, like the set of methods and fields. * * @param repo The repository. The repository will be sealed before any attributes are * set. This to guarantee that the repository remains constant * during setting. * @throws IllegalStateException if the class whose attributes are defined already have * attributes defined for it (even if it has no attributes). * @since 2.1 */ public static synchronized void setAttributes (RuntimeAttributeRepository repo) throws IllegalStateException { if (repo == null) { throw new NullPointerException ("repo"); } repo.seal (); Class clazz = repo.getDefinedClass (); if (classRepositories.get (clazz) != null) { throw new IllegalStateException (clazz.getName ()); } Util.validateRepository (clazz, repo); DefaultCachedRepository cached = new DefaultCachedRepository (clazz, repo); classRepositories.put (clazz, cached); } }

Other Commons Attributes examples (source code examples)

Here is a short list of links related to this Commons Attributes Attributes.java source code file:

new blog posts

 

Copyright 1998-2014 Alvin Alexander, alvinalexander.com
All Rights Reserved.