The Partner Classes in the One-To-Many Situation
When implementing the classes at the ends of the association in the one-to-many situation, you must differentiate between the
many end and the
one end. At the
many end things look more or less like they did in the one-to-one situation, but at the one end things are different. Let's have a look at the
many end first. The
setMyWife operation in the
Man class is implemented as follows.
public void setMyWife(Woman element) {
if ( this.f_marriage != null ) {
// this man is already married, remove the old marriage
((Marriage)this.f_marriage).clean();
}
if ( element != null ) {
// create the new marriage
this.f_marriage = new Marriage(this, element);
} else {
this.f_marriage = null;
}
}
You still need to check whether this man is already married, but you do not have to check anymore whether the new wife is married. She is allowed to be married multiple times.
On the many end, the implementation of the Woman class differs to a greater extent. First the type of the field that refers to the association class is no longer Marriage, instead it is java.util.Set. It holds a collection of Marriage instances. Second, as in the normal case, the implementation of the Woman class must have the following operations:
- a set operation with a collection as parameter: sets the collection of husbands to be the given collection.
- an add operation with a single object as parameter, as explained above: adds a single husband.
- an add operation with a collection as parameter: adds all elements in the parameter collection to the set of husbands.
- a remove operation with a single object as parameter: removes a single husband.
- a remove operation with a collection as parameter: removes all elements in the parameters collection from the set of husbands.
a clear operation that removes all associated objects: leaves the set of husbands empty.
A closer look at the add and remove operations that take a single object as parameter shows that they are the most complex ones. They are implemented as follows:
public void addToMyHusbands(Man element) {
if ( element != null ) {
if ( element.getMarriage() != null ) {
((Marriage)element.getMarriage()).clean();
}
new Marriage(element, this);
}
}
public void removeFromMyHusbands(Man element) {
if ( element != null ) {
if ( element.getMarriage() != null ) {
((Marriage)element.getMarriage()).clean();
}
}
}
In the
addToMyHusbands operation an existing marriage of the new husband is deleted. In the
removeFromMyHusbands operation the existing marriage of the removed husbandwhich is the one with this woman instanceis deleted. You simply reuse the existing
clean operation in
Marriage to take care of upholding the ABACUS rules.
Another operation that is worth examining is the one that enables a Woman object to use the role name myHusbands to refer to the set of Man instances it is related to. It is implemented as follows.
public Set getMyHusbands() {
Set /*(Man)*/ result = new HashSet( /*Man*/);
Iterator it = this.f_marriage.iterator();
while ( it.hasNext() ) {
Marriage elem = (Marriage) it.next();
result.add( elem.getMyHusbands() );
}
return result;
}
As in the one-to-one situation, you use the
f_marriage field to obtain the values that should be in the result set. Remember that this field is of type
java.util.Set. Therefore you need to iterate over its elements and obtain the value of the
getMyHusbands operation for every element. Note that the
getMyHusbands operation in the
Marriage class returns a single
Man object, even though its name suggests otherwise. Its name is derived from the role name at the
Man end, which is
myHusbands.
The Partner Classes in the Many-To-Many Situation
As can be expected, the implementation of the classes at the ends of the association in the many-to-many situation looks very much like the implementation of the Woman class in the one-to-many situation. And, because of the symmetry, both classes can be implemented in the same manner. Both classes have a field that holds a set of Marriage instances, and a number of operations that implement the addition and removal of partner instances. Again, the most interesting operations are the addition and removal of a single element. We'll have a look at the addToMyHusbands operation in the Woman class first.
public void addToMyHusbands(Man element) {
boolean isPresent = false;
// ensure that the new husband is not allready present
Iterator it = f_marriage.iterator();
while ( it.hasNext() && !isPresent ) {
Marriage elem = (Marriage) it.next();
if ( elem.getMyHusbands() == element ) {
isPresent = true;
}
}
if ( !isPresent ) {
f_marriage.add(new Marriage(element, this));
}
}
Most of the code in this operation is there because we need to ensure that the collection of husbands is a set and not a bag or sequence. For this we iterate over the set of
Marriage instances of this woman. Only if the new husband is not present in the set of husbands a new
Marriage instance is created.
Likewise, before removing an element from the set of husbands, you first need to find it. Therefore, we need to iterate over the set of Marriage instances of this woman in the removeFromMyHusbands operation as well. When you have found the corresponding element you can remove it, using the clean operation in the Marriage class.
public void removeFromMyHusbands(Man element) {
Marriage foundElem = null;
Iterator it = f_marriage.iterator();
while ( it.hasNext() ) {
Marriage elem = (Marriage) it.next();
if ( elem.getMyHusbands() == element ) {
foundElem = elem;
}
}
if ( foundElem != null ) {
((Marriage)foundElem).clean();
this.f_marriage.remove(foundElem);
}
}
Finally ...
Now you know how to implement associations with and without association classes. As we mentioned before, building a good implementation is not a trivial matter and is a good argument for generating code from a UML model. Just think of the situation where the modeler suddenly decides to upgrade an association to an association class. That would be a disaster for the programmer; he would need to start all over again. And, just as in the case for the normal associations, the association classes can all be implemented in the same manner. You only need to adjust the role names. We can conclude only this: We desperately need some better code generation tools on the market.
Mind Teasers
As we did last time, we would like to leave you with a few puzzles that will make you understand association classes better.
- Try to model the situation where a person may work for a bank, thus having a employee-employer relationship, while at the same time that person is a client to the bank. The person has a mortgage from this bank, and the bank-client relationship should hold information on, for instance, loan sum, security, and monthly payment. The employee-employer relationship should hold information on, for instance, salary, start date, and function description.
- An association class is often compared with a link table in a database. The records in the link table hold the keys of the records in the other tables that it relates, but it may also have attributes of its own. See for yourself if you can agree with this comparison. Are there differences or not?
- Other people suggest that all associations are comparable with link tables. As a consequence of this you might choose to implement normal associations (without association classes) in the same way as association with association classes. What do you think are the advantages and disadvantages of this approach?