You are right. It feels like misusing generics. I think generics were not meant to be used at runtime (type erasure is not there for fun :) ).

-Matej

Eelco Hillenius wrote:
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




-------------------------------------------------------
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

Reply via email to