org.extex.typesetter.type
Interface NodeVisitor<R,A>

Type Parameters:
R - return type
A - argument type
All Known Subinterfaces:
InspectableNodeVisitor
All Known Implementing Classes:
AbstractNodeVisitor, CollectNodeVisitor, DebugNodeVisitor, PageFactoryNodeVisitor, PdfNodeVisitor, PdfNodeVisitor, PsBasicConverter, PsBoxConverter, SVGDocumentWriter, TextDocumentWriter, XMLDocumentWriter

public interface NodeVisitor<R,A>

This interface implements part of the visitor pattern for nodes.

In object-oriented design a pattern has been established to let one class react on the type of some object. Consider a tree composed of different types of nodes all implementing a same base interface and some of them having extensions of the interface. This is the situation for Nodes for which several types exist.

The original idea was to attach the desired functionality to the nodes and let it have one common method to invoke it. This turns out not to be practical for modular components where the algorithm might be exchanged. This is the case for the DocumentWriter which might produce Text, PDF, DVI, or some other output format. Any new implementation of this interface would have the need to extend the Node classes.

The other simplistic solution is to use a large switch, or cascaded if-then-else, to differentiate the cases. This kind of code is cumbersome to maintain. Whenever a new type of node is added you have to remember all places which need adaption.

This problem is solved in the visitor pattern. Each class or interface of the nodes has to provide one method called visit() here. This method has as one argument the visitor which should be called back. The visitor is defined by this interface. He has to provide a set of methods which allow him to differentiate the types of the nodes.

Each node has to implement the method visit() in a way that the appropriate method from the visitor interface is invoked. Thus as a result the nodes and the algorithm are decoupled.

The Mechanics of the NodeVisitor

The actions during the use of a NodeVisitor is illustrated in the following sequence diagram.


A sequence diagram for the NodeVisitor

In this diagram a NodeVisitor is assumed to process two nodes. The first one is a CharNode and the second one is a GlueNode. We assume that the concrete sub-type of Node to be processed is not known. For instance it can be passed to the initial method in a NodeList.

The first Node is processed by invoking the method visit(). The first argument is the reference to the current instanceof the NodeVisitor. Since the method is defined in CharNode to delegate it to the NodeVisitor by invoking the method visitChar(). Now the real work can be performed in the calling instance. Here the sub-type is known and can be taken into account.

After the return to the caller the second node can be taken into account. The procedure is the same: visit() is invoked. But now the delegation used the method visitGlue(). Thus in the calling instance the GlueNode can be processed specially.

Example Source Code

Consider you have a class implementing DocumentWriter with a method which needs to react differently on different node types. The first approximation looks as follows:


 public class MyDocumentWriter implements DocumentWriter {

     public void myMethod(Node node) {
         // Do something with node depending on its type
     }
 }
 

Now we can add the NodeVisitor interface. Thus we are forced to define a bunch of methods declared in this interface:


 public class MyDocumentWriter
     implements DocumentWriter,
                NodeVisitor<Boolean, Integer> {

     public void myMethod(Node node) {
         // Do something with node depending on its type
     }
 
     public Boolean visitAdjust(AdjustNode node, Integer arg) {
         // do something for adjust nodes
     }

     public Boolean visitChar(CharNode node, Integer arg) {
         // do something for char nodes
     }

     // and many others..
 
 }
 

Now we just have to make sure that those methods are invoked. This is done with the method visit() of the Node. The signature allows us to provide two additional arguments and receive a return value. Since we want to do something with the node itself, this node is provided with the correct type to the node visitor. The second argument can be casted to the appropriate type.

In the visit methods we can now safely assume that the node is of the named type and cast the object to have access to its public methods.


 public class MyDocumentWriter
     implements DocumentWriter,
                NodeVisitor<Boolean, Integer> {

     public void myMethod(Node node) {
         node.visit(this, "some value");
     }

     public Object visitAdjust(AdjustNode node, Object arg) {
         String s = (String) arg;
         // do something for adjust nodes
     }

     public Object visitChar(CharNode node, Object arg) {
         String s = (String) arg;
         // do something for char nodes
     }

     // and many others..

 }
 

In the example above we have not used the additional argument or the return value. In the visit methods we are free to use them in all ways we like.

The definition of the parameters and the return value are rather general. Thus it is possible to use the visitor pattern in several different situations.

The visitor is not necessarily the class MyDocumentWriter. If this class contains several methods which need to distinguish the types of the nodes it is possible to use another class as visitor, e.g. an inner class.

Version:
$Revision: 4739 $
Author:
Gerd Neugebauer

Method Summary
 R visitAdjust(AdjustNode node, A value)
          This method is called when an AdjustNode has been encountered.
 R visitAfterMath(AfterMathNode node, A value)
          This method is called when an AfterMathNode has been encountered.
 R visitAlignedLeaders(AlignedLeadersNode node, A value)
          This method is called when an AlignedLeadersNode has been encountered.
 R visitBeforeMath(BeforeMathNode node, A value)
          This method is called when a BeforeMathNode has been encountered.
 R visitCenteredLeaders(CenteredLeadersNode node, A value)
          This method is called when a CenteredLeadersNode has been encountered.
 R visitChar(CharNode node, A value)
          This method is called when a CharNode has been encountered.
 R visitDiscretionary(DiscretionaryNode node, A value)
          This method is called when a DiscretionaryNode has been encountered.
 R visitExpandedLeaders(ExpandedLeadersNode node, A value)
          This method is called when an ExpandedLeadersNode has been encountered.
 R visitGlue(GlueNode node, A value)
          This method is called when a GlueNode has been encountered.
 R visitHorizontalList(HorizontalListNode node, A value)
          This method is called when a HorizontalListNode has been encountered.
 R visitInsertion(InsertionNode node, A value)
          This method is called when an InsertionNode has been encountered.
 R visitKern(KernNode node, A value)
          This method is called when a KernNode has been encountered.
 R visitLigature(LigatureNode node, A value)
          This method is called when a LigatureNode has been encountered.
 R visitMark(MarkNode node, A value)
          This method is called when a MarkNode has been encountered.
 R visitPenalty(PenaltyNode node, A value)
          This method is called when a PenaltyNode has been encountered.
 R visitRule(RuleNode node, A value)
          This method is called when a RuleNode has been encountered.
 R visitSpace(SpaceNode node, A value)
          This method is called when a SpaceNode has been encountered.
 R visitVerticalList(VerticalListNode node, A value)
          This method is called when a VerticalListNode has been encountered.
 R visitVirtualChar(VirtualCharNode node, A value)
          This method is called when a VirtualCharNode has been encountered.
 R visitWhatsIt(WhatsItNode node, A value)
          This method is called when a WhatsItNode has been encountered.
 

Method Detail

visitAdjust

R visitAdjust(AdjustNode node,
              A value)
              throws GeneralException
This method is called when an AdjustNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitAfterMath

R visitAfterMath(AfterMathNode node,
                 A value)
                 throws GeneralException
This method is called when an AfterMathNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitAlignedLeaders

R visitAlignedLeaders(AlignedLeadersNode node,
                      A value)
                      throws GeneralException
This method is called when an AlignedLeadersNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitBeforeMath

R visitBeforeMath(BeforeMathNode node,
                  A value)
                  throws GeneralException
This method is called when a BeforeMathNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitCenteredLeaders

R visitCenteredLeaders(CenteredLeadersNode node,
                       A value)
                       throws GeneralException
This method is called when a CenteredLeadersNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitChar

R visitChar(CharNode node,
            A value)
            throws GeneralException
This method is called when a CharNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitDiscretionary

R visitDiscretionary(DiscretionaryNode node,
                     A value)
                     throws GeneralException
This method is called when a DiscretionaryNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitExpandedLeaders

R visitExpandedLeaders(ExpandedLeadersNode node,
                       A value)
                       throws GeneralException
This method is called when an ExpandedLeadersNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitGlue

R visitGlue(GlueNode node,
            A value)
            throws GeneralException
This method is called when a GlueNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitHorizontalList

R visitHorizontalList(HorizontalListNode node,
                      A value)
                      throws GeneralException
This method is called when a HorizontalListNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitInsertion

R visitInsertion(InsertionNode node,
                 A value)
                 throws GeneralException
This method is called when an InsertionNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitKern

R visitKern(KernNode node,
            A value)
            throws GeneralException
This method is called when a KernNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitLigature

R visitLigature(LigatureNode node,
                A value)
                throws GeneralException
This method is called when a LigatureNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitMark

R visitMark(MarkNode node,
            A value)
            throws GeneralException
This method is called when a MarkNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitPenalty

R visitPenalty(PenaltyNode node,
               A value)
               throws GeneralException
This method is called when a PenaltyNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitRule

R visitRule(RuleNode node,
            A value)
            throws GeneralException
This method is called when a RuleNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitSpace

R visitSpace(SpaceNode node,
             A value)
             throws GeneralException
This method is called when a SpaceNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitVerticalList

R visitVerticalList(VerticalListNode node,
                    A value)
                    throws GeneralException
This method is called when a VerticalListNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitVirtualChar

R visitVirtualChar(VirtualCharNode node,
                   A value)
                   throws GeneralException
This method is called when a VirtualCharNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error

visitWhatsIt

R visitWhatsIt(WhatsItNode node,
               A value)
               throws GeneralException
This method is called when a WhatsItNode has been encountered.

Parameters:
node - the first parameter for the visitor is the node visited
value - the second parameter for the visitor
Returns:
the visitor specific value
Throws:
GeneralException - in case of an error