Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## ix.util.context
Class Context

    java.lang.Object
      ix.util.context.Context

    public final class Context

extends java.lang.Object

A Context is an object that is used as an additional, often implicit, parameter when accessing values, such as in a "get"-method. Instead of a value being stored directly in a field, the field contains a list of associations from contexts to values, arranged so that they can be searched efficiently. The conventions used in this implementation of contexts are that the associations are held in a chain of `ContextLink`s, and the relevant context is obtained from an implementation of `ContextHolder`. So instead of writing something like this in a class definition:

       ValClass field = new FieldValue();

       ValClass getField() {
           return field;
       }

       void setField(ValClass value) {
           field = value;
       }

you would write something like this:

       ContextLink field = new ContextLink(new FieldValue());

       // Here one holder used with all fields, and the holder
       // is obtained when this object is created.
       ContextHolder contextHolder = Context.getContextHolder();

       ValClass getField() {
           Context c = contextHolder.getContext();
           return (ValClass)Context.getInContext(field, c);
       }

       void setField(ValClass value) {
           Context c = contextHolder.getContext();
           Context.setInContext(field, c, value);
       }

An alternative is to use objects that hide some of the details. Here is the same example using a `ContextValue`:

       // Here one holder used with all fields, and the holder
       // is obtained when this object is created.
       ContextHolder contextHolder = Context.getContextHolder();

       ContextValue field = new ContextValue(contextHolder, new FieldValue());

       ValClass getField() {
           return (ValClass)field.get();
       }

       void setField(ValClass value) {
           field.set(value);
       }

Since the defaut holder used when a ContextValue is constructed is the one returned by `Context.getContextHolder()`, the example can be simplified further to:

       ContextValue field = new ContextValue(new FieldValue());

       ValClass getField() {
           return (ValClass)field.get();
       }

       void setField(ValClass value) {
           field.set(value);
       }

A context has few properties of its own. It is simply an object with which the values obtained by context-relative accessors may be associated. Contexts are arranged in a tree: each context has a single parent and a list of children. When there is no value directly associated with a context, a value is inherited from the nearest ancestor context that does have a directly associated value. However, when a value is assigned in a context, it is always associated directly with that context, and the associations between ancestor contexts and values are not changed. This makes it possible to protect the values associated with a context, while still being able to access them, by moving to a descendent context.

An efficient search for the value associated with a context, or inherited from an ancestor, is accomplished by exploiting context numbers. Every context has a number which is assigned when it is created, and newer contexts have higher numbers than older ones. In particular, a context has a higher number than any of its ancestors. The chain of ContextLinks for a given field has links for higher-numbered (newer) contexts first. The algorithm for finding the right value is therefore as follows:

1. Initialize target to the desired context and chain to the relevant chain of ContextLinks.
2. Discard entries for contexts newer than target from the front of chain. If chain becomes null, then there is no value for the current context.
3. At this point, the first of the remaining entries in chain should be for target or for a context older than target. If it's for target, then we're done: return the associated value. Otherwise, set target to the parent of target and return to step 2.

The getInContext method implements that algorithm.

Context-holders are used for two reasons. First, they make it unnecessary to pass contexts as parameters to "get"- and "set"-methods. This makes "context-layered" objects look much more like ordinary objects. Second, a context-holder may be shared by many objects, so that they all change context at once.

However, there is no single way of managing context-holders that is right for every case. In some applications, a single, global context-holder can be used. In others, a number of more local context-holders will be needed.

These problems are partly addressed by context-holding "strategies". A holding strategy provides a method that returns a context-holder, and the Context class holds a current (global) strategy. The static method Context.getContextHolder() asks the current strategy for a holder.

When using contexts, it is typical to fix the holder used by an object when the object is created (as in the examples above). Otherwise, every access to a context-dependent value would involve asking a strategy for a holder and then asking the holder for its current context, rather than just asking a holder for its current context.

See Also:
  `ContextLink`, `getContextHolder()`, `ContextHolder`, `ContextHolder.getContext()`, `ContextHoldingStrategy`, `ContextValue`, `LLQueue`

