You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@commons.apache.org by "KARR, DAVID (ATTSI)" <dk...@att.com> on 2011/01/13 18:39:25 UTC

RE: [digester] Need help with simple digester usage

> -----Original Message-----
> From: Rahul Akolkar [mailto:rahul.akolkar@gmail.com]
> Sent: Monday, December 20, 2010 10:18 PM
> To: Commons Users List
> Subject: Re: [digester] Need help with simple digester usage
> 
> On Mon, Dec 20, 2010 at 11:08 PM, KARR, DAVID (ATTSI) <dk...@att.com>
> wrote:
> >> -----Original Message-----
> >> From: KARR, DAVID (ATTSI)
> >> Sent: Monday, December 20, 2010 7:54 PM
> >> To: user@commons.apache.org
> >> Subject: [digester] Need help with simple digester usage
> >>
> >> I'm trying to use Digester for a simple application.  I want to
> define
> >> the structure of a binary tree in XML, and then construct that node
> >> tree
> >> using Digester.
> >>
> >> The trivial "Node" class is just this:
> >> --------------------
> >>     public static class Node {
> >>         private Node left;
> >>         private Node right;
> >>         private String value;
> >>
> >>         public Node getLeft() { return left; }
> >>         public Node getRight() { return right; }
> >>         public String getValue() { return value; }
> >>
> >>         public void setLeft(Node left) { this.left = left; }
> >>         public void setRight(Node right) { this.right = right; }
> >>         public void setValue(String value) { this.value = value; }
> >>     }
> >> ------------
> >>
> >> The XML is composed of nested "node" elements.  The first "node"
> child
> >> gets set as the "left" property of the root, and the second gets set
> > as
> >> the "right" property.
> >>
> >> For instance:
> >>
> >>   <node value="abc">
> >>     <node value="def"/>
> >>   </node>
> >>
> >> Should result in a root Node with a "left" property referring to the
> >> second node.
> >>
> >> So, going through the Digester documentation, which I haven't looked
> > at
> >> in many years, I figured it would be something like this:
> >>
> >>         digester.addRule("*/node", new
> >> ObjectCreateRule(AugmentedNode.class));
> >>         digester.addRule("*/node", new SetPropertiesRule());
> >>         digester.addRule("*/node", new SetNextRule("addChild",
> >> AugmentedNode.class.getName()));
> >>
> >> Where "AugmentedNode" extends "Node", adding:
> >>
> >>        public void addChild(Node node) {
> >>             if (getLeft() == null)
> >>                 setLeft(node);
> >>             else
> >>                 setRight(node);
> >>         }
> >>
> >> For those well steeped in Digester lore, I imagine you can
> immediately
> >> tell this won't work.  You're right, of course.  This dies with an
> NPE
> >> in "MethodUtils.invokeMethod()" (object is null).  I have no clue
> >> what's
> >> wrong with this, or what I should be doing instead.
> >
> > Oh, ok.  I figured out one thing.  I have to push an AugmentedNode on
> > the stack before I start parsing, and then I take the result as the
> > "left" property of that top node.  Is that all I should have figured
> > out?  Is there a better way to do this in the first place?
> >
> <snip/>
> 
> Add this as the first rule, then the parse method will get you the
> actual (root) node:
> 
>   digester.addRule("node", new ObjectCreateRule(AugmentedNode.class));
> 
> This calls out the root as different from other nodes -- the root
> doesn't need a SetNextRule (thats the one causing the NPE since it has
> no parent).

I'm still not quite sure how to transform my existing code so I can use the top node, not the "left" of the top node.

My existing code is this:

        digester.push(new AugmentedNode());
        
        digester.addRule("*/node", new ObjectCreateRule(AugmentedNode.class));
        digester.addRule("*/node", new SetPropertiesRule());
        digester.addRule("*/node", new SetNextRule("addChild", AugmentedNode.class.getName()));
        
        return ((Node) digester.parse(new StringReader(xml))).getLeft();

I've tried several variations with adding that line you suggest, but I can't get it to work, and I'm not sure exactly what it's trying to accomplish.

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


Re: [digester] Need help with simple digester usage

Posted by Jimmy Zhang <cr...@comcast.net>.
You may want to look at extended vtd-xml, which is significantly better than
digester in memory and performance, and ease of use...

-----Original Message----- 
From: KARR, DAVID (ATTSI)
Sent: Thursday, January 13, 2011 9:39 AM
To: Commons Users List
Subject: RE: [digester] Need help with simple digester usage

> -----Original Message-----
> From: Rahul Akolkar [mailto:rahul.akolkar@gmail.com]
> Sent: Monday, December 20, 2010 10:18 PM
> To: Commons Users List
> Subject: Re: [digester] Need help with simple digester usage
>
> On Mon, Dec 20, 2010 at 11:08 PM, KARR, DAVID (ATTSI) <dk...@att.com>
> wrote:
> >> -----Original Message-----
> >> From: KARR, DAVID (ATTSI)
> >> Sent: Monday, December 20, 2010 7:54 PM
> >> To: user@commons.apache.org
> >> Subject: [digester] Need help with simple digester usage
> >>
> >> I'm trying to use Digester for a simple application.  I want to
> define
> >> the structure of a binary tree in XML, and then construct that node
> >> tree
> >> using Digester.
> >>
> >> The trivial "Node" class is just this:
> >> --------------------
> >>     public static class Node {
> >>         private Node left;
> >>         private Node right;
> >>         private String value;
> >>
> >>         public Node getLeft() { return left; }
> >>         public Node getRight() { return right; }
> >>         public String getValue() { return value; }
> >>
> >>         public void setLeft(Node left) { this.left = left; }
> >>         public void setRight(Node right) { this.right = right; }
> >>         public void setValue(String value) { this.value = value; }
> >>     }
> >> ------------
> >>
> >> The XML is composed of nested "node" elements.  The first "node"
> child
> >> gets set as the "left" property of the root, and the second gets set
> > as
> >> the "right" property.
> >>
> >> For instance:
> >>
> >>   <node value="abc">
> >>     <node value="def"/>
> >>   </node>
> >>
> >> Should result in a root Node with a "left" property referring to the
> >> second node.
> >>
> >> So, going through the Digester documentation, which I haven't looked
> > at
> >> in many years, I figured it would be something like this:
> >>
> >>         digester.addRule("*/node", new
> >> ObjectCreateRule(AugmentedNode.class));
> >>         digester.addRule("*/node", new SetPropertiesRule());
> >>         digester.addRule("*/node", new SetNextRule("addChild",
> >> AugmentedNode.class.getName()));
> >>
> >> Where "AugmentedNode" extends "Node", adding:
> >>
> >>        public void addChild(Node node) {
> >>             if (getLeft() == null)
> >>                 setLeft(node);
> >>             else
> >>                 setRight(node);
> >>         }
> >>
> >> For those well steeped in Digester lore, I imagine you can
> immediately
> >> tell this won't work.  You're right, of course.  This dies with an
> NPE
> >> in "MethodUtils.invokeMethod()" (object is null).  I have no clue
> >> what's
> >> wrong with this, or what I should be doing instead.
> >
> > Oh, ok.  I figured out one thing.  I have to push an AugmentedNode on
> > the stack before I start parsing, and then I take the result as the
> > "left" property of that top node.  Is that all I should have figured
> > out?  Is there a better way to do this in the first place?
> >
> <snip/>
>
> Add this as the first rule, then the parse method will get you the
> actual (root) node:
>
>   digester.addRule("node", new ObjectCreateRule(AugmentedNode.class));
>
> This calls out the root as different from other nodes -- the root
> doesn't need a SetNextRule (thats the one causing the NPE since it has
> no parent).

