⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classmapping.java

📁 定要上载质量高而定要上载质量高而定要上载质量高而定要上载质量高而定要上载质量高而
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Created on Apr 5, 2005
 */
package org.flexdock.util;

import java.util.WeakHashMap;

/**
 * This class manages associations between classes and object instances. It
 * allows for mappings between a class and its subclasses and another associated
 * class, or an associated instance of a class.
 * <p>
 * This class is useful for "handler" type logic in which a handler class must
 * be mapped to the classes it is designed to handle. Consider the class
 * hierarchy of {@code Foo}, {@code Bar}, and {@code Baz}, where {@code Bar}
 * extends {@code Foo} and {@code Baz} extends {@code Bar}.
 * 
 * <pre>
 * Foo.class
 *   |-Bar.class
 *       |-Baz.class
 * </pre>
 * 
 * Each of these classes is ultimately a type of {@code Foo}. Some operation is
 * performed on instances of {@code Foo} and a set of handler classes are used
 * to handle different types of {@code Foo}. Adding a mapping between
 * {@code Foo.class} and {@code Handler1.class} will create an association
 * between {@code Foo} and all <i>strict, non-specific</i> subclasses of
 * {@code Foo} and {@code Handler1.class}.
 * <p>
 * This means that given any instance of {@code Foo}, calling
 * {@code getClassMapping(Object obj)} will return {@code Handler1.class} as the
 * class responsible for handling the {@code Foo} instance. This includes
 * {@code Bar} and {@code Baz}. All types of {@code Foo} now have a implicit
 * association with {@code Handler1.class}
 * <p>
 * However, if this method is subsequently called with arguments of
 * {@code Baz.class} and {@code Handler2.class}, then a <i>specific</i>
 * subclass mapping has been introduced for {@code Baz}. Associations apply to
 * the given class and <i>non-specific</i> subclasses. Thus, the
 * {@code Handler1.class} association remains for {@code Foo} and {@code Bar},
 * but no longer for {@code Baz}. Calling {@code getClassMapping(Object obj)}
 * with an instance of {@code Baz} will now return {@code Handler2.class}.
 * 
 * <pre>
 *  Foo.class ---------------&gt; (maps to Handler1.class)
 *    |-Bar.class -----------&gt; (maps to Handler1.class)
 *        |-Baz.class -------&gt; (maps to Handler2.class)
 * </pre>
 * 
 * Polymorphic identity within the class association uses <i>strict</i>
 * subclasses. This means that the {@code Handler1.class} mapping for
 * {@code Foo}, {@code Bar}, and all non-specific subclasses will hold true.
 * However, if {@code Foo} happens to implement the interface {@code Qwerty},
 * the class mapping relationship will not hold true for all implementations of
 * {@code Qwerty}. Only subclasses of {@code Foo}.
 * 
 * <pre>
 *  Foo.class (implements Qwerty) ----------------&gt; (maps to Handler1.class)
 *    |-Bar.class (implements Qwerty) ------------&gt; (maps to Handler1.class)
 *        |-Baz.class (implements Qwerty) --------&gt; (maps to Handler2.class)
 *  Asdf.class (implements Qwerty) ---------------&gt; (maps to nothing)
 * </pre>
 * 
 * @author Christopher Butler
 */
public class ClassMapping {
    private WeakHashMap classes;

    private WeakHashMap instances;

    private Class defaultClass;

    private Object defaultInstance;

    /**
     * Creates a new {@code ClassMapping} instance with the specified default
     * values. All calls to {@code getClassMapping(Class key)} for this
     * {@code ClassMapping} in which a specific mapping cannot be found will
     * return the specified {@code defaultClass}. All calls to
     * {@code getClassInstance(Class key)} in which a specific mapping cannot be
     * found will return the specified {@code defaultInstance}.
     * 
     * @param defaultClass
     *            the default class used by this {@code ClassMapping}
     * @param defaultInstance
     *            the default object instance used by this {@code ClassMapping}
     */
    public ClassMapping(Class defaultClass, Object defaultInstance) {
        this.defaultClass = defaultClass;
        this.defaultInstance = defaultInstance;

        classes = new WeakHashMap(4);
        instances = new WeakHashMap(4);
    }

