[digester] setter methods named by element attributes values

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[digester] setter methods named by element attributes values

Valerio
Hello,
this is the input  xml:
<website>
  <pageclass>
    <page>
      <metadata name="title">the title</metadata>
      <metadata name="content">the content</metadata>
      <metadata name='someUknownName'>...</metadata>
    </page>
  </pageclass>
</website>

in the DigesterReader.java:

digester.addObjectCreate("website/pageclass/page",Notizia.class);

And here comes comes the problems:
--how to call notizia.setTitle("the title"); ?
--how to call notizia.setContent("the content"); ?
--how to call notizia.setUnknownValue("..."); ?

Notizia does provide all necessary setters.

the values of name attributes can vary greatly, so I need a general way to
invoke setter methods, retriving the name of the setter method to be invoked
by looking at the value of the attribute.


thanks to everyone,
valerio

--
To Iterate is Human, to Recurse, Divine
James O. Coplien, Bell Labs
(how good is to be human indeed)
Reply | Threaded
Open this post in threaded view
|

Re: [digester] setter methods named by element attributes values

Simon Kitching
On Thu, 2006-02-09 at 18:44 +0100, Valerio Schiavoni wrote:

> Hello,
> this is the input  xml:
> <website>
>   <pageclass>
>     <page>
>       <metadata name="title">the title</metadata>
>       <metadata name="content">the content</metadata>
>       <metadata name='someUknownName'>...</metadata>
>     </page>
>   </pageclass>
> </website>
>
> in the DigesterReader.java:
>
> digester.addObjectCreate("website/pageclass/page",Notizia.class);
>
> And here comes comes the problems:
> --how to call notizia.setTitle("the title"); ?
> --how to call notizia.setContent("the content"); ?
> --how to call notizia.setUnknownValue("..."); ?

Unfortunately there is currently no built-in rule in Digester to do
this. It's listed as a to-do item:
  http://wiki.apache.org/jakarta-commons/Digester/TODO

Implementing this in a way that supports wildcard expressions (ie where
nested invocation of the rule instance is possible) is tricky which is
why it hasn't been done yet.

However a simpler implementation of this rule should do in your case,
and *is* quite easy to write. Just create a custom Rule class, and in
the begin method save the value of the "name" attribute on the rule
instance. In the "body" method, use reflection to find the appropriate
method on the object on the top of the stack and invoke it; the
SetNextRule or CallMethodRule classes should be good examples.

Don't be concerned about writing a custom Rule class; it's quite
acceptable and not particularly difficult.

Regards,

Simon




---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [digester] setter methods named by element attributes values

Valerio
Hi,
i followed your suggestion, and I came out with this:

private static class MetadataRule extends Rule {

          public void begin( String ns, String name,
                Attributes att) {
            Map ctx = new HashMap();
            ctx.put("METADATA_NAME", att.getValue("name"));

            getDigester().push( ctx);
          }
public void body( String ns, String name,
                    String text) {
                Map ctx = ( Map) getDigester().pop();
                String metadataName =  (String) ctx.get("METADATA_NAME");
                String methodName = StringUtils.capitalize(metadataName);
                Object onTop = getDigester().peek();
                try {
                    Method metadataSetter =
                        onTop.getClass().getMethod("set"+methodName, new
Class[] {String.class});
                    log.info("Method via reflect: "+ metadataSetter);
                    metadataSetter.invoke(onTop, text);
                } catch(NoSuchMethodException nsme) {
                    nsme.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
             }
        }


which works fine.
thanks,
valerio

On 2/10/06, Simon Kitching <[hidden email]> wrote:

>
> On Thu, 2006-02-09 at 18:44 +0100, Valerio Schiavoni wrote:
> > Hello,
> > this is the input  xml:
> > <website>
> >   <pageclass>
> >     <page>
> >       <metadata name="title">the title</metadata>
> >       <metadata name="content">the content</metadata>
> >       <metadata name='someUknownName'>...</metadata>
> >     </page>
> >   </pageclass>
> > </website>
> >
> > in the DigesterReader.java:
> >
> > digester.addObjectCreate("website/pageclass/page",Notizia.class);
> >
> > And here comes comes the problems:
> > --how to call notizia.setTitle("the title"); ?
> > --how to call notizia.setContent("the content"); ?
> > --how to call notizia.setUnknownValue("..."); ?
>
> Unfortunately there is currently no built-in rule in Digester to do
> this. It's listed as a to-do item:
>   http://wiki.apache.org/jakarta-commons/Digester/TODO
>
> Implementing this in a way that supports wildcard expressions (ie where
> nested invocation of the rule instance is possible) is tricky which is
> why it hasn't been done yet.
>
> However a simpler implementation of this rule should do in your case,
> and *is* quite easy to write. Just create a custom Rule class, and in
> the begin method save the value of the "name" attribute on the rule
> instance. In the "body" method, use reflection to find the appropriate
> method on the object on the top of the stack and invoke it; the
> SetNextRule or CallMethodRule classes should be good examples.
>
> Don't be concerned about writing a custom Rule class; it's quite
> acceptable and not particularly difficult.
>
> Regards,
>
> Simon
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>


--
To Iterate is Human, to Recurse, Divine
James O. Coplien, Bell Labs
(how good is to be human indeed)