de.dante.extex.typesetter.type
Interface NodeVisitor

All Known Subinterfaces:
InspectableNodeVisitor, PageFactoryNodeVisitor
All Known Implementing Classes:
AbstractNodeVisitor, DebugNodeVisitor, PdfNodeVisitor, PsBasicConverter, PsBoxConverter, SVGDocumentWriter, TextDocumentWriter, XMLDocumentWriter

public interface NodeVisitor

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(final 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 {

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

     public Object visitChar(final CharNode node, final Object 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 savely 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 {

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

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

     public Object visitChar(final CharNode node, final 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: 1.9 $
Author:
Gerd Neugebauer

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

Method Detail

visitAdjust

public java.lang.Object visitAdjust(AdjustNode node,
                                    java.lang.Object 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

public java.lang.Object visitAfterMath(AfterMathNode node,
                                       java.lang.Object 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

public java.lang.Object visitAlignedLeaders(AlignedLeadersNode node,
                                            java.lang.Object 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

public java.lang.Object visitBeforeMath(BeforeMathNode node,
                                        java.lang.Object 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

public java.lang.Object visitCenteredLeaders(CenteredLeadersNode node,
                                             java.lang.Object 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

public java.lang.Object visitChar(CharNode node,
                                  java.lang.Object 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

public java.lang.Object visitDiscretionary(DiscretionaryNode node,
                                           java.lang.Object 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

public java.lang.Object visitExpandedLeaders(ExpandedLeadersNode node,
                                             java.lang.Object 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

public java.lang.Object visitGlue(GlueNode node,
                                  java.lang.Object 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

public java.lang.Object visitHorizontalList(HorizontalListNode node,
                                            java.lang.Object 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

public java.lang.Object visitInsertion(InsertionNode node,
                                       java.lang.Object 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

public java.lang.Object visitKern(KernNode node,
                                  java.lang.Object 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

public java.lang.Object visitLigature(LigatureNode node,
                                      java.lang.Object 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

public java.lang.Object visitMark(MarkNode node,
                                  java.lang.Object 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

public java.lang.Object visitPenalty(PenaltyNode node,
                                     java.lang.Object 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

public java.lang.Object visitRule(RuleNode node,
                                  java.lang.Object 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

public java.lang.Object visitSpace(SpaceNode node,
                                   java.lang.Object 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

public java.lang.Object visitVerticalList(VerticalListNode node,
                                          java.lang.Object 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

public java.lang.Object visitVirtualChar(VirtualCharNode node,
                                         java.lang.Object 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

public java.lang.Object visitWhatsIt(WhatsItNode node,
                                     java.lang.Object 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