1 Interaction schemas: Programming with Generic Actions a better title?

This section introduces generic actions that are used by interaction schemas. The actions are generic because they are parameterized by a class graph. The class graph is best thought of as a UML class diagram that is automatically computed from the Java source code or using reflection (introspection) after loading of the classes.

The list of actions we discuss is not intended to be exhaustive. What characterizes the ac- tions is that they are special cases of a traverse action with suitable visitors. Therefore we start with the traverse action. As example class graph we use the library example with four classes in Fig. 1? The mother of all actions is the traverse action [DJ99]:

Class ClassGraph{ Object traverse(Object o, TravSpec s, Dictionary dict, Visitor v); }

The meaning is to traverse object o following traversal specification s with source equal to the class of o. Dict is a dictionary of variables defined by s. The visitor specifies what needs to be done during the traversal and may use the variables contained in dict. A tra- versal specification s is of the form “from A1 via A2 via A3 … to An”. It can either be explicit, listing all the nodes along the path in the class graph, or it can be succinct, listing only some of the nodes along the path provided there is a unique path between those nodes. A1 is called the source of the traversal and An the target. More complex traversal specifications are beyond the scope of this paper and are discussed in [PCL95, LP97, L96].

Example: Integer lentBooks = (Integer) cg.traverse(lib, new TravSpec(“from lib:Library via u:User to Copy”), dict, new Visitor() { int count; void start() {count = 0;} void before (Copy host) { System.out.println( “library”+lib+“user”+u+“copy”+host); count++; } void getReturnVal(){new Integer(count);} }

} We compute the number of lent books with a traversal from Library via User to Copy. During the traversal we also print all triples of library, user and copy whenever we visit a Copy-object. At a Copy-object we also increase count by one. We use here the concept of an inner class in Java. Visitor is an abstract class provided by a class library with empty implementations of a before and after method for every application class. The traversal specification assumes that there is a unique path in the class graph from Library to User and from User to Copy.

We subdivide the actions into two kinds: structure-change, non structure-change actions. A structure-change action may modify the traversed object while a non structure-change action never modifies the traversed object. We cover the structure-change actions tra- verse, add, delete, set and the non structure-change actions fetch, gather, iterate?

The add action

Class ClassGraph{ Object add(Object o, TravSpec s, Object toAdd); } traverses o following the unique path specified by s and adds toAdd to the end of the last collection along this path. Intermediate objects are created if needed. For a given class graph, add can be implemented by a traversal following s and a visitor that has a before method on the edge leading to the last collection on the path. It is important to note that the add action is more generic than the traverse action because in a visitor we cannot talk about the last collection class along a path.

Example: cg.add(u, new TravSpec(“from User to Copy”), c); Takes the unique path from User to Copy and adds c to the collection from User to Copy. If there is a CheckOutItem–object between User and Copy (see Fig. 2?) with a 0..* cardi- nality from User to CheckOutItem and a 1..1 cardinality from CheckOutItem to Copy, then a new CheckOutItem object would be created as part of the add.

Some of the actions of our system are implemented by a set of overloaded methods. The fetch action, in its simplest form, allows us to retrieve a distant object

Class ClassGraph{ Object fetch(Object o, TravSpec s); }

The meaning is to traverse object o following s and when we arrive at the target of s to the return the found object. Assumes that s defines a unique path without collections in the class graph. A variant of the fetch action allows us to fetch an object from a collec- tion.

Class ClassGraph{

Object fetch(Object o, TravSpec s, Predicate p); } interface Predicate { boolean match(Object); }

The meaning is to traverse o following s and when we arrive at a target object to return the first one that matches predicate p.

Example: Book b = cg.fetch( lib, new Strategy (“to Book”), new Predicate() { boolean match(Object obj){ return((Book) obj).get_isbn() == 678); } } )

Traverses from Library to Book and checks for a book that has the correct ISBN number. This example uses again Java inner classes.

Class ClassGraph{ Object delete(Object o, TravSpec s, Predicate p); }

The meaning is to traverse o following s and when we arrive at a target object to delete all that match predicate p.

Class ClassGraph{ Vector gather(Object o, TravSpec s); }

The meaning is to traverse object o following s and when we arrive at the target of s to return all found objects. A variant of the gather action allows us to gather objects satisfy- ing a predicate p.

Class ClassGraph{ Vector gather(Object o, TravSpec s, Predicate p); }

The meaning is to traverse o following s and to collect all target objects that satisfy predi- cate p into vector.