I'm still not quite sure how to transform my existing code so I can use the 
top node, not the "left" of the top node.

My existing code is this:

        digester.push(new AugmentedNode());

        digester.addRule("*/node", new 
ObjectCreateRule(AugmentedNode.class));
        digester.addRule("*/node", new SetPropertiesRule());
        digester.addRule("*/node", new SetNextRule("addChild", 
AugmentedNode.class.getName()));

        return ((Node) digester.parse(new StringReader(xml))).getLeft();

I've tried several variations with adding that line you suggest, but I can't 
get it to work, and I'm not sure exactly what it's trying to accomplish.

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org 


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


RE: [digester] Need help with simple digester usage

Posted by "KARR, DAVID (ATTSI)" <dk...@att.com>.
> -----Original Message-----
> From: Rahul Akolkar [mailto:rahul.akolkar@gmail.com]
> Sent: Thursday, January 13, 2011 7:42 PM
> To: Commons Users List
> Subject: Re: [digester] Need help with simple digester usage
> 
> On Thu, Jan 13, 2011 at 7:40 PM, KARR, DAVID (ATTSI) <dk...@att.com>
> wrote:
> >> -----Original Message-----
> >> From: Rahul Akolkar
> >> Sent: Thursday, January 13, 2011 2:07 PM
> >> To: Commons Users List
> >> Subject: Re: [digester] Need help with simple digester usage
> >>
> >> On Thu, Jan 13, 2011 at 12:39 PM, KARR, DAVID (ATTSI)
> <dk...@att.com>
> >> wrote:
> >> >> -----Original Message-----
> >> >> From: Rahul Akolkar
> >> >> Sent: Monday, December 20, 2010 10:18 PM
> >> >> To: Commons Users List
> >> >> Subject: Re: [digester] Need help with simple digester usage
> >> >>
> >> >> On Mon, Dec 20, 2010 at 11:08 PM, KARR, DAVID (ATTSI)
> >> <dk...@att.com>
> >> >> wrote:
> >> >> >> -----Original Message-----
> >> >> >> From: KARR, DAVID (ATTSI)
> >> >> >> Sent: Monday, December 20, 2010 7:54 PM
> >> >> >> To: user@commons.apache.org
> >> >> >> Subject: [digester] Need help with simple digester usage
> >> >> >>
> >> >> >> I'm trying to use Digester for a simple application.  I want
> to
> >> >> define
> >> >> >> the structure of a binary tree in XML, and then construct that
> >> node
> >> >> >> tree
> >> >> >> using Digester.
> >> >> >>
> >> >> >> The trivial "Node" class is just this:
> >> >> >> --------------------
> >> >> >>     public static class Node {
> >> >> >>         private Node left;
> >> >> >>         private Node right;
> >> >> >>         private String value;
> >> >> >>
> >> >> >>         public Node getLeft() { return left; }
> >> >> >>         public Node getRight() { return right; }
> >> >> >>         public String getValue() { return value; }
> >> >> >>
> >> >> >>         public void setLeft(Node left) { this.left = left; }
> >> >> >>         public void setRight(Node right) { this.right = right;
> }
> >> >> >>         public void setValue(String value) { this.value =
> value;
> >> }
> >> >> >>     }
> >> >> >> ------------
> >> >> >>
> >> >> >> The XML is composed of nested "node" elements.  The first
> "node"
> >> >> child
> >> >> >> gets set as the "left" property of the root, and the second
> gets
> >> set
> >> >> > as
> >> >> >> the "right" property.
> >> >> >>
> >> >> >> For instance:
> >> >> >>
> >> >> >>   <node value="abc">
> >> >> >>     <node value="def"/>
> >> >> >>   </node>
> >> >> >>
> >> >> >> Should result in a root Node with a "left" property referring
> to
> >> the
> >> >> >> second node.
> >> >> >>
> >> >> >> So, going through the Digester documentation, which I haven't
> >> looked
> >> >> > at
> >> >> >> in many years, I figured it would be something like this:
> >> >> >>
> >> >> >>         digester.addRule("*/node", new
> >> >> >> ObjectCreateRule(AugmentedNode.class));
> >> >> >>         digester.addRule("*/node", new SetPropertiesRule());
> >> >> >>         digester.addRule("*/node", new SetNextRule("addChild",
> >> >> >> AugmentedNode.class.getName()));
> >> >> >>
> >> >> >> Where "AugmentedNode" extends "Node", adding:
> >> >> >>
> >> >> >>        public void addChild(Node node) {
> >> >> >>             if (getLeft() == null)
> >> >> >>                 setLeft(node);
> >> >> >>             else
> >> >> >>                 setRight(node);
> >> >> >>         }
> >> >> >>
> >> >> >> For those well steeped in Digester lore, I imagine you can
> >> >> immediately
> >> >> >> tell this won't work.  You're right, of course.  This dies
> with
> >> an
> >> >> NPE
> >> >> >> in "MethodUtils.invokeMethod()" (object is null).  I have no
> clue
> >> >> >> what's
> >> >> >> wrong with this, or what I should be doing instead.
> >> >> >
> >> >> > Oh, ok.  I figured out one thing.  I have to push an
> AugmentedNode
> >> on
> >> >> > the stack before I start parsing, and then I take the result as
> >> the
> >> >> > "left" property of that top node.  Is that all I should have
> >> figured
> >> >> > out?  Is there a better way to do this in the first place?
> >> >> >
> >> >> <snip/>
> >> >>
> >> >> Add this as the first rule, then the parse method will get you
> the
> >> >> actual (root) node:
> >> >>
> >> >>   digester.addRule("node", new
> >> ObjectCreateRule(AugmentedNode.class));
> >> >>
> >> >> This calls out the root as different from other nodes -- the root
> >> >> doesn't need a SetNextRule (thats the one causing the NPE since
> it
> >> has
> >> >> no parent).
> >> >
> >> > I'm still not quite sure how to transform my existing code so I
> can
> >> use the top node, not the "left" of the top node.
> >> >
> >> > My existing code is this:
> >> >
> >> >        digester.push(new AugmentedNode());
> >> >
> >> >        digester.addRule("*/node", new
> >> ObjectCreateRule(AugmentedNode.class));
> >> >        digester.addRule("*/node", new SetPropertiesRule());
> >> >        digester.addRule("*/node", new SetNextRule("addChild",
> >> AugmentedNode.class.getName()));
> >> >
> >> >        return ((Node) digester.parse(new
> >> StringReader(xml))).getLeft();
> >> >
> >> > I've tried several variations with adding that line you suggest,
> but
> >> I can't get it to work, and I'm not sure exactly what it's trying to
> >> accomplish.
> >> >
> >> <snip/>
> >>
> >> Try this, per previous email:
> >>
> >>     digester.addRule("node", new
> >> ObjectCreateRule(AugmentedNode.class));
> >>     // above line is better match for root (not using push)
> <snip/>
> 
> Given the root node can also have a value attribute, need this (insert
> after the line above):
> 
>     digester.addRule("node", new SetPropertiesRule());

