Gregory Kick wrote:
> Ok, here's the problem and how I was looking to solve it:
>
> When unmarshalling generates the whole object tree, the
> unmarshalCallback() takes care of everything and I don't have to worry
> about setting the parent pointers. However, I'd like to be able to
> have valid parent pointers without having to set them separately.
>
> The first part of the solution was to make all generated classes
> implement a Child interface like the following:
>
> public interface Child
> {
> public Object getParent();
> public void setParent(Object parent);
> }
>
> Now, for a property with cardinality of one:
>
> setProperty(Child property)
> {
> this.property = property;
> }
>
> becomes
>
> setProperty(Child property)
> {
> this.property = property;
> this.property.setParent(this);
> }
OK.
> That part's easy enough. The higher cardinality is the tricky part.
> It seems that either a wrapper that implements List<T extends Child>
> and delegates to a backing list that's provided at construction, or an
> extension of of one of the List implementation that keeps track of
> parent pointer would be the way to manage it. In either case, methods
> like add() and remove() would provide the functionality to set and
> unset the parent pointer of the elements in the list.
Right.
> Once I decide on that, I need to figure out how to get it into the xjc
> generated classes. Using the technique you explained earlier, I got
> the new List implementation in there, but there were some problems.
> What I ended up with was (using an extension of ArrayList with a
> constructor like public void ParentTrackingArrayList(Object parent) as
> a trial):
>
> private List<Property> property = new ParentTrackingArrayList<Property>();
>
> Unfortunately, this won't compile because it doesn't use a default
> constructor. Also, since
> coreList.fullName().equals("java.util.ArrayList") is no longer true
> (in UntypedListField), it is attempting eager initialization when
> really, I'd prefer that it is instantiated in the getter just like it
> normally would.
>
> So, it looks like I'd have to override the FieldRendererFactory to get
> the right FieldRenderer to get the right FieldOutline etc. just to get
> the list initialized properly? I don't really like this because it's
> very elaborate and might not be composable with other plugins (because
> of the new FieldRendererFactory). I'm still not very comfortable with
> what should be added in the model vs. what should be added in the
> outline. Am I on the right track with all of this?
Yes, you are doing the right thing, and I see the problem now. This is
indeed bit tricky.
I'm assuming that you can't use the default constructor because the List
implementation needs the 'this' pointer, right?
Maybe one way you can do this is instead of passing in 'this' in the
ParentTrackingArrayList<Property>() constructor, you might be able to
set that in the parent's constructor, like this:
class MyBean {
private List<Property> property = new
ParentTrackingArrayList<Property>();
MyBean() {
property.setOwner(this);
}
}
--
Kohsuke Kawaguchi
Sun Microsystems kohsuke.kawaguchi_at_sun.com