You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@commons.apache.org by Chris Cheshire <ch...@gmail.com> on 2006/09/13 23:05:28 UTC

Re: [digester] WAS: FactoryCreateRule help NOW: Custom Rule help

Thanks Simon, I figured this would be the case, but I wanted to make sure.

The solution I have come up with is to make a custom rule that parses
that element into a helper class, then uses the VariableFactory to
instantiate the right Variable subclass.

Just to make sure I have this right in begin() I am pushing an
instance of the helper class (DefaultVariable) on the digester stack.

In end() I am popping it, creating a new subclass and adding it to the
list (which was one above on the stack). At the end of end() should I
be pushing this new Variable back on the stack after I add it to the
list (top of the stack), or is it correct to just consume it?

Thanks

Chris

On 9/13/06, Simon Kitching <sk...@apache.org> wrote:
> Hi Chris,
>
> On Tue, 2006-09-12 at 18:01 -0700, Chris Cheshire wrote:
> > I have to process an XML file that contains (in part) the following structure
> > <variables>
> >   <Variable>
> >     <ID>...</ID>
> >     <Name>...</Name>
> >     <Instance>...</Instance>
> >     <Value>...</Value>
> >   </Variable>
> > </variables>
> >
> > I have a predefined list of variables based upon their ID, an abstract
> > Variable class, and then concrete subclasses of these for each valid
> > ID.
> >
> > Variable contains a static method Variable getInstance(int ID) that
> > creates a new variable subclass based upon the ID (the id-subclass
> > mapping is based upon a properties file).
> >
> > The FactoryCreateRule allows for creation of classes based via a
> > factory providing the identifiying parameter is an XML attribute. In
> > this case it is not. It is a sub-element, I have no control over that.
> >
> > How can I use the FactoryCreateRule to call getInstance(int ID) in my
> > Variable class when I need to extract the ID from a nested element not
> > an attribute?
>
> This is quite a common question, and really deserves an FAQ entry.
>
> In short, you can't. Digester is a SAX-based system, and with SAX there
> is no "look ahead" option.
>
> One possible solution is to use an XSLT stylesheet to pre-process your
> xml to move all the data needed to determine the object type into
> attributes of the element that triggers the object creation. Then the
> FactoryCreateRule can be used as normal.
>
> It might be possible to create a variant of the FactoryCreateRule that
> creates a hashmap or similar when the start element is found, store
> child objects in that hashmap until the end element is found, then looks
> into the hashmap to get the data to determine the type of object to
> instantiate and copy the hashmap contents into properties of the created
> object. It all seems rather clumsy/fragile though. If you do wish to try
> this, and get it to work then please put that info in the digester wiki
> as you're not the first person to ask about this.
>
> Regards,
>
> Simon
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-user-help@jakarta.apache.org
>
>

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


Re: [digester] WAS: FactoryCreateRule help NOW: Custom Rule help

Posted by Simon Kitching <sk...@apache.org>.
Hi Chris,

After a rule's end method is finished, the digester stack should be
exactly the same depth as before the rule's begin method ran. In other
words, a rule is responsible for cleaning up after itself.

So in your case, your end method need to call the setter on the parent
passing the newly created object (as you do), but this new object should
*not* be pushed onto the stack. Doing so would "unbalance" the stack, ie
stack depth before begin would not match stack depth after end.

Never pushing the newly created instance onto the stack of course makes
it impossible for any other rule to operate on this object, but that's
ok in your case as the only thing you need to do is add the object to
the parent List which you do explicitly from the custom rule.

Regards,

Simon

On Wed, 2006-09-13 at 14:05 -0700, Chris Cheshire wrote:
> Thanks Simon, I figured this would be the case, but I wanted to make sure.
> 
> The solution I have come up with is to make a custom rule that parses
> that element into a helper class, then uses the VariableFactory to
> instantiate the right Variable subclass.
> 
> Just to make sure I have this right in begin() I am pushing an
> instance of the helper class (DefaultVariable) on the digester stack.
> 
> In end() I am popping it, creating a new subclass and adding it to the
> list (which was one above on the stack). At the end of end() should I
> be pushing this new Variable back on the stack after I add it to the
> list (top of the stack), or is it correct to just consume it?
> 
> Thanks
> 
> Chris
> 
> On 9/13/06, Simon Kitching <sk...@apache.org> wrote:
> > Hi Chris,
> >
> > On Tue, 2006-09-12 at 18:01 -0700, Chris Cheshire wrote:
> > > I have to process an XML file that contains (in part) the following structure
> > > <variables>
> > >   <Variable>
> > >     <ID>...</ID>
> > >     <Name>...</Name>
> > >     <Instance>...</Instance>
> > >     <Value>...</Value>
> > >   </Variable>
> > > </variables>
> > >
> > > I have a predefined list of variables based upon their ID, an abstract
> > > Variable class, and then concrete subclasses of these for each valid
> > > ID.
> > >
> > > Variable contains a static method Variable getInstance(int ID) that
> > > creates a new variable subclass based upon the ID (the id-subclass
> > > mapping is based upon a properties file).
> > >
> > > The FactoryCreateRule allows for creation of classes based via a
> > > factory providing the identifiying parameter is an XML attribute. In
> > > this case it is not. It is a sub-element, I have no control over that.
> > >
> > > How can I use the FactoryCreateRule to call getInstance(int ID) in my
> > > Variable class when I need to extract the ID from a nested element not
> > > an attribute?
> >
> > This is quite a common question, and really deserves an FAQ entry.
> >
> > In short, you can't. Digester is a SAX-based system, and with SAX there
> > is no "look ahead" option.
> >
> > One possible solution is to use an XSLT stylesheet to pre-process your
> > xml to move all the data needed to determine the object type into
> > attributes of the element that triggers the object creation. Then the
> > FactoryCreateRule can be used as normal.
> >
> > It might be possible to create a variant of the FactoryCreateRule that
> > creates a hashmap or similar when the start element is found, store
> > child objects in that hashmap until the end element is found, then looks
> > into the hashmap to get the data to determine the type of object to
> > instantiate and copy the hashmap contents into properties of the created
> > object. It all seems rather clumsy/fragile though. If you do wish to try
> > this, and get it to work then please put that info in the digester wiki
> > as you're not the first person to ask about this.
> >
> > Regards,
> >
> > Simon
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: commons-user-help@jakarta.apache.org
> >
> >
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-user-help@jakarta.apache.org
> 


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