Ah.  Got it.  That worked.  Thanks.

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


Re: [digester] Need help with simple digester usage

Posted by Rahul Akolkar <ra...@gmail.com>.
On Thu, Jan 13, 2011 at 7:40 PM, KARR, DAVID (ATTSI) <dk...@att.com> wrote:
>> -----Original Message-----
>> From: Rahul Akolkar
>> Sent: Thursday, January 13, 2011 2:07 PM
>> To: Commons Users List
>> Subject: Re: [digester] Need help with simple digester usage
>>
>> On Thu, Jan 13, 2011 at 12:39 PM, KARR, DAVID (ATTSI) <dk...@att.com>
>> wrote:
>> >> -----Original Message-----
>> >> From: Rahul Akolkar
>> >> Sent: Monday, December 20, 2010 10:18 PM
>> >> To: Commons Users List
>> >> Subject: Re: [digester] Need help with simple digester usage
>> >>
>> >> On Mon, Dec 20, 2010 at 11:08 PM, KARR, DAVID (ATTSI)
>> <dk...@att.com>
>> >> wrote:
>> >> >> -----Original Message-----
>> >> >> From: KARR, DAVID (ATTSI)
>> >> >> Sent: Monday, December 20, 2010 7:54 PM
>> >> >> To: user@commons.apache.org
>> >> >> Subject: [digester] Need help with simple digester usage
>> >> >>
>> >> >> I'm trying to use Digester for a simple application.  I want to
>> >> define
>> >> >> the structure of a binary tree in XML, and then construct that
>> node
>> >> >> tree
>> >> >> using Digester.
>> >> >>
>> >> >> The trivial "Node" class is just this:
>> >> >> --------------------
>> >> >>     public static class Node {
>> >> >>         private Node left;
>> >> >>         private Node right;
>> >> >>         private String value;
>> >> >>
>> >> >>         public Node getLeft() { return left; }
>> >> >>         public Node getRight() { return right; }
>> >> >>         public String getValue() { return value; }
>> >> >>
>> >> >>         public void setLeft(Node left) { this.left = left; }
>> >> >>         public void setRight(Node right) { this.right = right; }
>> >> >>         public void setValue(String value) { this.value = value;
>> }
>> >> >>     }
>> >> >> ------------
>> >> >>
>> >> >> The XML is composed of nested "node" elements.  The first "node"
>> >> child
>> >> >> gets set as the "left" property of the root, and the second gets
>> set
>> >> > as
>> >> >> the "right" property.
>> >> >>
>> >> >> For instance:
>> >> >>
>> >> >>   <node value="abc">
>> >> >>     <node value="def"/>
>> >> >>   </node>
>> >> >>
>> >> >> Should result in a root Node with a "left" property referring to
>> the
>> >> >> second node.
>> >> >>
>> >> >> So, going through the Digester documentation, which I haven't
>> looked
>> >> > at
>> >> >> in many years, I figured it would be something like this:
>> >> >>
>> >> >>         digester.addRule("*/node", new
>> >> >> ObjectCreateRule(AugmentedNode.class));
>> >> >>         digester.addRule("*/node", new SetPropertiesRule());
>> >> >>         digester.addRule("*/node", new SetNextRule("addChild",
>> >> >> AugmentedNode.class.getName()));
>> >> >>
>> >> >> Where "AugmentedNode" extends "Node", adding:
>> >> >>
>> >> >>        public void addChild(Node node) {
>> >> >>             if (getLeft() == null)
>> >> >>                 setLeft(node);
>> >> >>             else
>> >> >>                 setRight(node);
>> >> >>         }
>> >> >>
>> >> >> For those well steeped in Digester lore, I imagine you can
>> >> immediately
>> >> >> tell this won't work.  You're right, of course.  This dies with
>> an
>> >> NPE
>> >> >> in "MethodUtils.invokeMethod()" (object is null).  I have no clue
>> >> >> what's
>> >> >> wrong with this, or what I should be doing instead.
>> >> >
>> >> > Oh, ok.  I figured out one thing.  I have to push an AugmentedNode
>> on
>> >> > the stack before I start parsing, and then I take the result as
>> the
>> >> > "left" property of that top node.  Is that all I should have
>> figured
>> >> > out?  Is there a better way to do this in the first place?
>> >> >
>> >> <snip/>
>> >>
>> >> Add this as the first rule, then the parse method will get you the
>> >> actual (root) node:
>> >>
>> >>   digester.addRule("node", new
>> ObjectCreateRule(AugmentedNode.class));
>> >>
>> >> This calls out the root as different from other nodes -- the root
>> >> doesn't need a SetNextRule (thats the one causing the NPE since it
>> has
>> >> no parent).
>> >
>> > I'm still not quite sure how to transform my existing code so I can
>> use the top node, not the "left" of the top node.
>> >
>> > My existing code is this:
>> >
>> >        digester.push(new AugmentedNode());
>> >
>> >        digester.addRule("*/node", new
>> ObjectCreateRule(AugmentedNode.class));
>> >        digester.addRule("*/node", new SetPropertiesRule());
>> >        digester.addRule("*/node", new SetNextRule("addChild",
>> AugmentedNode.class.getName()));
>> >
>> >        return ((Node) digester.parse(new
>> StringReader(xml))).getLeft();
>> >
>> > I've tried several variations with adding that line you suggest, but
>> I can't get it to work, and I'm not sure exactly what it's trying to
>> accomplish.
>> >
>> <snip/>
>>
>> Try this, per previous email:
>>
>>     digester.addRule("node", new
>> ObjectCreateRule(AugmentedNode.class));
>>     // above line is better match for root (not using push)
<snip/>

