commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Valerio Schiavoni" <valerio.schiav...@gmail.com>
Subject Re: [Digester] parameter value from a parent node attribute
Date Wed, 26 Apr 2006 09:46:55 GMT
Hello Simon,
thanks for the explanation you provided. I thought about writing a custom
rule, and it actually worked for all but one test case, and this is why i'm
replying.

On 4/22/06, Simon Kitching <skitching@apache.org> wrote:
>
> > <root>
> > <element id="A">
> >    <subelement id="B"/>
> > </element>
> > </root>


in the following code, root == committer; and the path
root/element/subelement
is committer/element/children/subelement (but same semantics);

digester.addObjectCreate("committer", ConfigurationDescriptor.class);
digester.addRule("committer/element",new ElementRule());
where this first custom rule looks like:

private class ElementRule extends Rule {
        public void begin( String ns, String name,
                Attributes att) {
            Map<String,String> ctx = new HashMap<String,String>();
            String value = att.getValue("id");
            ConfigurationDescriptor hd =
(ConfigurationDescriptor) getDigester().peek();
            hd.addElementType(value);
            ctx.put("ROOT_ID", value);
            getDigester().push( ctx);
          }
    }

digester.addRule("committer/element/children/element", new
ChildElementRule());
private class ChildElementRule extends Rule{

        public void begin( String ns, String name, Attributes att) {

            Map<String,String> ctx = ( Map) getDigester().pop();
            String parentId =  ctx.get("ROOT_ID");
            String childElementId = att.getValue("refid");

            ConfigurationDescriptor hd = (ConfigurationDescriptor)
getDigester().peek();
            hd.addChildForType(parentId, childElementId);

          }
    }

and everything goes fine until i run a test with the following input:
rootCategory_twoChildrenType.xml :

<committer>
<element id="category">
<children>
<element refid="client" maxocc="-1" />
<element refid="folder" maxocc="-1" />
</children>
</element>
<element id="client"/>
</committer>

and I run a test like:
public void testExactlyTwoChildrenElement() throws Throwable {
        ConfigurationDescriptor hd = hr.read(rootCategory_twoChildrenType);
        assertEquals("Assert on childrens by ID"+ROOT_TYPE,
                2, hd.typeChildrenForType(ROOT_TYPE).size());
    }

and i get a ClassCastException in the ChildElementRule when I do something
like:
Map<String,String> ctx = ( Map) getDigester().pop();
where it founds a ConfigurationDescriptor class instead.

the code of the digester is here: http://veleno.pastebin.com/682606
and i get a stacktrace: http://veleno.pastebin.com/682612

probably somewhere I should do a pop() but i don't understand where :(



>
> > whenever I match path element/subelement, i need to invoke a
> 2-parameters
> > method  defined on the object on the stack
> > ,call it twoParamMethod(String idElement,String idSubElement).
> >
> > i was able to code up to this code:
> >
> > digester.addCallMethod("root/element/subelement", "twoParamMethod", 2);
> > //HOW DO I GET THE VALUE FOR THE FIRST PARAMETER ?
>
> You can get the "previous object on the stack" via:
>   // See addCallParam(String pattern, int paramIndex, int stackIndex)
>   digester.addCallParam("root/element/subelement", 0, 1);
>
> Assuming you have an ObjectCreateRule for <element> and <subelement>
> this will pass the <element> as the 0th parameter.
>
> However the CallMethodRule is probably not what you want; by default it
> calls the object that is on the top of the stack. So in your case,
> you'll end up invoking methods on the object created by the
> ObjectCreateRule for <subelement>. Maybe you want SetTopRule? Or maybe
> you want one of the CallMethodRule constructors that take a targetOffset
> parameter (NB: these don't have factory methods on Digester because they
> are only rarely needed).
>
> >  digester.addCallParam("root/element/subelement", 1, "id"); //value for
> the
> > second parameter
> >
> > i need to this to fill in a map (stored in the root object) key="element
> > id", values="list of id-s of subelements";
>
> Before doing any further implementation, though, I suggest you think
> very carefully about your object model. When people need to start doing
> such tricky things with stack offsets it usually means that the java
> object model they are building doesn't correspond properly to the xml.
> Often the solution is to fix the object model rather than write tricky
> digester rules.
>
> Regards,
>
> Simon
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-user-help@jakarta.apache.org
>
>


--
http://valerioschiavoni.blogspot.com
http://jroller.com/page/vschiavoni

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message