\chapter{Traversal Strategies} % three layers Traversal strategies, for short, strategies, are a layer of abstraction above the class graph layer. In adaptive programming we use three kinds of graphs to reason about programs: we have object graphs and class graphs, familiar from object-oriented programming, and a third layer called the strategy graph layer unique to adaptive programming. % size, traversals of objects, vague yet precise Strategy graphs are often small, much smaller than the class graphs. The purpose of strategy graphs is to define traversals of objects through a set of paths in a class graph. A strategy graph may be viewed as an independent entity which defines vaguely how objects should be traversed. The description is vague since the class graph is left open. However, as soon as a class graph is provided, a strategy defines a very precise set of paths. % adaptive level Strategies are usually developed in the context of a class graph but they are written in such a way that they will work for many other class graphs as well. % compare to something familiar Strategy graphs are a useful concept similar to the concept of a grammar or a finite state machine. Strategy graphs are helpful to define program fragments which collaborate with other program fragments. A grammar defines a parser and a strategy defines a "traverser" in combination with a class graph and an object graph. Strategies are a little more complex than a grammar since they are labeled graphs whose labels refer to two other graphs. A grammar is simpler since it can be viewed as a graph whose labels are tokens. % subgraph In most cases, a strategy in connection with a class graph can be understood in terms of a subgraph of the class graph. The subgraph describes a group of collaborating classes. You think of this subgraph also as a traversal scope which in turn determines how objects are going to be traversed. The strategy is the blueprint of a trip which a a visitor will perform. The blueprint gives only the milestones of the trip and forbids to go through certain hazardous areas. The blue print is then implemented in a detailed map which will tell the visitor very precisely how to travel. In some cases, the blue print must be viewed as a set of paths instead of as a subgraph. %visitors Indeed, the visitor metaphor used above is matching reality. Traversals only traverse objects and we need a mechanism to specify what needs to be done on top of the traversal. Therefore, each traversal gets one or more visitors sent along. But the purpose of this chapter is just to focus on strategies. \section{Notations} %notations DJ supports two notations for strategy graphs: \begin{itemize} \item Line graph notation It allows to express graphs which are a line. An example is: \begin{verbatim} S1 = from BookKeeping via Taxes via Business to LineItem \end{verbatim} Note: naming of strategies not yet supported. If it is not necessary to name a strategy, we introduce it directly in class BookKeeping: \begin{verbatim} BookKeeping { ... via Taxes via Business to LineItem ... } \end{verbatim} In this form, the "from BookKeeping" is not needed. Between the milestones it is also possible to bypass "hazardous areas". An example is: \begin{verbatim} BookKeeping { ... via Taxes via Business bypassing HomeOffice to LineItem ... } \end{verbatim} \item Strategy graph notation This notation is more general than the line graph notation and it allows to express any strategy graph. The bookkeeping example would be expressed as: \begin{verbatim} {BookKeeping -> Taxes Taxes -> Business bypassing HomeOffice Business -> LineItem } source: BookKeeping target: LineItem ... \end{verbatim} Comparison of notations The line graph notation is intuitive and self-explaining. It does not require us to repeat node names to express a line graph, for example. On the other hand, the strategy graph notation is more general. Therefore, we use both notations. The strategy graph notation we use to explain the "details". When we introduce a feature of the line graph notation we show the translation into the strategy graph notation to explain the detailed meaning. \section{Strategies by example} We start with very simple strategies and gradually introduce more complex ones. \subsection{Single edge strategies} %are general Single edge strategies are the most fundamental strategies and they are powerful enough to express any group of collaborating classes which you need for a specific class graph. So why don't we express all strategies as single edge strategies? It turns out that some groups of collaborating classes can be specified much more succinctly as strategies which are not single edge. Single edge strategies are the building blocks of general strategies. Once you understand single edge strategies you have mastered strategies pretty well although multi-edge strategies can lead in rare cases to complications which Demeter/Java will handle automatically for you. The explanation here is for the common case, however Demeter/Java also handles the uncommon case. Indeed, Demeter/Java will always correctly compile your strategies into Java code and you will not have to worry about any exceptions. You should, however, be aware of the fact that strategies are not as easy to implement for multi-edge strategies as the following description will make you believe. For single-edge strategies the following description leads to a correct implementation and you will not have to worry about any lurking pitfalls. We call such strategies ``no-pitfall'' strategies. The pitfalls show up only in certain multi-edge strategies case. The simplest line strategy is of the form "from Container to Weight" in line graph notation and of the form { Container -> Weight } in strategy graph notation. The meaning is to find all Weight-objects contained in a Container-object. The group of collaborating classes consists of all classes ``between'' Container and Weight. How do you find those classes given a class graph? The procedure is quite simple: To find the collaborating classes for ``from A to B" in a class graph C: \begin{itemize} \item Reverse all inheritance edges and call them subclass edges. \item Flatten all inheritance by expanding all common parts to concrete subclasses. \item Find all classes reachable from A and color them red including the edges traversed. \item Find all classes from which B is reachable and color them blue including the edges traversed. \item The group of collaborating classes is the set of classes and edges colored both red and blue. \end{itemize} The graph of collaborating classes we get this way is called the propagation graph for ``from A to B'' and C. The propagation graph is used as control agent for traversing A-objects. When we traverse an A-object and we get to an X-object, the edges outgoing from class X in the propagation graph will determine which objects we visit from the X-objects. If class X has parts p and q in the propagation graph, then we can only visit the p and q parts of the X-object. Computing propagation graphs for ``from A to B" is the fundamental computation, called the From-To computation for, implementing strategies. Indeed, general strategies are also implemented using this fundamental From-To computation. You might get confused from all this talking about From-To computations. You would like to see the group of collaborating classes for your class graph and a ``from A to B" strategy. To allow you to get visual feedback for your strategies, the GUI of Demeter/Java, called AP Studio, allows you to draw your class graph and to point and click in this graph to define your strategy. The preview feature of AP Studio will highlight the selected group of collaborating classes. AP Studio is described in this manual on page ??. Single edge strategies may contain a set of classes which must be bypassed as you go from A to B. You think of the bypassed classes to be taken out of the class graph (together with the edges incident with those classes) before the From-To computation is applied. An example of a single edge strategy with bypassing in line graph notation is: \begin{verbatim} S2 = from BusRoute bypassing Bus to Person \end{verbatim} If it is not necessary to name the strategy, we introduce it directly in class BusRoute: BusRoute { ... bypassing Bus to Person ... } \end{verbatim} In the strategy graph notation the same strategy is written as: \begin{verbatim} { BusRoute -> Person bypassing Bus } source: BusRoute target: Person \end{verbatim} In the general case, bypassing may contain a set of classes, using the curly brace syntax \begin{verbatim} bypassing {X, Y, Z} \end{verbatim} \subsection{Star graph strategies} We leave now the territory of single edge strategies. The star graph strategies are multi target strategies and are, like the single edge strategies, no-pitfall strategies. Sometimes you need to visit objects of a set of classes instead of only one. For example, for a Company-object, you need to find all Customer and all SalesAgent objects. In the line graph notation you write \begin{verbatim} S3 = from Company bypassing {...} to {Customer, SalesAgent} \end{verbatim} or, if there is no need to name the strategy \begin{verbatim} Company { ... bypassing {...} to {Customer, SalesAgent} ... } In the strategy graph notation, we have to repeat the bypassing information: \begin{verbatim} {Company -> Customer bypassing {...} Company -> SalesAgent bypassing {...} } source: Company target: {Customer, SalesAgent} \end{verbatim} We need to explain the meaning of multi-edge strategies. For most cases the following union technique gives the correct result: Consider the decomposition of the strategy graph into its individual edges and compute the propagation graph for each edge with respect to the given class graph. This process has been explained in the section on single edge strategies. To get the propagation graph for the multi-edge strategy we take the union of the propagation graphs of the single edge strategies. In other words, we merge all the propagation graphs together. The union graph is called the propagation graph for the multi-edge strategy and is used to control traversals like in the single edge case. \subsection{Basic join strategies} A basic join strategy joins two single edge strategies together. In line graph notation we write: \begin{verbatim} S4 = from Company bypassing {...} through Customer to Address \end{verbatim} or Company { ... bypassing {...} through Customer to Address ... } \sf{through} may be replaced by \sf{via}. In strategy graph notation: \begin{verbatim} {Company -> Customer bypassing {...} Customer -> Address } source: Company target: Address \end{verbatim} A join strategy may have multiple join points. An example in line graph notation is: \begin{verbatim} S5 = from Company through {Secretary, Manager} to Salary \end{verbatim} This means that we are interested in the salaries of secretaries or managers. In strategy graph notation: \begin{verbatim} { Company -> Secretary, Company -> Manager, Secretary -> Salary, Manager -> Salary } source: Company target: Salary \end{verbatim} \subsection{Edge-controlled strategies} So far we expressed strategies by only referring to classes in the class graph. We call such strategies class-only strategies. Class-only strategies have the advantage that they do not reveal details about the parts of the classes. Class-only strategies should be used whenever possible. When edge-controlled strategies are absolutely needed, we can refer to edges as follows \begin{verbatim} -> A,b,B construction edge from A to B labeled b => A,B subclass edge from A to B \end{verbatim} A set of edges is put into curly braces and they are separated by commas: \begin{verbatim} {-> A,b,B , -> X,y,Y} \end{verbatim} A situation where an edge-controlled strategy is needed is illustrated by the following class graph: \begin{verbatim} A = B B B. B = C. C = . \end{verbatim} We want the propagation graph \begin{verbatim} A = B. B = C. C = . \end{verbatim} We can use either a positive or a negative edge-controlled strategy. The positive edge-controlled strategy would be in line graph notation (currently not implemented) \begin{verbatim} from A through -> A,b1,B to C \end{verbatim} or in strategy graph notation \begin{verbatim} { A -> A A -> B only-through -> A,b1,B} B -> C } source: A target: C \end{verbatim} only-through means that we are allowed to go only through the edge indicated. Only-through is a negative constraint since it bypasses all the other edges. The negative edge-controlled strategy is in strategy graph notation \begin{verbatim} {A -> C bypassing {-> A,b2,B , -> A,b3,B}} source: A target: B \end{verbatim} \subsection{The wildcard feature} Suppose we want to find inside an A-object all objects except the ones reachable through B-objects. This can be expressed by the strategy \begin{verbatim} from A to * bypassing B \end{verbatim} or in strategy graph notation \begin{verbatim} {A -> * bypassing B} \end{verbatim} * is the wildcard symbol. It may be used both for class names as well as for edge names. The wildcard symbol adds additional expressiveness to the notation since we can talk about class names and edge names without knowing them. \begin{verbatim} from A to * \end{verbatim} defines a traversal which visits all sub objects contained in an A-object. Demeter/Java provides a universal traversal, called universal_trv0 (name may change in future), which does a depth-first traversal of entire objects. You should reuse the universal traversal when possible to avoid generating unnecessary traversal code. Instead of writing \begin{verbatim} A { void f() to * (V1) } \end{verbatim} it is better to use \begin{verbatim} A { void f() {V1 v1 = new V1(); universal_trv0(v1);} } \end{verbatim} \subsection{Preventing recursion} Recursion in the class graph may lead to undesired loops in the propagation graph. For example, if we want to find the top-level companies in a conglomerate of companies, the strategy \begin{verbatim} from Conglomerate to Company \end{verbatim} will find all Company-objects. To get only the top-level company objects, we use instead \begin{verbatim} from Conglomerate to-stop Company \end{verbatim} which is equivalent to \begin{verbatim} from Conglomerate bypassing {-> Company,*,* , => Company,* } to Company \end{verbatim} In strategy graph notation \begin{verbatim} {Conglomerate -> Company bypassing {-> Company,*,* , => Company,*} } source: Conglomerate target: Company \end{verbatim} The meaning of to-stop is that all edges outgoing from the targets are bypassed. \subsection{Surprise paths} A strategy defines a path set in the class graph. For example, {\sf {A -> B}} defines the set of all paths from A to B. Such paths may be of the form {\sf A P B Q A B R A S B} where we visit more A's and B's between the source A and target B. If we want to exclude such ``surprise'' paths, we write the strategy in the following form: \begin{verbatim} {A->B bypassing {A,B}} \end{verbatim} %check strategy paper: bypass edges into A and edges out from B. We cannot delete A and B. %require A != B which excludes any intermediate A's and B's. Notice that the source A and target B are, of course, not excluded. In class graphs with cycles, we have to be careful with surprise paths. Consider the following class graph: \begin{verbatim} Person = PersonList PersonList Status. Status : Single | Married. Single = . Married = Person. PersonList ~ {Person}. \end{verbatim} To compute the spouse of a person, we use \begin{verbatim} Person { Person get_spouse() bypassing Person through Married bypassing Person to Person // through Married to-stop Person {return_val = this;} // return_val initialized with null } \end{verbatim} Notice that the {\sf bypassing Person} is needed otherwise we would get also the brothers and sisters of the spouse as well as the original person we started with. %disallow? %Person get_spouse() {Person -> Person bypassing {Person, PersonList}} // the spouse % {return_val = this;} %// not implemented %Person get_spouse() {Person -> Person only-through -> Person,married_to,Person bypassing Person} % {return_val = this;} \begin{verbatim} Person = Brothers Sisters Status. Status : Single | Married. Single = . Married = Person. Brothers ~ {Person}. Sisters ~ {Person}. \end{verbatim} In-laws are relatives by marriage. To print the brothers and sisters in-law of a person we use either of the following two the strategies: (first one not implemented yet) \begin{verbatim} { Person -> Married bypassing Person Married -> spouse:Person bypassing Person spouse:Person -> Brothers bypassing Person spouse:Person -> Sisters bypassing Person Brothers -> brothers_in_law:Person bypassing Person Sisters -> sisters_in_law:Person bypassing Person } from Person bypassing Person through Married bypassing Person through Person bypassing Person through {Brothers, Sisters} bypassing Person to Person \end{verbatim} This in-laws example shows an important feature of strategies (not yet implemented in Demeter/Java): we can use strategy graphs to define traversal states. So far we have ignored this possibility. {\sf spouse:Person} means that if during the traversal we arrive here, the person is a spouse. \section{General strategy graphs} A general strategy graph consists of a list of edges, each with optional constraints, and source and target classes. We assume for now that the same class name always refers to the same strategy graph node. An example of a general strategy graph is: \begin{verbatim} { A -> B //negative constraint 1 B -> D //negative constraint 2 A -> C //negative constraint 3 C -> D //negative constraint 4 } source: A target: D \end{verbatim} % this will change, also allow node specific version A negative constraint is either of the bypassing or the only-through form. \begin{verbatim} {A -> B bypassing -> *,y,*} \end{verbatim} means to go from A to B but not through a construction edge labeled y. \begin{verbatim} {A -> B only-through -> A,b2,B} \end{verbatim} means to go from A to B but the only edge we are allowed to use is the construction edge from A to B labeled b2. All other edges from A to B are implicitly bypassed. Only-through is the complement of bypassing. \subsection{When not to use strategies} {Person -> Person bypassing Person} %With only-through you can specify detailed traversals which is useful in some dense graphs. % %Person = PersonList PersonList [ Person]. %PersonList ~ {Person}. % %In-laws are relatives by marriage. To print the brothers and sisters in-law of a person we use the strategy % %{ Person -> Person bypassing {Person, PersonList} // the spouse %Person -> PersonList only-through {-> Person,*,PersonList} %} % %{ Person -> Person only-through -> Person,married_to,Person % Person -> PersonList only-through {-> Person,*,PersonList} %} PersonList -> Person insert from manual temp