Given the root node can also have a value attribute, need this (insert
after the line above):

    digester.addRule("node", new SetPropertiesRule());

-Rahul



>>     digester.addRule("*/node", new
>> ObjectCreateRule(AugmentedNode.class));
>>     digester.addRule("*/node", new SetPropertiesRule());
>>     digester.addRule("*/node", new SetNextRule("addChild",
>> AugmentedNode.class.getName()));
>>     return ((Node) digester.parse(new StringReader(xml)));
>>     // above line is without getLeft()
>
> That causes my tests to fail.  It appears as if it's not returning the root node, but some other node.
>
> How about if I include my CUT and test class here?
> -----------------------
> package binarytree;
>
> import java.util.HashSet;
> import java.util.Set;
> import java.util.Stack;
>
> /**
>  * Perform pre, in, and post order traversal of a binary tree, using nonrecursive methods.
>  *
>  * Based on algorithms from <http://en.wikipedia.org/wiki/Tree_traversal#Iterative_Traversal>.
>  *
>  * @author dk068x
>  */
> public class NonRecursiveBinaryTreeTraversal {
>    /**
>     * Perform a preorder traversal.  This will process the data in the node before processing the data in the
>     * left and right child.
>     */
>    public static void preOrder(Node rootNode, Visitor visitor) {
>        Stack<Node>   nodeStack   = new Stack<Node>();
>        nodeStack.push(rootNode);
>        while (!nodeStack.empty()) {
>            // At each level, we process the data in the node and then push the right and left child and then repeat.
>            Node    node        = nodeStack.pop();
>            visitor.visit(node);
>            Node    rightNode    = node.getRight();
>            if (rightNode != null)
>                nodeStack.push(rightNode);
>            Node    leftNode    = node.getLeft();
>            if (leftNode != null)
>                nodeStack.push(leftNode);
>        }
>    }
>
>    /**
>     * Perform an inorder traversal. This will process the data in the node after processing the data in the left child,
>     * and before processing the data in the right child.
>     */
>    public static void inOrder(Node rootNode, Visitor visitor) {
>        Stack<Node>   nodeStack   = new Stack<Node>();
>        Node    currentNode = rootNode;
>        while (true) {
>            // We walk the left branch, pushing nodes until we reach the end, then we process the data at the top
>            // of the stack, then walk to the right child, and then repeat.
>            if (currentNode != null) {
>                nodeStack.push(currentNode);
>                currentNode = currentNode.getLeft();
>            }
>            else if (nodeStack.size() > 0){
>                currentNode = nodeStack.pop();
>                visitor.visit(currentNode);
>                currentNode = currentNode.getRight();
>            }
>            else
>                break;
>        }
>    }
>
>    /**
>     * Perform a postorder traversal.  This will process the data in the node after processing the data in the left
>     * and right child.
>     */
>    public static void postOrder(Node rootNode, Visitor visitor) {
>        Stack<Node> nodeStack   = new Stack<Node>();
>        Set<Node>   visitedSet  = new HashSet<Node>();
>        nodeStack.push(rootNode);
>        while (!nodeStack.isEmpty()) {
>            // At each iteration, we peek at the top node, and push the left and right child if they are not null,
>            // and we haven't visited those nodes.  If both left and right are null OR we've visited both of them,
>            // then process the data in the current node (the one we've peeked at), add it to the visited set,
>            // and pop it.
>            Node    node    = nodeStack.peek();
>            if (node.getLeft() != null && !visitedSet.contains(node.getLeft()))
>                nodeStack.push(node.getLeft());
>            else if (node.getRight() != null && !visitedSet.contains(node.getRight()))
>                nodeStack.push(node.getRight());
>            else {
>                visitor.visit(node);
>                visitedSet.add(node);
>                nodeStack.pop();
>            }
>        }
>    }
>
>    public static class PrintVisitor implements Visitor {
>        @Override
>        public void visit(Node node) {
>            System.out.println("node.value[" + node.getValue() + "]");
>        }
>    }
>
>    public static interface Visitor {
>        public void visit(Node node);
>    }
>
>    public static class Node {
>        private Node left;
>        private Node right;
>        private String value;
>
>        public Node getLeft() { return left; }
>        public Node getRight() { return right; }
>        public String getValue() { return value; }
>
>        public void setLeft(Node left) { this.left = left; }
>        public void setRight(Node right) { this.right = right; }
>        public void setValue(String value) { this.value = value; }
>    }
> }
> -----------------------
> package binarytree;
>
> import static org.junit.Assert.*;
>
> import java.io.IOException;
> import java.io.StringReader;
> import java.util.ArrayList;
> import java.util.List;
>
> import org.apache.commons.digester.Digester;
> import org.apache.commons.digester.ObjectCreateRule;
> import org.apache.commons.digester.SetNextRule;
> import org.apache.commons.digester.SetPropertiesRule;
> import org.junit.Test;
> import org.xml.sax.SAXException;
>
> import binarytree.NonRecursiveBinaryTreeTraversal.Node;
> import binarytree.NonRecursiveBinaryTreeTraversal.Visitor;
>
> public class NonRecursiveBinaryTreeTraversalTest {
>    @Test
>    public void testPreorderTrivial() throws Exception {
>        Node    rootNode    =
>            parseXml("<node value=\"1\">" +
>                     "</node>");
>        final List<String>  foundNodes          = new ArrayList<String>();
>        Visitor             addToListVisitor    = new AddToListVisitor(foundNodes);
>
>        NonRecursiveBinaryTreeTraversal.preOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "1");
>
>        NonRecursiveBinaryTreeTraversal.inOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "1");
>
>        NonRecursiveBinaryTreeTraversal.postOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "1");
>    }
>
>    @Test
>    public void testPreorderSimple1() throws Exception {
>        Node    rootNode    =
>            parseXml("<node value=\"1\">" +
>                     " <node value=\"2\"/>" +
>                     "</node>");
>        final List<String>  foundNodes          = new ArrayList<String>();
>        Visitor             addToListVisitor    = new AddToListVisitor(foundNodes);
>
>        NonRecursiveBinaryTreeTraversal.preOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "1", "2");
>
>        NonRecursiveBinaryTreeTraversal.inOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "2", "1");
>
>        NonRecursiveBinaryTreeTraversal.postOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "2", "1");
>    }
>
>    @Test
>    public void testPreorderSimple2() throws Exception {
>        Node    rootNode    =
>            parseXml("<node value=\"1\">" +
>                     " <node value=\"2\"/>" +
>                     " <node value=\"3\"/>" +
>                     "</node>");
>        final List<String>  foundNodes          = new ArrayList<String>();
>        Visitor             addToListVisitor    = new AddToListVisitor(foundNodes);
>
>        NonRecursiveBinaryTreeTraversal.preOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "1", "2", "3");
>
>        NonRecursiveBinaryTreeTraversal.inOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "2", "1", "3");
>
>        NonRecursiveBinaryTreeTraversal.postOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "2", "3", "1");
>    }
>
>    @Test
>    public void testPreorderSimple3() throws Exception {
>        Node    rootNode    =
>            parseXml("<node value=\"1\">" +
>                     " <node value=\"2\">" +
>                     "   <node value=\"3\"/>" +
>                     " </node>" +
>                     " <node value=\"4\"/>" +
>                     "</node>");
>        final List<String>  foundNodes          = new ArrayList<String>();
>        Visitor             addToListVisitor    = new AddToListVisitor(foundNodes);
>
>        NonRecursiveBinaryTreeTraversal.preOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "1", "2", "3", "4");
>
>        NonRecursiveBinaryTreeTraversal.inOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "3", "2", "1", "4");
>
>        NonRecursiveBinaryTreeTraversal.postOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "3", "2", "4", "1");
>    }
>
>    @Test
>    public void testPreorderSimple4() throws Exception {
>        Node    rootNode    =
>            parseXml("<node value=\"1\">" +
>                     " <node value=\"2\">" +
>                     "  <node value=\"4\"/>" +
>                     "  <node value=\"5\">" +
>                     "   <node value=\"8\"/>" +
>                     "  </node>" +
>                     " </node>" +
>                     " <node value=\"3\">" +
>                     "  <node value=\"6\"/>" +
>                     "  <node value=\"7\"/>" +
>                     " </node>" +
>                     "</node>");
>        final List<String>  foundNodes          = new ArrayList<String>();
>        Visitor             addToListVisitor    = new AddToListVisitor(foundNodes);
>
>        NonRecursiveBinaryTreeTraversal.preOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "1", "2", "4", "5", "8", "3", "6", "7");
>
>        NonRecursiveBinaryTreeTraversal.inOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "4", "2", "8", "5", "1", "6", "3", "7");
>
>        NonRecursiveBinaryTreeTraversal.postOrder(rootNode, addToListVisitor);
>        verifyOrder(foundNodes, "4", "8", "5", "2", "6", "7", "3", "1");
>    }
>
>    private void verifyOrder(List<String> foundOrder, String... requiredOrder) {
>        if (requiredOrder.length != foundOrder.size())
>            fail("Found " +
>                    foundOrder.size() + " node" + (foundOrder.size() == 0 ? "" : "s") +
>                    ", but needed " +
>                    requiredOrder.length + " node" + (requiredOrder.length == 0 ? "" : "s") +
>                    ", with required order " + renderOrder(requiredOrder) + " and found order " +
>                    renderOrder(foundOrder) + ".");
>        else {
>            for (int ctr = 0; ctr < foundOrder.size(); ++ ctr) {
>                if (!foundOrder.get(ctr).equals(requiredOrder[ctr])) {
>                    fail("Order entry " + ctr + " should have been " + requiredOrder[ctr] + ", but it was " +
>                            foundOrder.get(ctr) + ", required order " + renderOrder(requiredOrder) +
>                            " and found order " + renderOrder(foundOrder) + ".");
>                }
>            }
>        }
>
>        // This is a side effect for the convenience of the tests.
>        foundOrder.clear();
>    }
>
>    private String renderOrder(String[] strs) {
>        StringBuilder   sb  = new StringBuilder();
>        for (int ctr = 0; ctr < strs.length; ++ ctr) {
>            sb.append(strs[ctr]);
>            if (ctr < strs.length - 1)
>                sb.append(", ");
>        }
>        return sb.toString();
>    }
>
>    private String renderOrder(List<String> strs) {
>        return renderOrder(strs.toArray(new String[strs.size()]));
>    }
>
>    private Node    parseXml(String xml) throws IOException, SAXException {
>        Digester    digester    = new Digester();
>
>        // The easiest way to do this with Digester is to push a fake node on the top of the stack.  The "left"
>        // property of that node will be the resulting tree. Also note that we have to define a Node subclass with a
>        // single method to add a child, and it figures out whether to add the child as the left or the right property.
>
>        // digester.push(new AugmentedNode());
>
> //        digester.addRule("node", new ObjectCreateRule(AugmentedNode.class));
>        digester.addRule("*/node", new ObjectCreateRule(AugmentedNode.class));
>        digester.addRule("*/node", new SetPropertiesRule());
>        digester.addRule("*/node", new SetNextRule("addChild", AugmentedNode.class.getName()));
>
>        return ((Node) digester.parse(new StringReader(xml))).getLeft();
> //        return ((Node) digester.parse(new StringReader(xml)));
>    }
>
>    public static class AddToListVisitor implements Visitor {
>        private List<String>    list;
>
>        public AddToListVisitor(List<String> list) {
>            this.list   = list;
>        }
>
>        @Override
>        public void visit(Node node) {
>            list.add(node.getValue());
>        }
>    }
>
>    public static class AugmentedNode extends Node {
>        public void addChild(Node node) {
>            if (getLeft() == null)
>                setLeft(node);
>            else
>                setRight(node);
>        }
>    }
> }
> -----------------------

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


