org.flexdock.util

## Class ClassMapping

- java.lang.Object
- - org.flexdock.util.ClassMapping

    public class ClassMapping
    extends java.lang.Object

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.

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 `Foo`, `Bar`, and `Baz`, where `Bar` extends `Foo` and `Baz` extends `Bar`.

     Foo.class
       |-Bar.class
           |-Baz.class

Each of these classes is ultimately a type of `Foo`. Some operation is performed on instances of `Foo` and a set of handler classes are used to handle different types of `Foo`. Adding a mapping between `Foo.class` and `Handler1.class` will create an association between `Foo` and all strict, non-specific subclasses of `Foo` and `Handler1.class`.

This means that given any instance of `Foo`, calling `getClassMapping(Object obj)` will return `Handler1.class` as the class responsible for handling the `Foo` instance. This includes `Bar` and `Baz`. All types of `Foo` now have a implicit association with `Handler1.class`

However, if this method is subsequently called with arguments of `Baz.class` and `Handler2.class`, then a specific subclass mapping has been introduced for `Baz`. Associations apply to the given class and non-specific subclasses. Thus, the `Handler1.class` association remains for `Foo` and `Bar`, but no longer for `Baz`. Calling `getClassMapping(Object obj)` with an instance of `Baz` will now return `Handler2.class`.

      Foo.class ---------------> (maps to Handler1.class)
        |-Bar.class -----------> (maps to Handler1.class)
            |-Baz.class -------> (maps to Handler2.class)

Polymorphic identity within the class association uses strict subclasses. This means that the `Handler1.class` mapping for `Foo`, `Bar`, and all non-specific subclasses will hold true. However, if `Foo` happens to implement the interface `Qwerty`, the class mapping relationship will not hold true for all implementations of `Qwerty`. Only subclasses of `Foo`.

      Foo.class (implements Qwerty) ----------------> (maps to Handler1.class)
        |-Bar.class (implements Qwerty) ------------> (maps to Handler1.class)
            |-Baz.class (implements Qwerty) --------> (maps to Handler2.class)
      Asdf.class (implements Qwerty) ---------------> (maps to nothing)

Author:
  Christopher Butler

### Constructor Summary

Constructors
Constructor and Description
`ClassMapping(java.lang.Class defaultClass, java.lang.Object defaultInstance)` Creates a new `ClassMapping` instance with the specified default values.

### Method Summary

Methods
`void` `addClassMapping(java.lang.Class key, java.lang.Class value)` Adds a mapping between the key `Class` and the specified `value`.
`void` `addClassMapping(java.lang.Class key, java.lang.Class value, java.lang.Object instance)` Adds a mapping between the key `Class` and both the specified `value` and specified object instance..
`void` `addClassMapping(java.lang.Object obj, java.lang.Class value)` Adds a mapping between the `Class` type of the specified `Object` and the specified `value`.
`java.lang.Object` `getClassInstance(java.lang.Class key)` Returns the `Object` instance associated with the specified `Class`.
`java.lang.Class` `getClassMapping(java.lang.Class key)` Returns the `Class` associated with the specified `Class`.
`java.lang.Class` `getClassMapping(java.lang.Object obj)` Returns the `Class` associated with the `Class` of the specified `Object`.
`java.lang.Object` `getDefaultInstance()` Returns the default `Object` used for situations in which there is no internal instance mapping.
`java.lang.Class` `getDefaultMapping()` Returns the default `Class` used for situations in which there is no internal class mapping.
`java.lang.Class` `removeClassMapping(java.lang.Class key)` Removes any existing class mappings for the `Class` type of the specified `Object`.
`java.lang.Class` `removeClassMapping(java.lang.Object obj)` Removes any existing class mappings for the `Class` type of the specified `Object`.

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

### Constructor Detail

#### ClassMapping

    public ClassMapping(java.lang.Class defaultClass,
                java.lang.Object defaultInstance)

Creates a new `ClassMapping` instance with the specified default values. All calls to `getClassMapping(Class key)` for this `ClassMapping` in which a specific mapping cannot be found will return the specified `defaultClass`. All calls to `getClassInstance(Class key)` in which a specific mapping cannot be found will return the specified `defaultInstance`.

Parameters:
  `defaultClass` - the default class used by this `ClassMapping`
  `defaultInstance` - the default object instance used by this `ClassMapping`

### Method Detail

#### addClassMapping

    public void addClassMapping(java.lang.Object obj,
                       java.lang.Class value)

Adds a mapping between the `Class` type of the specified `Object` and the specified `value`. This method calls `getClass()` on the specified `Object` and dispatches to `addClassMapping(Class key, Class value)`. If either `obj` or `value` are `null`, then this method returns with no action taken. The `value` class may later be retrieved by calling `getClassMapping(Class key)` using the specified `key` class (`obj.getClass()`) or any subclass thereof for which a specific class mapping does not already exist.

Parameters:
  `obj` - the `Object` whose `Class` will be mapped to the specified `value`.
  `value` - the `Class` to be associated with the specified key
See Also:
  `addClassMapping(Object, Class)`, `getClassMapping(Object)`, `getClassMapping(Class)`, `removeClassMapping(Object)`, `removeClassMapping(Class)`

#### addClassMapping

    public void addClassMapping(java.lang.Class key,
                       java.lang.Class value)

Adds a mapping between the key `Class` and the specified `value`. If either `key` or `value` are `null`, then this method returns with no action taken. This method creates an association between the specified `key` `Class` and all strict, non-specific subclasses and the specified `value` `Class`. The `value` class may later be retrieved by calling getClassMapping(Class key) using the specified `key` class or any subclass thereof for which a specific class mapping does not already exist.

Parameters:
  `key` - the `Class` to be mapped to the specified `value`.
  `value` - the `Class` to be associated with the specified key
See Also:
  `addClassMapping(Class, Class, Object)`, `getClassMapping(Class)`, `removeClassMapping(Class)`

#### addClassMapping

    public void addClassMapping(java.lang.Class key,
                       java.lang.Class value,
                       java.lang.Object instance)

Adds a mapping between the key `Class` and both the specified `value` and specified object instance.. If either `key` or `value` are `null`, then this method returns with no action taken. This method creates an association between the specified `key` `Class` and all strict, non-specific subclasses and the specified `value` `Class`. The `value` class may later be retrieved by calling `getClassMapping(Class key)` using the specified `key` class or any subclass thereof for which a specific class mapping does not already exist.

This method also creates an optional mapping between the `key` and a particular object instance, defined by the `instance` parameter. If `instance` is non-`null`, then a mapping is defined between `key` and all strict, non-specific subclasses and the object instance itself. The `instance` object may later be retrieved by calling `getClassInstance(Class key)` using the specified `key` class or any subclass thereof for which a specific instance mapping does not already exist. If `instance` is `null`, then no instance mapping is created.

Parameters:
  `key` - the `Class` to be mapped to the specified `value`.
  `value` - the `Class` to be associated with the specified key
  `instance` - the object instance to be associated with the specified key
See Also:
  `getClassMapping(Class)`, `getClassInstance(Class)`, `removeClassMapping(Class)`

#### removeClassMapping

    public java.lang.Class removeClassMapping(java.lang.Object obj)

Removes any existing class mappings for the `Class` type of the specified `Object`. This method calls `getClass()` on the specified `Object` and dispatches to `removeClassMapping(Class key)`. If `obj` is `null`, then this method returns `null`.

Removing the mapping for the specified `Class` will also remove it for all non-specific subclasses. This means that subclasses of the specified `Class` will require specific mappings if the it is desired for the existing mapping behavior for these classes to remain the same.

If any instance mappings exist for the specified `Class`, they are also removed. This means non-specific subclass instance mappings will also be removed.

Parameters:
  `obj` - the `Object` whose `Class` will be removed from the internal mapping
Returns:
  the `Class` whose mapping has been removed
See Also:
  `removeClassMapping(Class)`, `addClassMapping(Object, Class)`, `getClassMapping(Object)`, `getClassInstance(Class)`

