commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Ken Egervari" <...@upfactor.com>
Subject RE: [Digester] Parent Reference Help
Date Tue, 31 Aug 2004 13:52:39 GMT
Actually, Simon, this is precisely along the track that I need to go.  Thank
you so much for suggesting this as I'm still a bit new to the digester.  

However, I'm still having some problems with this approach, mainly that
rules are being called prematurely and maybe that's why it was placed in
end() in the first place.  

In my case, the setters are still not being called, but this time it is
because SetNextRule or SetTopRule is calling setParent() or addChild()
before the child's properties have been set.  For example, if addChild() is
called, the child's properties might be needed at this point (in my case,
they do) and thus it adds a child with all null references.  While they
might be filled with values afterwards, they need values when addChild() is
called.  Consider this code:

	public void addForm( Form form ) {
		if( form == null ) {
			throw new FormControllerClassNotDefinedException();
		}

		String controller = form.getControllerClassName();

		if( StringUtils.isNullOrEmpty( controller ) ) {
			throw new FormControllerClassNotDefinedException();
		}

		logger.info( "Adding Form [" + controller + "] with " +
			form.getControls().size() + " Controls" );

		form.setContext( this );
		form.implementSuperForm();

		forms.put( controller, form );
	}

This is an example of a typical addChild method.  As you can see, if
form.getControllerClassName() returns empty or null, the addForm method will
fail since it is used as a map key.  Thus, it's imperative that it is
defined before this method is called.  You'll also notice that
form.setContext() and form.implementSuperForm() should not be here - they
should have been in the Form object itself but these were required to get
around the limitation discussed earlier yesterday.

Now, not all is lost.  This pretty much means that I have to use a
combination of SetTopRule and SetNextRule to achieve the desired
functionality and that's what I'm going to play with for the next few hours.
I imagine that I'll get it working the way I want it.

However, I think this problem can be defined to be a more generic problem.
The Digester could enforce an integrity constraint that all objects created
by the Digester are always guaranteed to be initialized when addChild() or
setParent() rules are invoked, which is not a reasonable constraint to put
on the digester since null-valued objects are pretty much meaningless.  If
this is already possible, it should be more explicit.  

Usually people put default values for unspecified attributes or elements to
avoid the null values but that isn't possible for required attributes like
controller class name in my case since they cannot be assumed by default.
Since the digester is inherently aware of XML, it should be aware of
optional and required attributes and put the objects in a state that is
consistent with the semantics of valid XML document.  Now, it doesn't need
to be aware of the DTD, but it can at least try to populate values before
these methods are invoked.  It's not something the user should have to worry
about I don't think.  Fortunately, achieving this functionality is probably
not that hard since your framework is already very flexible and it's
probably a matter of defining higher-level sets of rules that people can use
while the existing software is being used under the hood.

Anyway, thanks for your help and keep up the great work.

Best Regards,
Ken Egervari



-----Original Message-----
From: Simon Kitching [mailto:simon@ecnetwork.co.nz] 
Sent: Monday, August 30, 2004 8:42 PM
To: Jakarta Commons Users List
Subject: Re: [Digester] Parent Reference Help

On Tue, 2004-08-31 at 12:01, Ken Egervari wrote:
> Hi,
> 
>  
> 
> Is there any way to reference a parent object when parsing an XML document
> using the commons-digester component?  For example, let's assume that
there
> is an addObjectCreate() rule that creates a Page object for the <page> tag
> and a SelectOne object for the <selectone> tag.  If I have the following
XML
> (shown below), is there any way the reference of my Page object can be
> passed in the SelectOne object before the SelectOne's setters are called
> using a typical addSetProperties() rule?  I'm having trouble obtaining a
> reference since using addSetTop() is called after the setters are called.

> 
>  
> 
> This is rather inconvenient since some setters (in SelectOne for instance)
> will often need access to the parent object (the Page object in this
> instance).  In other instances, I need to traverse up the graph of objects
> to the root.  Since the parent is not defined, this is impossible.  

Hmm.. I see that the SetTopRule is invoking the target method in the
end() method, ie when it sees the closing tag.

I don't see why it does this. If it were to invoke the target method in
begin(), then that would solve your issue, as:
  digester.addObjectCreate("page/selectone", SelectOne.class);
  digester.addSetTop("page/selectone", "setParentPage");
  digester.addSetProperties("page/selectone");
would then invoke the setParentPage before the property setter methods.

I don't currently see any reason *why* it waits until end() to invoke
the target method.

I suggest taking the source code for SetTopRule, copying it into your
namespace then modifying it so that the work is done in begin() rather
than end(), and seeing if this works for you. If it does, let us know as
I for one think this should be merged into the digester mainline code. 

You would of course use it as:
  NewSetTopRule rule = new NewSetTopRule("setParentPage");
  digester.addRule("page/selectone", rule);

NB: If a change is to be applied to digester CVS, I think it's actually
more likely to involve a modification which adds an extra constructor
param indicating whether invocation at begin or end is desired, and
default to the current behaviour, for backwards compatibility.


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


Mime
View raw message