    /**
     * Adds a mapping between the {@code Class} type of the specified
     * {@code Object} and the specified {@code value}. This method calls
     * {@code getClass()} on the specified {@code Object} and dispatches to
     * {@code addClassMapping(Class key, Class value)}. If either {@code obj}
     * or {@code value} are {@code null}, then this method returns with no
     * action taken. The {@code value} class may later be retrieved by calling
     * {@code getClassMapping(Class key)} using the specified {@code key} class ({@code obj.getClass()})
     * or any subclass thereof for which a specific class mapping does not
     * already exist.
     * 
     * @param obj
     *            the {@code Object} whose {@code Class} will be mapped to the
     *            specified {@code value}.
     * @param value
     *            the {@code Class} to be associated with the specified <b>key</b>
     * @see #addClassMapping(Object, Class)
     * @see #getClassMapping(Object)
     * @see #getClassMapping(Class)
     * @see #removeClassMapping(Object)
     * @see #removeClassMapping(Class)
     */
    public void addClassMapping(Object obj, Class value) {
        Class key = obj == null ? null : obj.getClass();
        addClassMapping(key, value);
    }

    /**
     * Adds a mapping between the key {@code Class} and the specified
     * {@code value}. If either {@code key} or {@code value} are {@code null},
     * then this method returns with no action taken. This method creates an
     * association between the specified {@code key} {@code Class} and all
     * strict, non-specific subclasses and the specified {@code value}
     * {@code Class}. The {@code value} class may later be retrieved by calling
     * getClassMapping(Class key) using the specified {@code key} class or any
     * subclass thereof for which a specific class mapping does not already
     * exist.
     * 
     * @param key
     *            the {@code Class} to be mapped to the specified {@code value}.
     * @param value
     *            the {@code Class} to be associated with the specified <b>key</b>
     * @see #addClassMapping(Class, Class, Object)
     * @see #getClassMapping(Class)
     * @see #removeClassMapping(Class)
     */
    public void addClassMapping(Class key, Class value) {
        addClassMapping(key, value, null);
    }

    /**
     * Adds a mapping between the key {@code Class} and both the specified
     * {@code value} and specified object instance.. If either {@code key} or
     * {@code value} are {@code null}, then this method returns with no action
     * taken. This method creates an association between the specified
     * {@code key} {@code Class} and all strict, non-specific subclasses and the
     * specified {@code value} {@code Class}. The {@code value} class may later
     * be retrieved by calling {@code getClassMapping(Class key)} using the
     * specified {@code key} class or any subclass thereof for which a specific
     * class mapping does not already exist.
     * <p>
     * This method also creates an optional mapping between the {@code key} and
     * a particular object instance, defined by the {@code instance} parameter.
     * If {@code instance} is non-{@code null}, then a mapping is defined
     * between {@code key} and all strict, non-specific subclasses and the
     * object instance itself. The {@code instance} object may later be
     * retrieved by calling {@code getClassInstance(Class key)} using the
     * specified {@code key} class or any subclass thereof for which a specific
     * instance mapping does not already exist. If {@code instance} is
     * {@code null}, then no instance mapping is created.
     * 
     * @param key
     *            the {@code Class} to be mapped to the specified {@code value}.
     * @param value
     *            the {@code Class} to be associated with the specified <b>key</b>
     * @param instance
     *            the object instance to be associated with the specified <b>key</b>
     * @see #getClassMapping(Class)
     * @see #getClassInstance(Class)
     * @see #removeClassMapping(Class)
     */
    public void addClassMapping(Class key, Class value, Object instance) {
        if (key == null || value == null)
            return;

        synchronized (classes) {
            classes.put(key, value);
        }

        if (instance != null) {
            synchronized (instances) {
                instances.put(key, instance);
            }
        }
    }

    /**
     * Removes any existing class mappings for the {@code Class} type of the
     * specified {@code Object}. This method calls {@code getClass()} on the

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -