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
    Modifier and Type | Method and Description
    --- | ---
    `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)`