gumbo.util.relation
Interface Relation

All Superinterfaces:
Delegatable, Disposable
All Known Subinterfaces:
Associate, TreeNode
All Known Implementing Classes:
AbstractAssociate, AbstractRelation, AbstractTreeNode, Relations.RelationImm, Relations.RelationWrapper, TreeNodes.TreeNodeImm, TreeNodes.TreeNodeWrapper

public interface Relation
extends Disposable, Delegatable

An "abstract" base interface for a member of a data relationship (see Relationship). A relation can belong to none or one relationship, but a relation's delegator can belong to more than one relationship (by having a relation delegate for each relationship). Concrete subclasses are responsible for setting the relationship, for defining the connection types between relations, and for defining the pattern of delegation. Depending of the delegation pattern, a connection can be a reference to some other relation, or to a delegator associated with some other relation.

Since a relation is intended as a navigable service for reaching a delegator, this interface implements Disposable as a convenience for delegators. Unless otherwise noted, disposing a relation disconnects it from its relationship and adjacent relations but does not dispose the relationship or those relations.

A relation in a relationship (relationship is set non-null) is "live", and one not in a relationship (relationship is set null) is "dead". A relation must be live before it can be connected to any relations (pre condition); and, all relations reachable through relation connections must be in the same relationship (post condition). If a relation is dead it must have no connections (post condition).

Patterns for setting a relation's relationship include early and late binding, and manual and automatic binding. Early binding involves setting the relationship when a relation is constructed. Late binding involves creating an "dead" relation and setting it later. The client can explicitly set the relationship before trying to use it, or the system can automatically set it when a dead relation is connected to a live one. The relation contract can be enforced actively, by updating relation relationships and connections, or passively, by throwing an exception.

Delegation patterns are public, private, and mixed. In public delegation the relation can be made public, and client navigation occurs between relations, not the relation delegators. In private delegation the relation is kept private, and client navigation occurs between relation delegators. In mixed delegation the relation can be made public, but client navigation occurs between relation delegators. (See IntersectionTreeNode for an example of mixed delegation.)

Serialization of a relationship and its relations requires special handling. To avoid stack overflow during serialization of a relation network, a relation must declare its connection references as transient and let the relationship send the relationship members. To avoid forward references during deserialization, a relation must write and read its connection references after normal serialization (see implWriteConnections(), implReadConnections()). The rest of the relation, including its delegator reference, is written and read using normal serialization, with the caveat that the relationship will probably be read first, before all the relations, which may cause a relation's implReadConnections() to be called before the subclass has a chance to initialize itself.

Version:
$Revision: 1.2 $
Author:
Jon Barrilleaux (jonb@jmbaai.com) of JMB and Associates Inc.

Method Summary
 boolean canFindRelation(java.lang.Object delegator)
          Convenience method that returns true if a relation corresponding to a delegator can be found in this relation's relationship.
 Relation findRelation(java.lang.Object delegator)
          Convenience method for getting the relation corresponding to a delegator in this relation's relationship.
 ConnectionField.EventOut getAddedConnectionOut()
          Sends a connection involving this relation after the connection is created.
 Relationship getRelationship()
          Gets the relationship that this relation belongs to.
 ConnectionField.EventOut getRemovingConnectionOut()
          Sends a connection involving this relation before the connection is destroyed.
 void implReadConnections(java.io.ObjectInputStream s)
          Called by the system during deserialization when this relation should read its connection references from the serial input stream.
 void implWriteConnections(java.io.ObjectOutputStream s)
          Called by the system during serialization when this relation should write its connection references to the serial output stream.
 void setRelationship(Relationship relationship)
          Sets the relationship that this relation belongs to.
 
Methods inherited from interface gumbo.util.Disposable
dispose, isDisposed
 
Methods inherited from interface gumbo.util.Delegatable
getDelegator, initDelegator, isDelegatorInited
 

Method Detail

setRelationship

public void setRelationship(Relationship relationship)
Sets the relationship that this relation belongs to. If this relation is going dead implementors must satisfy the relation contract by actively disconnecting it from all relations, or passively throwing an exception. Unless otherwise noted, no change in relationship is ignored.

Parameters:
relationship - The relationship. Null if none (dead).

getRelationship

public Relationship getRelationship()
Gets the relationship that this relation belongs to.

Returns:
The relationship. If null, this relation is dead; if non-null it is live.

canFindRelation

public boolean canFindRelation(java.lang.Object delegator)
Convenience method that returns true if a relation corresponding to a delegator can be found in this relation's relationship.

Parameters:
delegator - The delegator. Returns false if null.
Returns:
The result. False if this relation is not in a relationship or delegator is null.

findRelation

public Relation findRelation(java.lang.Object delegator)
Convenience method for getting the relation corresponding to a delegator in this relation's relationship.

Parameters:
delegator - The delegator. Never null.
Returns:
The delegator's relation. Never null.
Throws:
java.lang.IllegalArgumentException - Delegator is null.
java.lang.IllegalStateException - This relation is not in a relationship.

getAddedConnectionOut

public ConnectionField.EventOut getAddedConnectionOut()
Sends a connection involving this relation after the connection is created. Never null.


getRemovingConnectionOut

public ConnectionField.EventOut getRemovingConnectionOut()
Sends a connection involving this relation before the connection is destroyed. Never null.


implWriteConnections

public void implWriteConnections(java.io.ObjectOutputStream s)
                          throws java.io.IOException,
                                 java.lang.ClassNotFoundException
Called by the system during serialization when this relation should write its connection references to the serial output stream. Connection references must be declared as transient so that they are written only by this method, which is called after all relationship objects (delegators and relations) have been written during normal serialization.

Parameters:
s - Output stream. Never null.
java.io.IOException
java.lang.ClassNotFoundException

implReadConnections

public void implReadConnections(java.io.ObjectInputStream s)
                         throws java.io.IOException,
                                java.lang.ClassNotFoundException
Called by the system during deserialization when this relation should read its connection references from the serial input stream. Connection references must be declared as transient so that they are read only by this method, which is called after all relationship objects (delegators and relations) have been read during normal serialization.

Parameters:
s - Output stream. Never null.
java.io.IOException
java.lang.ClassNotFoundException