Field Summary
`(package private) java.util.List` | `children` A collection of this context's children.
`(package private) static ContextHoldingStrategy` | `contextHoldingStrategy` The current context-holding strategy.
`(package private) static long` | `count` The number of contexts that have been created.
`(package private) long` | `number` A number, unique to this context and larger than the number of any context created earlier.
`(package private) static java.util.HashMap` | `numberToContextTable` A mapping from context numbers to (weak references to) contexts.
`(package private) Context` | `parent` This context's parent context.
`static Context` | `rootContext` A context that is an ancestor of all others.

Constructor Summary
`Context()` Create a context with the root context as its parent.
`Context(Context parent)` Create a context with a given parent.

Method Summary
`static void` | `clearContexts()` Removes all contexts except the root context.
`void` | `discard()` Remove this context and all of its descendents from the context tree and the number-to-context table.
`java.util.List` | `getChildren()` Returns an unmodifiable view of this context's children.
`static Context` | `getContext()` Returns the current context from the ContextHolder returned by the current ContextHoldingStrategy.
`static Context` | `getContext(long n)` Returns the context that has the indicated number, or null if that context has been discarded or has ceased to exist.
`static ContextHolder` | `getContextHolder()` Returns the context-holder provided by the current context-holding strategy.
`static ContextHoldingStrategy` | `getContextHoldingStrategy()` Returns the current context-holding strategy.
`static java.lang.Object` | `getInContext(ContextLink cl, Context c)` Searches a chain of ContextLinks to find the value associated with a given context.
`static java.lang.Object` | `getInContext(ContextLink cl, Context c, java.lang.Object defaultValue)` Searches a chain of ContextLinks to find the value associated with a given context and returns a default value if no value can be found.
`long` | `getNumber()` Returns this context's number.
`Context` | `getParent()` Returns this context's parent context.
`static ContextLink` | `getValueLinkInContext(ContextLink cl, Context c)` Searches a chain of ContextLinks to find the link that contains the value associated with a given context.
`static void` | `inContext(ContextHolder h, Context c, java.lang.Runnable r)` Temporarily changes a context-holder's current context around a call to a Runnable's run() method.
`static void` | `inContext(Context c, java.lang.Runnable r)` Calls `inContext(ContextHolder, Context, Runnable)` on the ContextHolder returned by the current ContextHoldingStrategy.
`static Context` | `popContext()` Calls `popContext(ContextHolder)` on the ContextHolder returned by the current ContextHoldingStrategy
`static Context` | `popContext(ContextHolder h)` Moves the specified context-holder to the parent of its current context.
`static void` | `printContextTree()` Prints a description of the current context tree on `Debug.out`.
`static Context` | `pushContext()` Calls `pushContext(ContextHolder)` on the ContextHolder returned by the current ContextHoldingStrategy.
`static Context` | `pushContext(ContextHolder h)` Moves the specified context-holder to a new child of its current context and returns that new context.
`static java.lang.Object` | `requireInContext(ContextLink cl, Context c)` Searches a chain of ContextLinks to find the value associated with a given context and throws an exception if no value can be found.
`static void` | `setContext(Context c)` Sets the context in the ContextHolder returned by the current ContextHoldingStrategy.
`static void` | `setContextHoldingStrategy(ContextHoldingStrategy s)` Sets the current context-holding strategy.
`static void` | `setInContext(ContextLink cl, Context c, java.lang.Object value)` Modifies a chain of ContextLinks to associate a value directly with a given context.
`java.lang.String` | `toString()`

