Package org.jutil.relation

Provides for component to set up all kinds of bi-directional bindings between objects.

See:
          Description

Class Summary
Reference A class of Relation components for implementing a binding in which the object of the Reference has a relation with only 1 other object. In UML this class is used for implementing multiplicity 1: In Java, you get the following situation. Note that the question mark is represented by a Relation object since we don't know its multiplicity.
ReferenceSet A class of Relation components for implementing a binding in which the object of the Reference has a relation with N other objects.
Relation A class of objects that can be used to set up bi-directional relations between objects. This class provides the general interface that is needed in order to create different types of bindings that can be created by taking two arbitrary multiplicities.
 

Package org.jutil.relation Description

Provides for component to set up all kinds of bi-directional bindings between objects.

Class Diagram

Relation components in a nutshell

Instead of implementing bi-directional bindings yourself, you can add an instance of a subclass to your class that will take care of the binding. This will save you the trouble of keeping the binding consistent. However, you still have to write the specification if you don't want to make the Relation components visible for outsiders.

If you do make them visible, you can reuse the specification of the components. You can do this because the state of a component is completely determined by the bindings it has. All components have a registered(List oldConnections, Relation registered) method which returns true if the current state of the component is one that could be reached by connecting with registered in a state where the component is connected to all Relation objects in oldConnections. Additionally, the have an unregistered(List oldConnections, Relation unregistered) method which returns true if the current state of the component was reached by disconnecting from unregistered when being connected to all components in unregistered.

Example

E.g. you make an 1-N binding between classes A and B, and the components are visible. The UML diagram looks like this:

With the components of this package, we can build this binding as follows:

The code for classes A and B is shown below.


public class A {

 /*o
   o public behavior
   o*/
  public A() {
    _BLink = new Reference(this);
  }

 /*o
   o public behavior
   o
   o post \result == getBLink().getOtherEnd();
   o*/
  public B getB() {
    return (B)_BLink.getOtherEnd();
  }

 /*o
   o public behavior
   o
   o post getBLink().registered(new Singleton(\old(getB())), b.getALink());
   o*/
  public void setB(B b) {
    _BLink.connectTo(b == null ? null : b.getALink());
  }

 /*o
   o public behavior
   o
   o post \result != null;
   o post \result.getObject() == this;
   o*/
  public Reference getBLink() {
    return _BLink;
  }

 /*o 
   o private invariant _BLink != null;
   o*/
  private Reference _BLink;
}

public class B {

 /*o
   o public behavior
   o*/
  public B() {
    _elements = new ReferenceSet(this);
  }

 /*o
   o public behavior
   o
   o post \result == getBLink().getOtherEnd();
   o*/
  public List getAs() {
    return _elements.getOtherEnds();
  }

 /*o
   o public behavior
   o
   o pre a != null;
   o
   o post getReference().registered(\old(getAs()), a.getBLink());
   o*/
  public void addA(A a) {
    _elements.add(a.getBLink());
  }

 /*o
   o public behavior
   o
   o pre a != null;
   o
   o post getALink().unregistered(other);
   o post a.getBLink().unregistered(getALink());
   o*/
  public void removeA(A a) {
    _elements.remove(a.getBLink());
  }

 /*o
   o public behavior
   o
   o post \result != null;
   o post \result.getObject() == this;
   o*/
  public ReferenceSet getALink() {
    return _elements;
  }

 /*o 
   o private invariant _elements != null;
   o*/
  private Reference _elements;
}

If you don't want to make the components publically visible, you will have to write the full specifications of the double binding, which is a pretty hard thing to do. If you don't believe it, take a look at page 597 of Object Oriented Software Construction by Bertrand Meyer. Even he writes a specification (and implementation) that is not correct. If you put a cell 3 to the right of a cell 1, which is already connected to cell 2, cell 2 will still refer to cell 1, but cell 1 will not point back, and thus the class invariant is violated.

Other bindings

In the same manner as above, you can also make 1-1 and N-N bindings. If you want to, you can even make hybrid bindings, just make the side where both Reference and ReferenceSet return a Relation a its link.

Multiple bindings

Of course, if a class has bindings with a number of other classes, you just add a component for each binding.