Subgraphs

This interface defines a nested Graph that appears to be a single Node from the perspective of its parent. This technique allows unlimited nesting of graphs inside graphs.

There are number of consequences of representing an entire Graph as a single Node. First of all, such a nested Graph (from now on referred to as a Subgraph) must be a Node from the parent's point of view. The parent Graph does not need to know whether a particular Node is actually a Subgraph or not. This is a major advantage of the subgraphing approach. Each Subgraph may be handled like an ordinary Node in a particular context.

Graph Abstraction Layer

When a Node is used to represent an entire Graph, however, the interface Node no longer suffices. A more general interface needs to exist that allows us to focus on the Subgraph as a Graph instance as well. Therefore, this interface extends the GraphObjectContainer as well.

Building Subgraphs

The following diagram illustrates the isomorphism of VisualSubgraph and VisualNode. The fact that both a VisualGraphView and a VisualSubgraph are visual representations of entire graphs is apparent, since both types inherit from the common interface VisualGraphObjectContainer.

Figure 1.3. VisualGraphObjects

VisualGraphObjects

The tight structural coupling between model and view objects can be seen in the following model diagram. Please note that model classes do not provide a top-level type like the VisualGraphView class.

Figure 1.4. Graph Objects

Graph Objects

Please note that interfaces GraphObjectContainer and VisualGraphObjectContainer can (and should) be used in most occasions where these interfaces are being used:

  • Graph,

  • Subgraph,

  • VisualGraph,

  • VisualGraphView and

  • VisualSubgraph

These derived interfaces are not known by any centralized Container objects.

Finally, the interface Edge cannot be used in place of a Subgraph.

Traversing Subgraphs

Since objects of type Subgraph (and VisualSubgraph) can be nested inside each other, it often becomes necessary to traverse a given hierarchy. This can be achieved by implementing interface GraphVisitor in the model or VisualGraphVisitor in the view.

Example 1.6. Traversal of nested Subgraphs

void traverse(Graph graph) 
{
    // Visit all nested subgraphs and print out their hashcodes.
    // The used order for traversal is POST_ORDER.
    // Alternatively GraphVisitor.PRE_ORDER can be specified.
    
    graph.visitSubgraphs(
        new GraphVisitor ()
        {
            
            public int getOrder()
            {
                return GraphVisitor.POST_ORDER;
            }
            
            public void visit(Subgraph subgraph, int level)
            {
                System.err.println ("visiting subgraph ... "
                    + System.identityHashCode(subgraph));
            }
        });
    
}

Example 1.7. Traversal of nested VisualSubgraphs

void traverseSubGraphs(VisualGraphView vgv)
{
    // Visit all nested visualsubgraphs and print out their hashcodes. 
    // The used order for traversal is POST_ORDER.
    // Alternatively VisualGraphVisitor.PRE_ORDER can be specified.
    vgv.visitSubgraphs(new VisualGraphVisitor()
    {

        public int getOrder()
        {
            return VisualGraphVisitor.POST_ORDER;
        }

        public void visit(
            VisualSubgraph visualsubgraph,
            VisualGraph visualgraph, 
            VisualGraph parentvisualgraph,
            int level)
        {
            System.err.println("visiting visualsubgraph ... "
                + System.identityHashCode(visualsubgraph));
        }
    });
}