#### removeClassMapping

    public java.lang.Class removeClassMapping(java.lang.Class key)

Removes any existing class mappings for the `Class` type of the specified `Object`. This method calls `getClass()` on the specified `Object` and dispatches to `removeClassMapping(Class key)`. If `obj` is `null`, then this method returns `null`.

Removing the mapping for the specified `Class` will also remove it for all non-specific subclasses. This means that subclasses of the specified `Class` will require specific mappings if the it is desired for the existing mapping behavior for these classes to remain the same.

If any instance mappings exist for the specified `Class`, they are also removed. This means non-specific subclass instance mappings will also be removed.

Parameters:
  `key` - the `Class` whose internal mapping will be removed
Returns:
  the `Class` whose mapping has been removed
See Also:
  `addClassMapping(Class, Class)`, `addClassMapping(Class, Class, Object)`, `getClassMapping(Object)`, `getClassInstance(Class)`

#### getClassMapping

    public java.lang.Class getClassMapping(java.lang.Object obj)

Returns the `Class` associated with the `Class` of the specified `Object`. If `obj` is `null`, this method will return the value retrieved from `getDefaultMapping()`. Otherwise, this method calls `obj.getClass()` and dispatches to `getClassMapping(Class key)`.

If no mapping has been defined for the specified `Class`, then it's superclass is checked, and then that classes' superclass, and so on until `java.lang.Object` is reached. If a mapping is found anywhere within the superclass hierarchy, then the mapped `Class` is returned. Otherwise, the value returned by `getDefaultMapping()` is returned.

Parameters:
  `obj` - the `Object` whose `Class's` internal mapping will be returned
Returns:
  the `Class` that is mapped internally to the specified key `Class`
See Also:
  `getDefaultMapping()`, `addClassMapping(Object, Class)`, `removeClassMapping(Object)`

#### getClassMapping

    public java.lang.Class getClassMapping(java.lang.Class key)

Returns the `Class` associated with the specified `Class`. If `key` is `null`, this method will return the value retrieved from `getDefaultMapping()`. If no mapping has been defined for the specified `Class`, then it's superclass is checked, and then that classes' superclass, and so on until `java.lang.Object` is reached. If a mapping is found anywhere within the superclass hierarchy, then the mapped `Class` is returned. Otherwise, the value returned by `getDefaultMapping()` is returned.

Parameters:
  `key` - the `Class` whose internal mapping will be returned
Returns:
  the `Class` that is mapped internally to the specified `key`
See Also:
  `getDefaultMapping()`, `addClassMapping(Class, Class)`, `removeClassMapping(Class)`

#### getClassInstance

    public java.lang.Object getClassInstance(java.lang.Class key)

Returns the `Object` instance associated with the specified `Class`. If `key` is `null`, this method will return the value retrieved from `getDefaultInstance()`. If no mapping has been defined for the specified `Class`, then it's superclass is checked, and then that classes' superclass, and so on until `java.lang.Object` is reached. If an instance mapping is found anywhere within the superclass hierarchy, then the mapped `Object` is returned. Otherwise, the value returned by `getDefaultInstance()` is returned.

Parameters:
  `key` - the `Class` whose internal mapping will be returned
Returns:
  the `Object` instance that is mapped internally to the specified `key`
See Also:
  `getDefaultInstance()`, `addClassMapping(Class, Class, Object)`, `removeClassMapping(Class)`

#### getDefaultMapping

    public java.lang.Class getDefaultMapping()

Returns the default `Class` used for situations in which there is no internal class mapping. This property is read-only and is initialized within the `ClassMapping` constructor.

Returns:
  the default `Class` used for situations in which there is no internal class mapping.
See Also:
  `ClassMapping(Class, Object)`

#### getDefaultInstance

    public java.lang.Object getDefaultInstance()

Returns the default `Object` used for situations in which there is no internal instance mapping. This property is read-only and is initialized within the `ClassMapping` constructor.

Returns:
  the default `Object` used for situations in which there is no internal instance mapping.
See Also:
  `ClassMapping(Class, Object)`