MarkupContainer.visitChildren traversal when visiting instances of a specific (non-container) class

2011-08-26 Thread Mika Viljanen
Hi,

(I was pretty sure I could find an answer to my question by searching
the list archives and the Wicket Jira, but didn't. But if there's an
answer somewhere already and I just missed it, I apologize and would
be very happy if I was pointed to it.)

Is the visitChildren method of MarkupContainer supposed to take into
account the return value of its IVisitor also if only specific,
non-container classes are to be visited?

The question naturally makes more sense with an example. Consider this
simple piece of code:

MarkupContainer container1 = new WebMarkupContainer(container1);
Label labelA1 = new Label(labelA1, A1);
Label labelA2 = new Label(labelA2, A2);

MarkupContainer container2 = new WebMarkupContainer(container2);
Label labelB1 = new Label(labelB1, B1);
Label labelB2 = new Label(labelB2, B2);

add(container1);
container1.add(labelA1, labelA2, container2);
container2.add(labelB1, labelB2);

container1.visitChildren(Label.class, new IVisitorComponent() {
@Override
public Object component(Component component) {
System.out.println(component.getDefaultModelObject());
return CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER;
}
});

When I wrote the above code I thought the Visitor would only visit
labels A1 and A2, and it would skip B1 and B2, since they are deeper
in the object hierarchy and I use the return value
CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER. But the Visitor actually visits
all four labels anyway. If visitChildren is called without the first
parameter (Label.class), it only visits labels A1 and A2, but also
container2 (which is what I would expect it to do).

The reason for this is pretty obvious if you look at the source code
of visitChildren. The traversal depth check depends on the Visitor's
return value (e.g. CONTINUE_TRAVERSAL or
CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER), and that is set only if no
specific class was defined (i.e. the first parameter wasn't given and
all kinds of components are visited) or the class of the component
matched the given parameter. In this case when visitChildren advances
to container2, the Visitor isn't called (because only Labels are to be
visited) and the return value remains null (the default value). And so
the visiting continues to container2's children, resulting in B1 and
B2 appearing in the results...

Is this how visitChildren was designed to work? Like I said, I
expected it to work differently, but the problem might only be in my
expectations. :)

BR,
Mika

-
To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org
For additional commands, e-mail: users-h...@wicket.apache.org



Re: MarkupContainer.visitChildren traversal when visiting instances of a specific (non-container) class

2011-08-26 Thread Igor Vaynberg
the way it works makes sense to me...

-igor


On Fri, Aug 26, 2011 at 3:24 PM, Mika Viljanen mika.vilja...@iki.fi wrote:
 Hi,

 (I was pretty sure I could find an answer to my question by searching
 the list archives and the Wicket Jira, but didn't. But if there's an
 answer somewhere already and I just missed it, I apologize and would
 be very happy if I was pointed to it.)

 Is the visitChildren method of MarkupContainer supposed to take into
 account the return value of its IVisitor also if only specific,
 non-container classes are to be visited?

 The question naturally makes more sense with an example. Consider this
 simple piece of code:

    MarkupContainer container1 = new WebMarkupContainer(container1);
    Label labelA1 = new Label(labelA1, A1);
    Label labelA2 = new Label(labelA2, A2);

    MarkupContainer container2 = new WebMarkupContainer(container2);
    Label labelB1 = new Label(labelB1, B1);
    Label labelB2 = new Label(labelB2, B2);

    add(container1);
    container1.add(labelA1, labelA2, container2);
    container2.add(labelB1, labelB2);

    container1.visitChildren(Label.class, new IVisitorComponent() {
        @Override
        public Object component(Component component) {
            System.out.println(component.getDefaultModelObject());
            return CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER;
        }
    });

 When I wrote the above code I thought the Visitor would only visit
 labels A1 and A2, and it would skip B1 and B2, since they are deeper
 in the object hierarchy and I use the return value
 CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER. But the Visitor actually visits
 all four labels anyway. If visitChildren is called without the first
 parameter (Label.class), it only visits labels A1 and A2, but also
 container2 (which is what I would expect it to do).

 The reason for this is pretty obvious if you look at the source code
 of visitChildren. The traversal depth check depends on the Visitor's
 return value (e.g. CONTINUE_TRAVERSAL or
 CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER), and that is set only if no
 specific class was defined (i.e. the first parameter wasn't given and
 all kinds of components are visited) or the class of the component
 matched the given parameter. In this case when visitChildren advances
 to container2, the Visitor isn't called (because only Labels are to be
 visited) and the return value remains null (the default value). And so
 the visiting continues to container2's children, resulting in B1 and
 B2 appearing in the results...

 Is this how visitChildren was designed to work? Like I said, I
 expected it to work differently, but the problem might only be in my
 expectations. :)

 BR,
 Mika

 -
 To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org
 For additional commands, e-mail: users-h...@wicket.apache.org



-
To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org
For additional commands, e-mail: users-h...@wicket.apache.org