RE: [digester] Need help with simple digester usage

Posted by "KARR, DAVID (ATTSI)" <dk...@att.com>.
> -----Original Message-----
> From: Rahul Akolkar [mailto:rahul.akolkar@gmail.com]
> Sent: Thursday, January 13, 2011 2:07 PM
> To: Commons Users List
> Subject: Re: [digester] Need help with simple digester usage
> 
> On Thu, Jan 13, 2011 at 12:39 PM, KARR, DAVID (ATTSI) <dk...@att.com>
> wrote:
> >> -----Original Message-----
> >> From: Rahul Akolkar
> >> Sent: Monday, December 20, 2010 10:18 PM
> >> To: Commons Users List
> >> Subject: Re: [digester] Need help with simple digester usage
> >>
> >> On Mon, Dec 20, 2010 at 11:08 PM, KARR, DAVID (ATTSI)
> <dk...@att.com>
> >> wrote:
> >> >> -----Original Message-----
> >> >> From: KARR, DAVID (ATTSI)
> >> >> Sent: Monday, December 20, 2010 7:54 PM
> >> >> To: user@commons.apache.org
> >> >> Subject: [digester] Need help with simple digester usage
> >> >>
> >> >> I'm trying to use Digester for a simple application.  I want to
> >> define
> >> >> the structure of a binary tree in XML, and then construct that
> node
> >> >> tree
> >> >> using Digester.
> >> >>
> >> >> The trivial "Node" class is just this:
> >> >> --------------------
> >> >>     public static class Node {
> >> >>         private Node left;
> >> >>         private Node right;
> >> >>         private String value;
> >> >>
> >> >>         public Node getLeft() { return left; }
> >> >>         public Node getRight() { return right; }
> >> >>         public String getValue() { return value; }
> >> >>
> >> >>         public void setLeft(Node left) { this.left = left; }
> >> >>         public void setRight(Node right) { this.right = right; }
> >> >>         public void setValue(String value) { this.value = value;
> }
> >> >>     }
> >> >> ------------
> >> >>
> >> >> The XML is composed of nested "node" elements.  The first "node"
> >> child
> >> >> gets set as the "left" property of the root, and the second gets
> set
> >> > as
> >> >> the "right" property.
> >> >>
> >> >> For instance:
> >> >>
> >> >>   <node value="abc">
> >> >>     <node value="def"/>
> >> >>   </node>
> >> >>
> >> >> Should result in a root Node with a "left" property referring to
> the
> >> >> second node.
> >> >>
> >> >> So, going through the Digester documentation, which I haven't
> looked
> >> > at
> >> >> in many years, I figured it would be something like this:
> >> >>
> >> >>         digester.addRule("*/node", new
> >> >> ObjectCreateRule(AugmentedNode.class));
> >> >>         digester.addRule("*/node", new SetPropertiesRule());
> >> >>         digester.addRule("*/node", new SetNextRule("addChild",
> >> >> AugmentedNode.class.getName()));
> >> >>
> >> >> Where "AugmentedNode" extends "Node", adding:
> >> >>
> >> >>        public void addChild(Node node) {
> >> >>             if (getLeft() == null)
> >> >>                 setLeft(node);
> >> >>             else
> >> >>                 setRight(node);
> >> >>         }
> >> >>
> >> >> For those well steeped in Digester lore, I imagine you can
> >> immediately
> >> >> tell this won't work.  You're right, of course.  This dies with
> an
> >> NPE
> >> >> in "MethodUtils.invokeMethod()" (object is null).  I have no clue
> >> >> what's
> >> >> wrong with this, or what I should be doing instead.
> >> >
> >> > Oh, ok.  I figured out one thing.  I have to push an AugmentedNode
> on
> >> > the stack before I start parsing, and then I take the result as
> the
> >> > "left" property of that top node.  Is that all I should have
> figured
> >> > out?  Is there a better way to do this in the first place?
> >> >
> >> <snip/>
> >>
> >> Add this as the first rule, then the parse method will get you the
> >> actual (root) node:
> >>
> >>   digester.addRule("node", new
> ObjectCreateRule(AugmentedNode.class));
> >>
> >> This calls out the root as different from other nodes -- the root
> >> doesn't need a SetNextRule (thats the one causing the NPE since it
> has
> >> no parent).
> >
> > I'm still not quite sure how to transform my existing code so I can
> use the top node, not the "left" of the top node.
> >
> > My existing code is this:
> >
> >        digester.push(new AugmentedNode());
> >
> >        digester.addRule("*/node", new
> ObjectCreateRule(AugmentedNode.class));
> >        digester.addRule("*/node", new SetPropertiesRule());
> >        digester.addRule("*/node", new SetNextRule("addChild",
> AugmentedNode.class.getName()));
> >
> >        return ((Node) digester.parse(new
> StringReader(xml))).getLeft();
> >
> > I've tried several variations with adding that line you suggest, but
> I can't get it to work, and I'm not sure exactly what it's trying to
> accomplish.
> >
> <snip/>
> 
> Try this, per previous email:
> 
>     digester.addRule("node", new
> ObjectCreateRule(AugmentedNode.class));
>     // above line is better match for root (not using push)
>     digester.addRule("*/node", new
> ObjectCreateRule(AugmentedNode.class));
>     digester.addRule("*/node", new SetPropertiesRule());
>     digester.addRule("*/node", new SetNextRule("addChild",
> AugmentedNode.class.getName()));
>     return ((Node) digester.parse(new StringReader(xml)));
>     // above line is without getLeft()

