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. The conventions for this implementation are that the associations are held in a chain of ContextLinks, and the relevant context is obtained from an implementation of ContextHolder. So instead of writing something like this in a class definition:

   Object field = new FieldValue();

   Object getField() { return field; }
   void setField(Object value) { field = value; }
 
you would write something like this:
   Object field = new ContextLink(new FieldValue());

   // One holder used with all fields
   ContextHolder contextHolder = Context.getContextHolder();

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

   void setField(Object value) {
       Context c = contextHolder.getContext();
       Context.setInContext(field, c, 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. Moreover, even when a system needs only one context for itself, it may be running in the same Java VM as other software that should be independent and that may also use contexts.

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.

See Also:
ContextLink, getContextHolder(), ContextHoldingStrategy

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
 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(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.
 long getNumber()
          Returns this context's number.
 Context getParent()
          Returns this context's parent 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 Context popContext(ContextHolder h)
          Moves the specified context-holder to the parent of its current context.
static void pushContext(ContextHolder h)
          Moves the specified context-holder to a new child of its current context.
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(long n)
Returns the context that has the indicated number, or null if that context has been discarded or has ceased to exist.

getContextHoldingStrategy

public static ContextHoldingStrategy getContextHoldingStrategy()
Returns the current context-holding strategy.

Initially, the strategy 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.
Throws:
java.lang.Error - (for now) if no value can be found

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 void pushContext(ContextHolder h)
Moves the specified context-holder to a new child of its current context.

popContext

public static Context popContext(ContextHolder h)
Moves the specified context-holder to the parent of its current context.