[jdom-interest] element iterator - code

David Kavanagh dak at dotech.com
Sat Jul 27 23:04:30 PDT 2002


I was in need of an element iterator (or tree walker) for JDOM and 
searched the archives on that topic. I know one is not included with 
JDOM. I just thought I'd post the one I wrote. I (or someone) could 
refactor this to remove references to some interfaces I use (which I've 
included for compilation reasons). Any interest in seeing this as port 
of a org.jdom.util package? I'd certainly be willing to contribute it.
You'll notice it was called AnakinTreeWalker. I had another 
implementation that was called LukeTreeWalker that used the crimson 
TreeWalker as a delegate. If it were to be included in jdom.util, I'm 
sure we could name it in the least humerous, and utilitarian way 
possible! :-)
BTW, this basicly does an in-order traversal of the elements in the 
tree, from a root provided. A tag name can be provided to filter the 
responses. I often use it in this way to find all instances of a given tag.

David Kavanagh

-------------- next part --------------
// Copyright 1998,1999,2000 Xerox Corporation, All Rights Reserved
// Xerox Digital Imaging Business Unit

package com.xerox.pix.template.xml2;

import java.util.List;

import org.jdom.Element;

import com.xerox.pix.template.ElementIterator;
import com.xerox.pix.template.TemplateElement;

//import com.dotech.GenericFactory;

/**
 * This class implements an ElementIterator
 *
 * @version $Revision$ $Date$
 * @author D. Kavanagh
 * @author developer at dotech.com
 */
public class AnakinTreeWalker implements ElementIterator {
	private Element root;
	private Element current;
	private List sibs;
	private boolean visitChildren;
	private String tagTarget;

	/**
	 * This method initializes the starting point for the search.
	 *
	 * @param root the starting element
	 */
	public void initialize(TemplateElement root) {
//		GenericFactory.debugMax( this, "Root element is " + root.getClass().getName() );
		this.root = (Element)root;
		this.current = (Element)root;
		this.sibs = null;
		this.visitChildren = false;
		this.tagTarget = null;
	}

	/**
	 * Returns the current element in the search.
	 *
	 * @return current search element
	 */
	public TemplateElement getCurrent() {
		if (current == null)
			throw new NullPointerException("Element not set.");
		return (TemplateElement)this.current;
	}

	/**
	 * This method returns the next element matching the search
	 * criteria. It uses the last available tag target. If none
	 * is available, the next available element is returned.
	 *
	 * @return next search element, null if search complete
	 */
	public TemplateElement getNext() {
		if (current == null)
			throw new NullPointerException("Element not set.");
		Element el = findNextElement();
		while (el != null) {
			if (this.tagTarget == null || el.getName().equals(this.tagTarget))
				if (el instanceof TemplateElement)
					break;
			el = findNextElement();
		}
//		GenericFactory.debugMax(this, "returning : "+((el!=null)?el.getName():null));
		return (TemplateElement)el;
	}

	/**
	 * This method returns the next element matching the tag
	 * passed in. The tag can be different each time this is
	 * method is called. The tag will be used in future calls
	 * to getNext().
	 *
	 * @param tag the target tag name
	 * @return next search element, null if search complete
	 */
	public TemplateElement getNextElement(String tag) {
		if (current == null)
			throw new NullPointerException("Element not set.");
		this.tagTarget = tag;
		return getNext();
	}

	/**
	 * This method resets the search to the initial node.
	 */
	public void reset() {
		if (current == null)
			throw new NullPointerException("Element not set.");
		this.current = this.root;
		this.sibs = null;
		this.visitChildren = false;
	}

	private Element findNextElement() {
		if (this.sibs == null) {
			if (this.current.hasChildren()) {
				this.sibs = this.current.getChildren();
				this.current = (Element)this.sibs.get(0);
				this.visitChildren = true;
//				GenericFactory.debugMax(this, "returning first child");
				return this.current;
			}
			else {
//				GenericFactory.debugMax(this, "returning null - end");
				return null;
			}
		}
		else {
			int idx = this.sibs.indexOf(this.current);
//			GenericFactory.debugMax(this, "sibs : "+idx+" of "+this.sibs.size());
			if (idx == (this.sibs.size()-1) && !visitChildren) { // pop back up a level
				this.current = this.current.getParent();
				if (this.current == this.root) {
//					GenericFactory.debugMax(this, "returning null - end");
					return null;	// done.
				}
				else {
					this.sibs = this.current.getParent().getChildren();
					this.visitChildren = false;
					return findNextElement();
				}
			}
			else {
				if (!this.visitChildren) { // return next sibling
					this.current = (Element)this.sibs.get(idx+1);
					this.visitChildren = true;
//					GenericFactory.debugMax(this, "returning next sib");
					return this.current;
				}
				else {	// dive down
					this.visitChildren = false;
					if (this.current.hasChildren()) { // check early, save a call
						this.sibs = null;
						return findNextElement();
					}
					else {
						return findNextElement();
					}
				}
			}
		}
	}

}
-------------- next part --------------
// Copyright 1998,1999,2000 Xerox Corporation, All Rights Reserved
// Xerox Digital Imaging Business Unit

package com.xerox.pix.template;

/**
 * This interface defines an iterator for retreiving elements from anwhere
 * in the product tree.
 *
 * @version $Revision: 1.1.1.1 $ $Date: 2000/07/21 20:31:38 $
 * @author D. Kavanagh
 * @author developer at dotech.com
 */
public interface ElementIterator {

	/**
	 * Sets the starting point in the product tree
	 *
	 * @param root the starting element
	 */
	public void initialize(TemplateElement root);

	/**
	 * Returns the current elmeent
	 */
	public TemplateElement getCurrent();

	/**
	 * Returns the next element in the product tree (becomes the current).
	 */
	public TemplateElement getNext();

	/**
	 * Returns the next element by name (makes that current).
	 *
	 * @param tag the name of the element type to look for
	 */
	public TemplateElement getNextElement(String tag);

	/**
	 * Sets the current node back to the root
	 */
	public void reset();
}
-------------- next part --------------
// Copyright 1998,1999,2000 Xerox Corporation, All Rights Reserved
// Xerox Digital Imaging Business Unit

package com.xerox.pix.template;

/**
 * This interface is a base for all element interfaces.
 *
 * @version $Revision: 1.4 $ $Date: 2002/07/27 17:38:37 $
 * @author D. Kavanagh
 * @author developer at dotech.com
 */
public interface TemplateElement {

	/**
	 * Get the direct children of this template element if there are any
	 * May return null if no children exist
	 **/
	TemplateElement [] getChildElements();

	/**
	 * Get the parent of this object if it has one
	 **/
	TemplateElement getParentElement();
}


More information about the jdom-interest mailing list