That causes my tests to fail.  It appears as if it's not returning the root node, but some other node.

How about if I include my CUT and test class here?
-----------------------
package binarytree;

import java.util.HashSet;
import java.util.Set;
import java.util.Stack;

/**
 * Perform pre, in, and post order traversal of a binary tree, using nonrecursive methods.
 * 
 * Based on algorithms from <http://en.wikipedia.org/wiki/Tree_traversal#Iterative_Traversal>.
 * 
 * @author dk068x
 */
public class NonRecursiveBinaryTreeTraversal {
    /**
     * Perform a preorder traversal.  This will process the data in the node before processing the data in the
     * left and right child.
     */
    public static void preOrder(Node rootNode, Visitor visitor) {
        Stack<Node>   nodeStack   = new Stack<Node>();
        nodeStack.push(rootNode);
        while (!nodeStack.empty()) {
            // At each level, we process the data in the node and then push the right and left child and then repeat.
            Node    node        = nodeStack.pop();
            visitor.visit(node);
            Node    rightNode    = node.getRight();
            if (rightNode != null)
                nodeStack.push(rightNode);
            Node    leftNode    = node.getLeft();
            if (leftNode != null)
                nodeStack.push(leftNode);
        }
    }

    /**
     * Perform an inorder traversal. This will process the data in the node after processing the data in the left child,
     * and before processing the data in the right child.
     */
    public static void inOrder(Node rootNode, Visitor visitor) {
        Stack<Node>   nodeStack   = new Stack<Node>();
        Node    currentNode = rootNode;
        while (true) {
            // We walk the left branch, pushing nodes until we reach the end, then we process the data at the top
            // of the stack, then walk to the right child, and then repeat.
            if (currentNode != null) {
                nodeStack.push(currentNode);
                currentNode = currentNode.getLeft();
            }
            else if (nodeStack.size() > 0){
                currentNode = nodeStack.pop();
                visitor.visit(currentNode);
                currentNode = currentNode.getRight();
            }
            else
                break;
        }
    }

    /**
     * Perform a postorder traversal.  This will process the data in the node after processing the data in the left
     * and right child.
     */
    public static void postOrder(Node rootNode, Visitor visitor) {
        Stack<Node> nodeStack   = new Stack<Node>();
        Set<Node>   visitedSet  = new HashSet<Node>();
        nodeStack.push(rootNode);
        while (!nodeStack.isEmpty()) {
            // At each iteration, we peek at the top node, and push the left and right child if they are not null,
            // and we haven't visited those nodes.  If both left and right are null OR we've visited both of them,
            // then process the data in the current node (the one we've peeked at), add it to the visited set,
            // and pop it.
            Node    node    = nodeStack.peek();
            if (node.getLeft() != null && !visitedSet.contains(node.getLeft()))
                nodeStack.push(node.getLeft());
            else if (node.getRight() != null && !visitedSet.contains(node.getRight()))
                nodeStack.push(node.getRight());
            else {
                visitor.visit(node);
                visitedSet.add(node);
                nodeStack.pop();
            }
        }
    }
    
    public static class PrintVisitor implements Visitor {
        @Override
        public void visit(Node node) {
            System.out.println("node.value[" + node.getValue() + "]");
        }
    }
    
    public static interface Visitor {
        public void visit(Node node);
    }
    
    public static class Node {
        private Node left;
        private Node right;
        private String value;
        
        public Node getLeft() { return left; }
        public Node getRight() { return right; }
        public String getValue() { return value; }
        
        public void setLeft(Node left) { this.left = left; }
        public void setRight(Node right) { this.right = right; }
        public void setValue(String value) { this.value = value; }
    }
}
-----------------------
package binarytree;

import static org.junit.Assert.*;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.digester.Digester;
import org.apache.commons.digester.ObjectCreateRule;
import org.apache.commons.digester.SetNextRule;
import org.apache.commons.digester.SetPropertiesRule;
import org.junit.Test;
import org.xml.sax.SAXException;

import binarytree.NonRecursiveBinaryTreeTraversal.Node;
import binarytree.NonRecursiveBinaryTreeTraversal.Visitor;

public class NonRecursiveBinaryTreeTraversalTest {
    @Test
    public void testPreorderTrivial() throws Exception {
        Node    rootNode    =
            parseXml("<node value=\"1\">" +
                     "</node>");
        final List<String>  foundNodes          = new ArrayList<String>();
        Visitor             addToListVisitor    = new AddToListVisitor(foundNodes);
        
        NonRecursiveBinaryTreeTraversal.preOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "1");
        
        NonRecursiveBinaryTreeTraversal.inOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "1");
        
        NonRecursiveBinaryTreeTraversal.postOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "1");
    }

    @Test
    public void testPreorderSimple1() throws Exception {
        Node    rootNode    =
            parseXml("<node value=\"1\">" +
                     " <node value=\"2\"/>" +
                     "</node>");
        final List<String>  foundNodes          = new ArrayList<String>();
        Visitor             addToListVisitor    = new AddToListVisitor(foundNodes);

        NonRecursiveBinaryTreeTraversal.preOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "1", "2");
        
        NonRecursiveBinaryTreeTraversal.inOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "2", "1");
        
        NonRecursiveBinaryTreeTraversal.postOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "2", "1");
    }

    @Test
    public void testPreorderSimple2() throws Exception {
        Node    rootNode    =
            parseXml("<node value=\"1\">" +
                     " <node value=\"2\"/>" +
                     " <node value=\"3\"/>" +
                     "</node>");
        final List<String>  foundNodes          = new ArrayList<String>();
        Visitor             addToListVisitor    = new AddToListVisitor(foundNodes);

        NonRecursiveBinaryTreeTraversal.preOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "1", "2", "3");
        
        NonRecursiveBinaryTreeTraversal.inOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "2", "1", "3");
        
        NonRecursiveBinaryTreeTraversal.postOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "2", "3", "1");
    }

    @Test
    public void testPreorderSimple3() throws Exception {
        Node    rootNode    =
            parseXml("<node value=\"1\">" +
                     " <node value=\"2\">" +
                     "   <node value=\"3\"/>" +
                     " </node>" +
                     " <node value=\"4\"/>" +
                     "</node>");
        final List<String>  foundNodes          = new ArrayList<String>();
        Visitor             addToListVisitor    = new AddToListVisitor(foundNodes);

        NonRecursiveBinaryTreeTraversal.preOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "1", "2", "3", "4");
        
        NonRecursiveBinaryTreeTraversal.inOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "3", "2", "1", "4");
        
        NonRecursiveBinaryTreeTraversal.postOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "3", "2", "4", "1");
    }

    @Test
    public void testPreorderSimple4() throws Exception {
        Node    rootNode    =
            parseXml("<node value=\"1\">" +
                     " <node value=\"2\">" +
                     "  <node value=\"4\"/>" +
                     "  <node value=\"5\">" +
                     "   <node value=\"8\"/>" +
                     "  </node>" +
                     " </node>" +
                     " <node value=\"3\">" +
                     "  <node value=\"6\"/>" +
                     "  <node value=\"7\"/>" +
                     " </node>" +
                     "</node>");
        final List<String>  foundNodes          = new ArrayList<String>();
        Visitor             addToListVisitor    = new AddToListVisitor(foundNodes);

        NonRecursiveBinaryTreeTraversal.preOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "1", "2", "4", "5", "8", "3", "6", "7");
        
        NonRecursiveBinaryTreeTraversal.inOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "4", "2", "8", "5", "1", "6", "3", "7");
        
        NonRecursiveBinaryTreeTraversal.postOrder(rootNode, addToListVisitor);
        verifyOrder(foundNodes, "4", "8", "5", "2", "6", "7", "3", "1");
    }

    private void verifyOrder(List<String> foundOrder, String... requiredOrder) {
        if (requiredOrder.length != foundOrder.size())
            fail("Found " +
                    foundOrder.size() + " node" + (foundOrder.size() == 0 ? "" : "s") +
                    ", but needed " +
                    requiredOrder.length + " node" + (requiredOrder.length == 0 ? "" : "s") +
                    ", with required order " + renderOrder(requiredOrder) + " and found order " +
                    renderOrder(foundOrder) + ".");
        else {
            for (int ctr = 0; ctr < foundOrder.size(); ++ ctr) {
                if (!foundOrder.get(ctr).equals(requiredOrder[ctr])) {
                    fail("Order entry " + ctr + " should have been " + requiredOrder[ctr] + ", but it was " +
                            foundOrder.get(ctr) + ", required order " + renderOrder(requiredOrder) +
                            " and found order " + renderOrder(foundOrder) + ".");
                }
            }
        }
        
        // This is a side effect for the convenience of the tests.
        foundOrder.clear();
    }
    
    private String renderOrder(String[] strs) {
        StringBuilder   sb  = new StringBuilder();
        for (int ctr = 0; ctr < strs.length; ++ ctr) {
            sb.append(strs[ctr]);
            if (ctr < strs.length - 1)
                sb.append(", ");
        }
        return sb.toString();
    }

    private String renderOrder(List<String> strs) {
        return renderOrder(strs.toArray(new String[strs.size()]));
    }

    private Node    parseXml(String xml) throws IOException, SAXException {
        Digester    digester    = new Digester();
        
        // The easiest way to do this with Digester is to push a fake node on the top of the stack.  The "left"
        // property of that node will be the resulting tree. Also note that we have to define a Node subclass with a
        // single method to add a child, and it figures out whether to add the child as the left or the right property.

        // digester.push(new AugmentedNode());
        
//        digester.addRule("node", new ObjectCreateRule(AugmentedNode.class));
        digester.addRule("*/node", new ObjectCreateRule(AugmentedNode.class));
        digester.addRule("*/node", new SetPropertiesRule());
        digester.addRule("*/node", new SetNextRule("addChild", AugmentedNode.class.getName()));
        
        return ((Node) digester.parse(new StringReader(xml))).getLeft();
//        return ((Node) digester.parse(new StringReader(xml)));
    }
    
    public static class AddToListVisitor implements Visitor {
        private List<String>    list;
        
        public AddToListVisitor(List<String> list) {
            this.list   = list;
        }
        
        @Override
        public void visit(Node node) {
            list.add(node.getValue());
        }
    }
    
    public static class AugmentedNode extends Node {
        public void addChild(Node node) {
            if (getLeft() == null)
                setLeft(node);
            else
                setRight(node);
        }
    }
}
-----------------------

