Hi, I've got a start for a generified IVisitor implementation. Basically, it would be used like this:
// Visit all Forms contained in the page visitChildren(new Component.IVisitor<Form>() { // For each FormComponent found on the Page (not Form) public Object component(final Form form) { form.loadPersistentFormComponentValues(); return CONTINUE_TRAVERSAL; } }); However, I'm kind of stuck at the dirty details of introspecting parameterized types. It's probably doable, but pretty messy and inefficient at times (to catch all cases, you'd have to implement a recursive alg that searches for the proper type, with a lot of 'ifs'). I'm not sure it's worth it, also as it seems a bit like misusing generics. Anyway, if anyone likes to take a look: here's a patch. A couple of unit test fail, and that's where the real fun begins :) Eelco Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/Component.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/Component.java (revision 5923) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/Component.java (working copy) @@ -271,11 +271,9 @@ /** * Generic component visitor interface for component traversals. - * - * @param <T> - * The type of the component where a visitor walks over. + * @param <E> The type of the component where a visitor walks over. */ - public static interface IVisitor + public static interface IVisitor<E> { /** * Value to return to continue a traversal. @@ -303,7 +301,7 @@ * should stop. If no return value is useful, the generic * non-null value STOP_TRAVERSAL can be used. */ - public Object component(Component component); + public Object component(E component); } /** @@ -1717,12 +1715,12 @@ // to // collect their messages before components like ListViews // remove any child components - container.visitChildren(IFeedback.class, new IVisitor() + container.visitChildren(new IVisitor<IFeedback>() { - public Object component(Component component) + public Object component(IFeedback feedback) { - ((IFeedback)component).updateFeedback(); - component.internalAttach(); + feedback.updateFeedback(); + ((Component)feedback).internalAttach(); return IVisitor.CONTINUE_TRAVERSAL; } }); Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/MarkupContainer.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/MarkupContainer.java (revision 5923) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/MarkupContainer.java (working copy) @@ -18,6 +18,8 @@ */ package wicket; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -644,9 +646,9 @@ super.setModel(model); if (previous instanceof ICompoundModel) { - visitChildren(new IVisitor() + visitChildren(new IVisitor<Component<?>>() { - public Object component(Component component) + public Object component(Component<?> component) { IModel compModel = component.getModel(); if (compModel == previous) @@ -725,11 +727,9 @@ } /** - * Traverses all child components of the given class in this container, + * Traverses all child components of the visitor's type in this container, * calling the visitor's visit method at each one. * - * @param clazz - * The class of child to visit, or null to visit all children * @param visitor * The visitor to call back to * @return The return value from a visitor which halted the traversal, or @@ -735,7 +735,8 @@ * @return The return value from a visitor which halted the traversal, or * null if the entire traversal occurred */ - public final Object visitChildren(final Class clazz, final IVisitor visitor) + @SuppressWarnings("unchecked") + public final Object visitChildren(final IVisitor visitor) { if (visitor == null) { @@ -742,6 +743,25 @@ throw new IllegalArgumentException("argument visitor may not be null"); } + final Class c = visitor.getClass(); + + final Type type = c.getGenericInterfaces()[0]; + final Class clazz; + if (type instanceof ParameterizedType) + { + Type typeArg = ((ParameterizedType)type).getActualTypeArguments()[0]; + if (!(typeArg instanceof Class)) + { + clazz = (Class)((ParameterizedType)typeArg).getRawType(); + } + else + { + clazz = (Class)typeArg; + } + } else { + clazz = Component.class; + } + // Iterate through children of this container for (int i = 0; i < children_size(); i++) { @@ -750,7 +770,7 @@ Object value = null; // Is the child of the correct class (or was no class specified)? - if (clazz == null || clazz.isInstance(child)) + if (clazz.isInstance(child)) { // Call visitor value = visitor.component(child); @@ -768,7 +788,7 @@ && (value != IVisitor.CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER)) { // visit the children in the container - value = ((MarkupContainer<?>)child).visitChildren(clazz, visitor); + value = ((MarkupContainer<?>)child).visitChildren(visitor); // If visitor returns a non-null value, it halts the traversal if ((value != IVisitor.CONTINUE_TRAVERSAL) @@ -783,20 +803,6 @@ } /** - * Traverses all child components in this container, calling the visitor's - * visit method at each one. - * - * @param visitor - * The visitor to call back to - * @return The return value from a visitor which halted the traversal, or - * null if the entire traversal occurred - */ - public final Object visitChildren(final IVisitor visitor) - { - return visitChildren(null, visitor); - } - - /** * Get the markup stream for this component. * * @return The markup stream for this component, or if it doesn't have one, @@ -1295,7 +1301,7 @@ // detach children models if (component instanceof MarkupContainer) { - ((MarkupContainer<?>)component).visitChildren(new IVisitor() + ((MarkupContainer<?>)component).visitChildren(new IVisitor<Component<?>>() { public Object component(Component component) { Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/Page.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/Page.java (revision 5923) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/Page.java (working copy) @@ -1,6 +1,6 @@ /* - * $Id$ $Revision$ $Date: - * 2006-05-26 00:32:40 +0200 (vr, 26 mei 2006) $ + * $Id$ + * $Revision$ $Date$ * * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); you may not @@ -326,7 +326,7 @@ public void detachModels() { // visit all this page's children to detach the models - visitChildren(new IVisitor() + visitChildren(new IVisitor<Component>() { public Object component(Component component) { @@ -381,12 +381,12 @@ // First, give priority to IFeedback instances, as they have to // collect their messages before components like ListViews // remove any child components - visitChildren(IFeedback.class, new IVisitor() + visitChildren(new IVisitor<IFeedback>() { - public Object component(Component component) + public Object component(IFeedback feedback) { - ((IFeedback)component).updateFeedback(); - component.internalAttach(); + feedback.updateFeedback(); + ((Component)feedback).internalAttach(); return IVisitor.CONTINUE_TRAVERSAL; } }); @@ -404,7 +404,7 @@ // or negative as a temporary boolean in the components, and when a // authorization exception is thrown it will block the rendering of this // page - visitChildren(new IVisitor() + visitChildren(new IVisitor<Component>() { public Object component(final Component component) { @@ -643,7 +643,7 @@ { final StringBuffer buffer = new StringBuffer(); buffer.append("Page " + getId() + " (version " + getCurrentVersionNumber() + ")"); - visitChildren(new IVisitor() + visitChildren(new IVisitor<Component>() { public Object component(Component component) { @@ -705,16 +705,16 @@ } // Visit all children which are an instance of formClass - visitChildren(formClass, new IVisitor() + visitChildren(new IVisitor<Form>() { - public Object component(final Component component) + public Object component(final Form form) { // They must be of type Form as well - if (component instanceof Form) + if (form.getClass().equals(formClass)) { // Delete persistet FormComponent data and disable // persistence - ((Form)component).removePersistentFormComponentValues(disablePersistence); + form.removePersistentFormComponentValues(disablePersistence); } return CONTINUE_TRAVERSAL; } @@ -841,7 +841,7 @@ @Override protected final void internalOnModelChanged() { - visitChildren(new Component.IVisitor() + visitChildren(new Component.IVisitor<Component>() { public Object component(final Component component) { @@ -991,7 +991,7 @@ { if (stateless == null) { - Object returnValue = visitChildren(Component.class, new IVisitor() + Object returnValue = visitChildren(new IVisitor<Component>() { public Object component(Component component) { @@ -1026,12 +1026,12 @@ final void setFormComponentValuesFromCookies() { // Visit all Forms contained in the page - visitChildren(Form.class, new Component.IVisitor() + visitChildren(new Component.IVisitor<Form>() { // For each FormComponent found on the Page (not Form) - public Object component(final Component component) + public Object component(final Form form) { - ((Form)component).loadPersistentFormComponentValues(); + form.loadPersistentFormComponentValues(); return CONTINUE_TRAVERSAL; } }); @@ -1103,7 +1103,7 @@ final Count unrenderedComponents = new Count(); final List<Component> unrenderedAutoComponents = new ArrayList<Component>(); final StringBuffer buffer = new StringBuffer(); - renderedContainer.visitChildren(new IVisitor() + renderedContainer.visitChildren(new IVisitor<Component>() { public Object component(final Component component) { Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/ajax/form/AjaxFormValidatingBehavior.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/ajax/form/AjaxFormValidatingBehavior.java (revision 5922) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/ajax/form/AjaxFormValidatingBehavior.java (working copy) @@ -56,11 +56,11 @@ @Override protected void onSubmit(final AjaxRequestTarget target) { - getComponent().getPage().visitChildren(IFeedback.class, new IVisitor() + getComponent().getPage().visitChildren(new IVisitor<IFeedback>() { - public Object component(Component component) + public Object component(IFeedback feedback) { - target.addComponent(component); + target.addComponent((Component)feedback); return IVisitor.CONTINUE_TRAVERSAL; } @@ -88,9 +88,9 @@ public static void addToAllFormComponents(final Form form, final String event, final Duration throttleDelay) { - form.visitChildren(FormComponent.class, new IVisitor() + form.visitChildren(new IVisitor<FormComponent>() { - public Object component(Component component) + public Object component(FormComponent component) { AjaxFormValidatingBehavior behavior = new AjaxFormValidatingBehavior(form, event); if (throttleDelay != null) Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/markup/html/debug/PageView.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/markup/html/debug/PageView.java (revision 5923) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/markup/html/debug/PageView.java (working copy) @@ -123,7 +123,7 @@ { final List<ComponentData> data = new ArrayList<ComponentData>(); - page.visitChildren(new IVisitor() + page.visitChildren(new IVisitor<Component>() { public Object component(final Component component) { Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/markup/html/form/Form.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/markup/html/form/Form.java (revision 5918) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/markup/html/form/Form.java (working copy) @@ -479,11 +479,11 @@ */ public final void visitFormComponents(final FormComponent.IVisitor visitor) { - visitChildren(FormComponent.class, new IVisitor() + visitChildren(new IVisitor<FormComponent>() { - public Object component(final Component component) + public Object component(final FormComponent component) { - visitor.formComponent((FormComponent)component); + visitor.formComponent(component); return CONTINUE_TRAVERSAL; } }); @@ -607,13 +607,10 @@ */ protected final Button findSubmittingButton() { - Button button = (Button)visitChildren(Button.class, new IVisitor() + Button button = (Button)visitChildren(new IVisitor<Button>() { - public Object component(final Component component) + public Object component(final Button button) { - // Get button - final Button button = (Button)component; - // Check for button-name or button-name.x request string if (getRequest().getParameter(button.getInputName()) != null || getRequest().getParameter(button.getInputName() + ".x") != null) @@ -630,13 +627,10 @@ if (button == null) { - button = (Button)getPage().visitChildren(SubmitLink.class, new IVisitor() + button = (Button)getPage().visitChildren(new IVisitor<SubmitLink>() { - public Object component(final Component component) + public Object component(final SubmitLink button) { - // Get button - final SubmitLink button = (SubmitLink)component; - // Check for button-name or button-name.x request string if (button.getForm() == Form.this && (getRequest().getParameter(button.getInputName()) != null || getRequest() @@ -1126,7 +1120,7 @@ */ private boolean anyFormComponentError() { - final Object value = visitChildren(new IVisitor() + final Object value = visitChildren(new IVisitor<Component>() { public Object component(final Component component) { Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/markup/html/internal/HtmlHeaderContainer.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/markup/html/internal/HtmlHeaderContainer.java (revision 5918) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/markup/html/internal/HtmlHeaderContainer.java (working copy) @@ -211,7 +211,7 @@ { // Make sure all Components interested in contributing to the header // and there attached behaviors are asked. - page.visitChildren(new IVisitor() + page.visitChildren(new IVisitor<Component>() { /** * @see wicket.Component.IVisitor#component(wicket.Component) Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/protocol/http/ClientPageSavingSessionStore.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/protocol/http/ClientPageSavingSessionStore.java (revision 5922) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/protocol/http/ClientPageSavingSessionStore.java (working copy) @@ -295,12 +295,11 @@ final AppendingStringBuffer forms = new AppendingStringBuffer(64); forms.append(JavascriptUtils.SCRIPT_OPEN_TAG); - page.visitChildren(Form.class, new IVisitor() + page.visitChildren(new IVisitor<Form>() { - public Object component(Component component) + public Object component(Form form) { forms.append("document.getElementById('"); - Form form = (Form)component; forms.append(form.getHiddenFieldId(Form.HIDDEN_FIELD_WICKET_STATE)); forms.append("').value=wicketState;\n"); return null; Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/protocol/http/MockHttpServletRequest.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/protocol/http/MockHttpServletRequest.java (revision 5918) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/protocol/http/MockHttpServletRequest.java (working copy) @@ -1056,7 +1056,7 @@ setRequestToComponent(form); final Map<String, Component> valuesApplied = new HashMap<String, Component>(); - form.visitChildren(new Component.IVisitor() + form.visitChildren(new Component.IVisitor<Component>() { public Object component(final Component component) { Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/util/tester/FormTester.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/util/tester/FormTester.java (revision 5923) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/util/tester/FormTester.java (working copy) @@ -58,9 +58,9 @@ protected abstract class ChoiceSelector { /** - * ??? + * @param <E> Visitor type */ - private final class SearchOptionByIndexVisitor implements IVisitor + private final class SearchOptionByIndexVisitor<E> implements IVisitor<E> { int count = 0; @@ -68,7 +68,6 @@ private SearchOptionByIndexVisitor(int index) { - super(); this.index = index; } @@ -75,7 +74,7 @@ /** * @see wicket.Component.IVisitor#component(wicket.Component) */ - public Object component(Component component) + public Object component(E component) { if (count == index) { @@ -117,8 +116,8 @@ { if (formComponent instanceof RadioGroup) { - Radio foundRadio = (Radio)formComponent.visitChildren(Radio.class, - new SearchOptionByIndexVisitor(index)); + Radio foundRadio = (Radio)formComponent.visitChildren( + new SearchOptionByIndexVisitor<Radio>(index)); if (foundRadio == null) { Assert.fail("RadioGroup " + formComponent.getPath() + " does not has index:" @@ -131,8 +130,8 @@ } else if (formComponent instanceof CheckGroup) { - Check foundCheck = (Check)formComponent.visitChildren(Check.class, - new SearchOptionByIndexVisitor(index)); + Check foundCheck = (Check)formComponent.visitChildren( + new SearchOptionByIndexVisitor<Check>(index)); if (foundCheck == null) { Assert.fail("CheckGroup " + formComponent.getPath() + " does not has index:" Index: /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/util/tester/WicketTesterHelper.java =================================================================== --- /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/util/tester/WicketTesterHelper.java (revision 5923) +++ /Users/eelcohillenius/Documents/workspace/wicket/src/java/wicket/util/tester/WicketTesterHelper.java (working copy) @@ -65,7 +65,7 @@ { final List<ComponentData> data = new ArrayList<ComponentData>(); - page.visitChildren(new IVisitor() + page.visitChildren(new IVisitor<Component>() { public Object component(final Component component) { @@ -106,8 +106,7 @@ * @param expects * @param actuals */ - public static void assertEquals(final Collection<?> expects, - final Collection<?> actuals) + public static void assertEquals(final Collection<?> expects, final Collection<?> actuals) { if (!expects.containsAll(actuals) || !actuals.containsAll(expects)) { ------------------------------------------------------- All the advantages of Linux Managed Hosting--Without the Cost and Risk! Fully trained technicians. The highest number of Red Hat certifications in the hosting industry. Fanatical Support. Click to learn more http://sel.as-us.falkag.net/sel?cmd=lnk&kid=107521&bid=248729&dat=121642 _______________________________________________ Wicket-develop mailing list Wicket-develop@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/wicket-develop