Methods inherited from class java.lang.Object
`clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

Field Detail

### count

    static long count

  The number of contexts that have been created.

### numberToContextTable

    static java.util.HashMap numberToContextTable

  A mapping from context numbers to (weak references to) contexts.

### rootContext

    public static final Context rootContext

  A context that is an ancestor of all others. The root context is often used for default values.

  Unlike any other context, the root context's parent is null.

### contextHoldingStrategy

    static ContextHoldingStrategy contextHoldingStrategy

  The current context-holding strategy.

  See Also:
    `getContextHoldingStrategy()`, `setContextHoldingStrategy(ContextHoldingStrategy s)`, `getContextHolder()`

### number

    final long number

  A number, unique to this context and larger than the number of any context created earlier.

### parent

    final Context parent

  This context's parent context.

### children

    final java.util.List children

  A collection of this context's children.

Constructor Detail

### Context

    public Context()

  Create a context with the root context as its parent.

  The constructor is also used once to create the root context itself, and then it's arranged for the root context's parent to be null.

### Context

    public Context(Context parent)

  Create a context with a given parent. If the parent is null, the root context will be used.

Method Detail

### getNumber

    public long getNumber()

  Returns this context's number.

### getParent

    public Context getParent()

  Returns this context's parent context.

### getChildren

    public java.util.List getChildren()

  Returns an unmodifiable view of this context's children.

### discard

    public void discard()

  Remove this context and all of its descendents from the context tree and the number-to-context table.

### toString

    public java.lang.String toString()

  Overrides:
    `toString` in class `java.lang.Object`

### getContext

    public static Context getContext()

  Returns the current context from the ContextHolder returned by the current ContextHoldingStrategy.

  See Also:
    `ContextHolder.getContext()`

### getContext

    public static Context getContext(long n)

  Returns the context that has the indicated number, or null if that context has been discarded or has ceased to exist.

### setContext

    public static void setContext(Context c)

  Sets the context in the ContextHolder returned by the current ContextHoldingStrategy.

  See Also:
    `ContextHolder.setContext(Context)`

### clearContexts

    public static void clearContexts()

  Removes all contexts except the root context. After this, the root context will have no children, and the only context accessible from its number will be the root context. Finally, it calls the `ContextHoldingStrategy.clearContexts()` method of the current ContextHoldingStrategy. The strategy should set the current context of any holders it knows about to the root context.

### getContextHoldingStrategy

    public static ContextHoldingStrategy getContextHoldingStrategy()

  Returns the current context-holding strategy.

  Initially, the strategy is one that provides a single, global context holder.

  See Also:
    `GlobalHoldingStrategy`

### setContextHoldingStrategy

    public static void setContextHoldingStrategy(ContextHoldingStrategy s)

  Sets the current context-holding strategy.

### getContextHolder

    public static ContextHolder getContextHolder()

  Returns the context-holder provided by the current context-holding strategy.

  See Also:
    `getContextHoldingStrategy()`

### getInContext

    public static java.lang.Object getInContext(ContextLink cl,
                                                Context c)

  Searches a chain of ContextLinks to find the value associated with a given context.

  Returns:
    an Object or null

### getInContext

    public static java.lang.Object getInContext(ContextLink cl,
                                                Context c,
                                                java.lang.Object defaultValue)

  Searches a chain of ContextLinks to find the value associated with a given context and returns a default value if no value can be found.

### requireInContext

    public static java.lang.Object requireInContext(ContextLink cl,
                                                    Context c)

  Searches a chain of ContextLinks to find the value associated with a given context and throws an exception if no value can be found.

  Throws:
    `java.lang.IllegalArgumentException` - if no value can be found

### getValueLinkInContext

    public static ContextLink getValueLinkInContext(ContextLink cl,
                                                    Context c)

  Searches a chain of ContextLinks to find the link that contains the value associated with a given context. Note that the link may be for an ancestor of the specified context.

  Returns:
    a ContextLink or null

### setInContext

    public static void setInContext(ContextLink cl,
                                    Context c,
                                    java.lang.Object value)

  Modifies a chain of ContextLinks to associate a value directly with a given context.

### inContext

    public static void inContext(ContextHolder h,
                                 Context c,
                                 java.lang.Runnable r)

  Temporarily changes a context-holder's current context around a call to a Runnable's run() method.

### pushContext

    public static Context pushContext(ContextHolder h)

  Moves the specified context-holder to a new child of its current context and returns that new context.

### popContext

    public static Context popContext(ContextHolder h)

  Moves the specified context-holder to the parent of its current context.

### pushContext

    public static Context pushContext()

  Calls `pushContext(ContextHolder)` on the ContextHolder returned by the current ContextHoldingStrategy.

### popContext

    public static Context popContext()

  Calls `popContext(ContextHolder)` on the ContextHolder returned by the current ContextHoldingStrategy

### inContext

    public static void inContext(Context c,
                                 java.lang.Runnable r)

  Calls `inContext(ContextHolder, Context, Runnable)` on the ContextHolder returned by the current ContextHoldingStrategy.

### printContextTree

    public static void printContextTree()

  Prints a description of the current context tree on `Debug.out`. Children appear after their parent, indented one more level.

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD