Site hosted by Angelfire.com: Build your free website today!

Original source at http://www.ddj.com/ftp/2000/2000_11/aa0011.txt

Algorithm Alley
by Alexander Ananiev 

Example 1:
if ( levelIter.hasChildren() ) {
  levelIter=levelIter.nextLevel(); 
}
Object nextElt=null;
// if there are more siblings at the current level
if ( levelIter.hasMoreElements() )
  nextElt=levelIter.nextElement();
// the entire level has been processed--go to the parent level
else if (levelIter.hasParent() ) {
  levelIter=levelIter.toParent();
  nextElt=levelIter.nextElement();
}
return nextElt;


Example 2:
/** Returns enumeration of the children of the node. */
public Enumeration getChildren( Object node );
/** Returns true if node has children. */
public boolean hasChildren( Object node );


Example 3:
(a)
if (nodeAdapter.hasChildren( node) && depth<=maxDepth) // go to children's level ...

(b)
public static final int idLevel = 2;
//...
Document xdoc = parser.readStream(new FileReader( "personnel.xml"));
TIterator tIterator = new TIterator ( xdoc , new DOMAdapter(), idLevel );
for( Node node = xdoc; node!=null; node=(Node)tIterator.next() ){
  // perform processing...
}

Figure 1:


  
    MARUYAMA Hiroshi
    maruyama@jp.ibm.com
    
  
  
    URAMOTO Naohiko
    uramoto@jp.ibm.com
    
  
  
    
      TAMURA Kent
    
    
    
    
    
  



Listing One
package aan.treexamples;
import org.w3c.dom.*;
public class RecursiveTraversal implements ITraversal {
  /* Performs full tree traversal using recursion. */
  public void traverse( Node parentNode ) {
    // traverse all nodes that belong to the parent
    for(Node node=parentNode.getFirstChild(); node!=null; 
                                              node=node.getNextSibling()) {
      // print node information
      System.out.println( node.getNodeName()+"="+node.getNodeValue());
      // traverse children
      traverse(node);
    }
  }
}

Listing Two
package aan.treexamples;
import org.w3c.dom.*;
import java.util.*;
public class StackTraversal implements ITraversal {
  /* Performs full tree traversal using stack. */
  public void traverse( Node rootNode ) {
    Stack stack = new Stack();
    // ignore root -- root acts as a container
    Node node=rootNode.getFirstChild();
    while (node!=null) {
      // print node information
      System.out.println( node.getNodeName()+"="+node.getNodeValue());
      if ( node.hasChildNodes()) {
        // store next sibling in stack. Return to it after all children 
        //                                                     are processed.
        if (node.getNextSibling()!=null)
          stack.push( node.getNextSibling() );
        node = node.getFirstChild();
      }
      else {
        node = node.getNextSibling();
        if (node==null && !stack.isEmpty())
          // return to the parent's level. // some levels can be skipped if parent's node was the last one.
          node=(Node) stack.pop();
      }
    }
  }
}

Listing Three
package aan.treexamples;
import org.w3c.dom.*;
public class LinkTraversal implements ITraversal {
  /* Performs full tree traversal usingchild-parent link. */
  public void traverse( Node rootNode ) {
    // ignore root -- root acts as a container
    Node node=rootNode.getFirstChild();
    while (node!=null) {
      // print node information
      System.out.println( node.getNodeName()+"="+node.getNodeValue());
      if ( node.hasChildNodes()) {
        node = node.getFirstChild();
      }
      else {    // leaf
        // find the parent level 
        while (node.getNextSibling()==null && node != rootNode)
            // use child-parent link to get to the parent level
            node=node.getParentNode();
        node = node.getNextSibling();
      }
    }
  }
}

Listing Four
package aan.treexamples;
import aan.tree.*;
import org.w3c.dom.*;
public class IterFullTraversal implements ITraversal {
  /* Performs full tree traversal using tree iterator. */
  public void traverse ( Node rootNode ) {
    // create iterator
    TIterator tIterator = new TIterator ( rootNode , new DOMAdapter() );
    Node node = null;
    while( (node=(Node)tIterator.next()) != null )  {
      // print node information
      System.out.println( node.getNodeName()+"="+node.getNodeValue());
    }
  }
}

Listing Five
package aan.tree;
import java.util.Enumeration;
import javax.swing.tree.TreeNode;
/* This adapter maps javax.swing.tree.TreeNode interface to
 * generic methods required by TIterator. */
public class SwingAdapter implements TNodeAdapter {
  public Enumeration getChildren( Object node ) {
    return ((TreeNode)node).children();
  }
  public boolean hasChildren( Object node ) {
    return ! ((TreeNode)node).isLeaf();
  }
}

Listing Six
package aan.tree;
import java.util.Enumeration;
import org.w3c.dom.*;
/** This adapter maps org.w3c.dom.Node interface to generic 
 * methods required by TIterator. Enumeration provided by the 
 * nested class in order to conforom to w3c spec. */
public class DOMAdapter implements TNodeAdapter {
  public Enumeration getChildren( Object node ) {
    return new Enumerator( ((Node)node).getFirstChild() );
  }
  public boolean hasChildren( Object node ) {
    return ((Node)node).hasChildNodes();
  }
  /* Maps org.w3c.dom.Node methods to Enumeration.
   * Inner class HeadNode provides dummy impelmemtation for
   * Node, it is used as the head of the list. This is needed 
   * to advance to the first element after the next() */
  static public class Enumerator implements Enumeration {
    private Node node;
    Enumerator( Node node) {
      // empty node is the head of the list
      this.node = new HeadNode( node );
    }
    public Object nextElement() {
      node = node.getNextSibling();
      return node;
    }
    public boolean hasMoreElements() {
      return (node.getNextSibling() != null);
    }
    /* Dummy implementation of the Node.
     * It returns its node after the nextSibling call */
    private class HeadNode  implements Node {
      private Node nextNode;
      /* Creates the node and initiates with the current node */
      private HeadNode( Node node){
        nextNode = node;
      }
      /* Returns current node as the next. This is the only method that's * used out of Node interface.  @return current node */
      public Node getNextSibling() {
        return nextNode;
      }
      // all these methods are not used
      public String getNodeName(){ return null;}
      public String getNodeValue() throws DOMException { return null;}
      public void setNodeValue(String nodeValue) throws DOMException {}
      public short getNodeType() {return 0;}
      public Node getParentNode() {return null;}
      public NodeList getChildNodes() {return null;}
      public Node getFirstChild()  {return null;}
      public Node getLastChild()  {return null;}
      public Node getPreviousSibling()  {return null;}
      public NamedNodeMap getAttributes(){return null;}
      public Document getOwnerDocument(){return null;}
      public Node insertBefore(Node newChild, Node refChild)
        throws DOMException {return null;}
      public Node replaceChild(Node newChild, Node oldChild)
        throws DOMException {return null;}
      public Node removeChild(Node oldChild)
        throws DOMException {return null;}
      public Node appendChild(Node newChild)
        throws DOMException {return null;}
      public boolean hasChildNodes() {return false;}
      public Node cloneNode(boolean deep) {return null;}
    } // end of HeadNode
  } // end of Enumerator
}

Listing Seven
package aan.tree;
import java.util.Enumeration;
import org.w3c.dom.Node;
import com.ibm.xml.parser.Parent;
/* Maps org.w3c.dom.Node and 
 * com.ibm.xml.parser.Parent to generic methods required 
 * by TIterator. */
public class XML4JAdapter implements TNodeAdapter {
  public Enumeration getChildren( Object node ) {
    return ((Parent)node).elements();
  }
  public boolean hasChildren( Object node ) {
    return ((Node)node).hasChildNodes();
  }
}

