The AP Library

Description | Download | Use

Please read first the AP Library Fact Sheet.

Description

Adaptive Programming (AP) is a programming technology where programs are split into crosscutting building blocks in a novel way to control tangling and redundancy. In AP, at least one of the building blocks is represented by a graph and other building blocks refer to subgraphs of the graph without revealing the details of the subgraphs. This is a form of succinct specification of graphs similar to the hierarchical specification of graphs widely used in hardware and software designs. A succinct specification can be expanded to a flat representation that is usually much larger than the succinct representation.

AP is a special case of AOP. Connection to Aspect-Oriented Programming.

The AP Library contains the core algorithm for expanding a succinct representation of a graph into a flat, detailed representation of a graph. A succinct specification is given by a strategy graph. Definition: Given a graph G, a strategy graph S of G is any subgraph of the transitive closure of G. The flat representation of a strategy graph S with respect to G is (in many cases) the subgraph of G that consists of all paths in G that are expansions of paths in S.

The problem the AP Library solves is (in simplified form): Given as input a strategy graph S and a graph G, return the flat representation of S with respect to G. The flat representation is the set of paths in G defined by S and is called a traversal graph.

The AP Library deals with more complex graphs, namely class graphs that have several kinds of nodes and edges. The strategy graphs can also have constraints attached to their edges. And the AP Library deals with name maps, to allow to map nodes in the strategy graph to nodes in the class graph. The details are in Strategies Paper.

The AP Library has been developed as a part of DemeterJ and is heavily used. What are the applications of the AP Library outside DemeterJ? It is a useful technology to map graphs into other more complex graphs or to select subgraphs from more complex graphs. This is a very generic problem in hardware and software design and has therefore many applications. Check the Demeter page for many applications such as framework design, distributed programming, API implementations, Visitor Design pattern, expressing object collaborations, traversals, Aspect-Oriented Programming etc. For example, the graph nodes could be classes and the edges associations or the graph nodes could be components and the edges could be connectors.

DJ and AP Library Documentation for Implementors.

Why is the AP Library useful to an architecture toolkit?. Because it allows for flexible specification of connections between components. See the work on Adaptive Plug-and-Play Components (OOPSLA 98).

Downloading and installing the AP Library

Demeter Software Documentation.

Demeter Software Installation.

AP Library Software API Documentation (see aplib).

Using the AP Library

  1. Add the aplib.jar and rt.jar files to your class path. (This step is not needed if you are developing with DemeterJ.)
  2. In your program, import the AP Library package (EDU.neu.ccs.demeter.aplib.*).
  3. Define classes implementing the four interfaces ClassGraphI, EdgeI, StrategyGraphI, and NameMapI. Alternatively, you can use the provided class graph and strategy graph implementations, by importing EDU.neu.ccs.demeter.aplib.cd.* and EDU.neu.ccs.demeter.aplib.sg.* (see documentation for these packages below-- sorry, no javadoc yet).
  4. Construct ClassGraphI, StrategyGraphI, and NameMapI objects and call the static method TraversalGraph.compute . This returns a TraversalGraph object, which can be queried about whether vertices and edges of the class graph are in the traversal graph; you can also get enumerations of the vertices and edges.
The provided implementation for StrategyGraphI is the class StrategyGraph, which can be parsed from a stream or a string by these static methods on the class Strategy:
  /** Read a strategy expression from a char stream and normalize it. */
  public static StrategyGraph readFrom(InputStream in) throws ParseException;

  /** Convert a string to a strategy expression and normalize it. */
  public static StrategyGraph fromString(String s);
The provided implementation for ClassGraphI is the class ClassGraph, which can be parsed from a stream or a string by these static methods on the class ClassGraph:
  /** Read a class dictionary from a char stream and normalize it. */
  public static ClassGraph readFrom(InputStream in) throws ParseException;

  /** Convert a string to a class dictionary and normalize it. */
  public static ClassGraph fromString(String s);
Alternatively, you can construct a ClassGraph object using these methods:
  /** Add a construction edge named name from the vertex labeled
      source to the vertex labeled target. */
  public void addConstructionEdge(String source, String name, String target);

  /** Add an alternation edge from the vertex labeled source to the
      vertex labeled target. */
  public void addAlternationEdge(String source, String target);

  /** Add an inheritance edge from the vertex labeled source to the
      vertex labeled target. */
  public void addInheritanceEdge(String source, String target);
Note that inheritance edges are not needed if your class graph is flat. If it is not flat, i.e. if you have alternation classes with outgoing construction edges, then you'll need to add an inheritance edge corresponding to every alternation edge (but in the opposite direction).

This method is also provided as a convenience:

  /** Print the class dictionary corresponding to the subgraph
      determined by the traversal graph. */
  public void printTraversalEdges(TraversalGraph tg, PrintWriter out);

The Demeter team <dem@ccs.neu.edu>
Last modified: Oct 8 00:55:17 EDT 2002