> 
> -Rahul
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
> For additional commands, e-mail: user-help@commons.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


Re: [digester] Need help with simple digester usage

Posted by Rahul Akolkar <ra...@gmail.com>.
On Thu, Jan 13, 2011 at 12:39 PM, KARR, DAVID (ATTSI) <dk...@att.com> wrote:
>> -----Original Message-----
>> From: Rahul Akolkar
>> Sent: Monday, December 20, 2010 10:18 PM
>> To: Commons Users List
>> Subject: Re: [digester] Need help with simple digester usage
>>
>> On Mon, Dec 20, 2010 at 11:08 PM, KARR, DAVID (ATTSI) <dk...@att.com>
>> wrote:
>> >> -----Original Message-----
>> >> From: KARR, DAVID (ATTSI)
>> >> Sent: Monday, December 20, 2010 7:54 PM
>> >> To: user@commons.apache.org
>> >> Subject: [digester] Need help with simple digester usage
>> >>
>> >> I'm trying to use Digester for a simple application.  I want to
>> define
>> >> the structure of a binary tree in XML, and then construct that node
>> >> tree
>> >> using Digester.
>> >>
>> >> The trivial "Node" class is just this:
>> >> --------------------
>> >>     public static class Node {
>> >>         private Node left;
>> >>         private Node right;
>> >>         private String value;
>> >>
>> >>         public Node getLeft() { return left; }
>> >>         public Node getRight() { return right; }
>> >>         public String getValue() { return value; }
>> >>
>> >>         public void setLeft(Node left) { this.left = left; }
>> >>         public void setRight(Node right) { this.right = right; }
>> >>         public void setValue(String value) { this.value = value; }
>> >>     }
>> >> ------------
>> >>
>> >> The XML is composed of nested "node" elements.  The first "node"
>> child
>> >> gets set as the "left" property of the root, and the second gets set
>> > as
>> >> the "right" property.
>> >>
>> >> For instance:
>> >>
>> >>   <node value="abc">
>> >>     <node value="def"/>
>> >>   </node>
>> >>
>> >> Should result in a root Node with a "left" property referring to the
>> >> second node.
>> >>
>> >> So, going through the Digester documentation, which I haven't looked
>> > at
>> >> in many years, I figured it would be something like this:
>> >>
>> >>         digester.addRule("*/node", new
>> >> ObjectCreateRule(AugmentedNode.class));
>> >>         digester.addRule("*/node", new SetPropertiesRule());
>> >>         digester.addRule("*/node", new SetNextRule("addChild",
>> >> AugmentedNode.class.getName()));
>> >>
>> >> Where "AugmentedNode" extends "Node", adding:
>> >>
>> >>        public void addChild(Node node) {
>> >>             if (getLeft() == null)
>> >>                 setLeft(node);
>> >>             else
>> >>                 setRight(node);
>> >>         }
>> >>
>> >> For those well steeped in Digester lore, I imagine you can
>> immediately
>> >> tell this won't work.  You're right, of course.  This dies with an
>> NPE
>> >> in "MethodUtils.invokeMethod()" (object is null).  I have no clue
>> >> what's
>> >> wrong with this, or what I should be doing instead.
>> >
>> > Oh, ok.  I figured out one thing.  I have to push an AugmentedNode on
>> > the stack before I start parsing, and then I take the result as the
>> > "left" property of that top node.  Is that all I should have figured
>> > out?  Is there a better way to do this in the first place?
>> >
>> <snip/>
>>
>> Add this as the first rule, then the parse method will get you the
>> actual (root) node:
>>
>>   digester.addRule("node", new ObjectCreateRule(AugmentedNode.class));
>>
>> This calls out the root as different from other nodes -- the root
>> doesn't need a SetNextRule (thats the one causing the NPE since it has
>> no parent).
>
> I'm still not quite sure how to transform my existing code so I can use the top node, not the "left" of the top node.
>
> My existing code is this:
>
>        digester.push(new AugmentedNode());
>
>        digester.addRule("*/node", new ObjectCreateRule(AugmentedNode.class));
>        digester.addRule("*/node", new SetPropertiesRule());
>        digester.addRule("*/node", new SetNextRule("addChild", AugmentedNode.class.getName()));
>
>        return ((Node) digester.parse(new StringReader(xml))).getLeft();
>
> I've tried several variations with adding that line you suggest, but I can't get it to work, and I'm not sure exactly what it's trying to accomplish.
>
<snip/>

Try this, per previous email:

    digester.addRule("node", new ObjectCreateRule(AugmentedNode.class));
    // above line is better match for root (not using push)
    digester.addRule("*/node", new ObjectCreateRule(AugmentedNode.class));
    digester.addRule("*/node", new SetPropertiesRule());
    digester.addRule("*/node", new SetNextRule("addChild",
AugmentedNode.class.getName()));
    return ((Node) digester.parse(new StringReader(xml)));
    // above line is without getLeft()

-Rahul

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org