Listing Eight
package aan.treexamples;
import aan.tree.*;
import org.w3c.dom.*;
public class IterMaxDepthTraversal implements ITraversal {
  /* Traverses tree with traversal depth set to depth of the "person" level */
  public void traverse ( Node rootNode ) {
    // create iterator
    TIterator tIterator = new TIterator ( rootNode, new DOMAdapter() );
    // find the depth of the required level
    int targetDepth = -1;
    Node node = null;
    while( (node=(Node)tIterator.next()) != null )  
      if (node.getNodeName().equals("person")) {
        targetDepth = tIterator.getDepth();
        break;
      }
    // we can reuse the same iterator
    tIterator.setRoot(rootNode);
    // limit the depth of traversal
    tIterator.setMaxDepth( targetDepth );
    while( (node=(Node)tIterator.next()) != null )  {
      // print node information
      System.out.println( node.getNodeName()+"="+node.getNodeValue());
    }
  }
}

Listing Nine
package aan.treexamples;
import aan.tree.*;
import org.w3c.dom.*;
public class SelectiveNestedTraversal implements ITraversal {
  /* Selectively traverses the tree ising nested loops. */
  public void traverse ( Node rootNode ) {
    // create 1st iterator. depth should be limited to ID's level
    DOMAdapter domAdapter = new DOMAdapter();
    TIterator tIterator = new TIterator ( rootNode, domAdapter, 2 );
    Node node = null;
    while( ( node=(Node)tIterator.next() )!=null ){
      // print node information
      System.out.println( node.getNodeName()+"="+node.getNodeValue());
      if  (node instanceof Element && ((Element)node).getAttribute( "id" ).
        equalsIgnoreCase( "K.TAMURA" )) {
        // create 2nd iterator, perform nested loop to process the branch.
        TIterator branchIterator =  new TIterator ( node, domAdapter);
        Node branchNode = null;
        while( (branchNode=(Node)branchIterator.next()) != null )
          // print node information
          System.out.println( branchNode.getNodeName()+"="+branchNode.getNodeValue());
      }
    }
  }
}

Listing Ten
package aan.treexamples;
import aan.tree.*;
import org.w3c.dom.*;
public class SelectiveSkipTraversal implements ITraversal {
  /* Selectively traverses the tree ising skip flag. */
  public void traverse ( Node rootNode ) {
    // create an iterator.
    int idLevel = 2;
    TIterator tIterator = new TIterator ( rootNode, new DOMAdapter());
    Node node = null;
    while( ( node=(Node)tIterator.next() )!=null ){
      // print node information
      System.out.println( node.getNodeName()+"="+node.getNodeValue());
      if  ( tIterator.getDepth() == idLevel && ! (node instanceof Element &&
        ((Element)node).getAttribute( "id").equalsIgnoreCase("K.TAMURA" ))) {
        // allow parsing all children of the node -- applies only to the current node
        tIterator.skipChildren();
      }
    }
  }
}

Listing Eleven
package aan.treexamples;
import aan.tree.*;
import org.w3c.dom.*;
public class SelectiveSetDepthTraversal implements ITraversal {
  /* Selectively traverses the tree using setLevelDepth */
  public void traverse (Node rootNode) {
    // create iterator, initially it is limited to the ID level
    int idLevel =2;
    TIterator tIterator = new TIterator (rootNode,new DOMAdapter(),idLevel);
    Node node = null;
    while( ( node=(Node)tIterator.next() )!=null ){
      // print node information
      System.out.println( node.getNodeName()+"="+node.getNodeValue());
      if  ( tIterator.getDepth() == idLevel && (node instanceof Element &&
        ((Element)node).getAttribute( "id").equalsIgnoreCase("K.TAMURA" ))) {
        // this allows iterator to traverse children of the current  node
        tIterator.setLevelDepth( TIterator.DEPTH_UNLIMITED);
      }
    }
  }
}