Based on your feedback, I have improved the Abstract Slicing pattern. Based on Doug's input, the example is much more elegant now. -- Karl ========================== I have tried out the new version of DJ and formulated the following very useful pattern whose implementation is facilitated by DJ. Many thanks to Doug for producing such a well-rounded, low-learning-curve implementation of AP for Java. To have a class ObjectGraphSlice was his idea. -- Karl The new version of DJ http://www.ccs.neu.edu/home/dougo/dj/ supports the Abstract Slicing pattern You program in terms of abstract object slices that are mapped later using traversal strategies. Example: The complete terminal buffer rule example is at: http://www.ccs.neu.edu/research/demeter//DJ/annot-examples/TBR/TBR1-flexible The terminal buffer rule says that all terminal classes should be "buffered" by a class that has the terminal class as part class. Improves readability of class graphs. To program this rule: FILE: Cd_graph.java public void TBRchecker2( ObjectGraphSlice defineClassNameSlice, ObjectGraphSlice allPartsSlice) { // here is the idea: // defineClassNameSlice defines the part of the object graph // that is relevant for finding all defined classes. // allPartsSlice defines the part of the object graph // that is relevant for checking the TerminalBufferRule DefinedClassVisitor v1 = new DefinedClassVisitor(); // find defined classes Vector definedClasses = (Vector) defineClassNameSlice.traverse(v1); // check for violations TBRVisitor v2 = new TBRVisitor(definedClasses); allPartsSlice.traverse(v2); } We need two visitors, one of which is shown here: FILE: DefinedClassVisitor.java public class DefinedClassVisitor extends Visitor { private Vector vNonTerminals = new Vector(); public void before(Adj o) { Ident idCurrentAdj; idCurrentAdj = o.vertex.name; System.out.println("Adj: " + idCurrentAdj.toString()); vNonTerminals.addElement(idCurrentAdj);} public Object getReturnValue() {return vNonTerminals;} } Visitor DefineClassVisitor expects that the slice defineClassNameSlice goes through class Adj. For a concrete use of TBRchecker2 we get (in Main.java): ObjectGraph og = new ObjectGraph(cd_graph,cg); cd_graph.TBRchecker2( new ObjectGraphSlice(og,"from Cd_graph to Adj"), new ObjectGraphSlice(og,"from Cd_graph via Construct to Vertex")); The above code is adaptation code that defines two concrete object graph slices for the current class graph and object graph. Class ObjectGraph should be considered as a helper class, that lifts a Java object into a space that allows computation of object graph slices. Pattern: Abstract Slicing Intent: Write algorithms at a high level of abstraction. Motivation: The AP motivation: Avoid polluting algorithms with accidental details yet write them so that they can handle all that accidental detail without modification. Applicability: Applications that involve multiple connected objects that need to be visited. Structure: Parameterize methods with abstract object graph slices that are needed to express the methods abstractly. It might be necessary to also pass slices as arguments to visitors that need to do subtraversals. Related idea: AspectJ supports the notion of an abstract point cut. Type ObjectGraphSlice is a kind of abstract point cut. Implementation: DJ provides a good implementation of abstract object slices but does not support static checking. That could be added as a separate tool. Tradeoff: use of the pattern makes algorithms more generic but each use of the algorithm requires object graph slice preparation. The input object needs to be prepared (adapted) for processing based on the details of the class graph. Feedback welcome!