ClassMap.java :  » XML-UI » JAXX » jaxx » Java Open Source

Java Open Source » XML UI » JAXX 
JAXX » jaxx » ClassMap.java
/*
 * Copyright 2006 Ethan Nicholas. All rights reserved.
 * Use is subject to license terms.
 */
package jaxx;

import jaxx.reflect.*;

import java.util.*;

/** A Map implementation which uses Classes as keys.  <code>ClassMap</code> differs from typical maps 
  * in that it takes subclasses into account;  mapping a class to a value also maps all subclasses of 
  * that class to the value.
  * <p>
  * A <code>get</code> operation will return the value associated with the class itself, or failing
  * that, with its nearest ancestor for which there exists a mapping.
  */
public class ClassMap extends HashMap {
    /** Keeps track of automatically-added Classes so we can distinguish them from user-added
      * Classes.  Unknown Classes are automatically added to the map during <code>get</code>
      * calls to speed up subsequent requests, but they must be updated when the mappings
      * for their superclasses are modified.
      */
    private List/*<ClassDescriptor>*/ autoKeys = new ArrayList/*<ClassDescriptor>*/();


    /** Returns the value associated with the key <code>Class</code>.  If the class itself does not have
      * a mapping, its superclass will be checked, and so on until an ancestor class with a mapping is 
      * located.  If none of the class' ancestors have a mapping, <code>null</code> is returned.
      *
      *@param key the class to check
      *@return the mapping for the class
      */
    public Object get(Object key) {
        Object result = null;
        ClassDescriptor c = (ClassDescriptor) key;
        while (c != null) {
            result = super.get(c);
            if (result != null)
                break;
            c = c.getSuperclass();
        }

        if (result == null && ((ClassDescriptor) key).isInterface()) {
            result = get(ClassDescriptorLoader.getClassDescriptor(Object.class));
        }
        
        if (c != key && result != null) { // no mapping for the class itself, but found one for a superclass
            put(key, result);
            autoKeys.add(key);
        }
        return result;
    }
    
    
    /** Associates a value with a class and all of its descendents.
      *
      *@param key the class to map
      *@param value the value to map to the class
      *@return the old value associated with the class
      */
    public Object put(Object key, Object value) {
        if (!(key instanceof ClassDescriptor))
            throw new IllegalArgumentException("expected ClassDescriptor, got " + key);
        if (autoKeys.size() > 0) { // remove all automatic keys which descend from the class being modified
            ClassDescriptor c = (ClassDescriptor) key;
            Iterator/*<Class>*/ i = autoKeys.iterator();
            while (i.hasNext()) {
                ClassDescriptor auto = (ClassDescriptor) i.next();
                if (c.isAssignableFrom(auto)) {
                    i.remove();
                    remove(auto);
                }
            }
        }
        return super.put(key, value);
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.