[picocontainer-dev] Visitor Patch Take 2
"Michael Rimov" <[email protected]> Fri, 20 Jun 2008 22:11:50 -0700
| Newsgroups | gmane.comp.java.picocontainer.devel |
|---|---|
| Organization | Centerline Computers, Inc |
| Message-ID | <005e01c8d35d$52730cb0$f7592610$@com> |
I swear I ran the tests inside eclipse. Missed on JMock expectation though when
ran in maven.
Ignore the previous patch :)
-Mike
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
visitorpatch.diff
(application/octet-stream, 16.4 KB)
Index: container/src/java/org/picocontainer/DefaultPicoContainer.java
===================================================================
--- container/src/java/org/picocontainer/DefaultPicoContainer.java (revision 4677)
+++ container/src/java/org/picocontainer/DefaultPicoContainer.java (working copy)
@@ -811,7 +811,14 @@
}
public void accept(final PicoVisitor visitor) {
- visitor.visitContainer(this);
+
+ //Pico 3 todo, change accept signatures to allow abort at any point in the traversal.
+ boolean shouldContinue = visitor.visitContainer(this);
+ if (!shouldContinue) {
+ return;
+ }
+
+
componentFactory.accept(visitor); // will cascade through behaviors
final List<ComponentAdapter<?>> componentAdapters = new ArrayList<ComponentAdapter<?>>(getComponentAdapters());
for (ComponentAdapter<?> componentAdapter : componentAdapters) {
Index: container/src/java/org/picocontainer/PicoVisitor.java
===================================================================
--- container/src/java/org/picocontainer/PicoVisitor.java (revision 4677)
+++ container/src/java/org/picocontainer/PicoVisitor.java (working copy)
@@ -16,6 +16,20 @@
* @author Jörg Schaible
*/
public interface PicoVisitor {
+
+
+ /**
+ * Constant that indicates that the traversal should continue after the
+ * visit*() method has been called.
+ */
+ boolean CONTINUE_TRAVERSAL = true;
+
+ /**
+ * Constant that indicates that the traversal should abort after the
+ * visit*() method has been called.
+ */
+ boolean ABORT_TRAVERSAL = false;
+
/**
* Entry point for the PicoVisitor traversal. The given node is the first object, that is
* asked for acceptance. Only objects of type {@link PicoContainer}, {@link ComponentAdapter},
@@ -31,16 +45,18 @@
* Visit a {@link PicoContainer} that has to accept the visitor.
*
* @param pico the visited container.
+ * @return CONTINUE_TRAVERSAL if the traversal should continue.
+ * Any visitor callback that returns ABORT_TRAVERSAL indicates
+ * the desire to abort any further traversal.
*/
+ boolean visitContainer(PicoContainer pico);
- void visitContainer(PicoContainer pico);
-
/**
* Visit a {@link ComponentAdapter} that has to accept the visitor.
*
* @param componentAdapter the visited ComponentAdapter.
*/
- void visitComponentAdapter(ComponentAdapter componentAdapter);
+ void visitComponentAdapter(ComponentAdapter<?> componentAdapter);
/**
* Visit a {@link ComponentAdapter} that has to accept the visitor.
Index: container/src/java/org/picocontainer/visitors/AbstractPicoVisitor.java
===================================================================
--- container/src/java/org/picocontainer/visitors/AbstractPicoVisitor.java (revision 4677)
+++ container/src/java/org/picocontainer/visitors/AbstractPicoVisitor.java (working copy)
@@ -30,7 +30,7 @@
public Object traverse(final Object node) {
traversal = true;
Object retval =
- AccessController.doPrivileged(new PrivilegedAction() {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
try {
return node.getClass().getMethod("accept", PicoVisitor.class);
Index: container/src/java/org/picocontainer/visitors/MethodCallingVisitor.java
===================================================================
--- container/src/java/org/picocontainer/visitors/MethodCallingVisitor.java (revision 4677)
+++ container/src/java/org/picocontainer/visitors/MethodCallingVisitor.java (working copy)
@@ -29,7 +29,7 @@
// TODO: we must serialize method with read/writeObject ... and are our parent serializable ???
private transient Method method;
private final Object[] arguments;
- private final Class type;
+ private final Class<?> type;
private final boolean visitInInstantiationOrder;
private final List componentInstances;
private static final long serialVersionUID = 2988472264483878674L;
@@ -43,7 +43,7 @@
* @param arguments the arguments for the method invocation (may be <code>null</code>)
* @throws NullPointerException if <tt>method</tt>, or <tt>ofType</tt> is <code>null</code>
*/
- public MethodCallingVisitor(Method method, Class ofType, Object[] arguments, boolean visitInInstantiationOrder) {
+ public MethodCallingVisitor(Method method, Class<?> ofType, Object[] arguments, boolean visitInInstantiationOrder) {
if (method == null) {
throw new NullPointerException();
}
@@ -82,9 +82,10 @@
return Void.TYPE;
}
- public void visitContainer(PicoContainer pico) {
+ public boolean visitContainer(PicoContainer pico) {
super.visitContainer(pico);
componentInstances.addAll(pico.getComponents(type));
+ return CONTINUE_TRAVERSAL;
}
protected Method getMethod() {
Index: container/src/java/org/picocontainer/visitors/TraversalCheckingVisitor.java
===================================================================
--- container/src/java/org/picocontainer/visitors/TraversalCheckingVisitor.java (revision 4677)
+++ container/src/java/org/picocontainer/visitors/TraversalCheckingVisitor.java (working copy)
@@ -27,30 +27,36 @@
* final List allContainers = new ArrayList();
*
* PicoVisitor visitor = new TraversalCheckingVisitor() {
- * public void visitContainer(PicoContainer pico) {
+ * public boolean visitContainer(PicoContainer pico) {
* super.visitContainer(pico); //Calls checkTraversal for us.
* allContainers.add(pico);
+ * return true;
* }
* }
* </pre>
*
- * @author Micheal Rimov
+ * @author Michael Rimov
*/
public class TraversalCheckingVisitor
extends AbstractPicoVisitor {
- public void visitContainer(PicoContainer pico) {
+ /** {@inheritDoc} **/
+ public boolean visitContainer(PicoContainer pico) {
checkTraversal();
+ return CONTINUE_TRAVERSAL;
}
- public void visitComponentAdapter(ComponentAdapter componentAdapter) {
+ /** {@inheritDoc} **/
+ public void visitComponentAdapter(ComponentAdapter<?> componentAdapter) {
checkTraversal();
}
+ /** {@inheritDoc} **/
public void visitComponentFactory(ComponentFactory componentFactory) {
checkTraversal();
}
+ /** {@inheritDoc} **/
public void visitParameter(Parameter parameter) {
checkTraversal();
}
Index: container/src/java/org/picocontainer/visitors/VerifyingVisitor.java
===================================================================
--- container/src/java/org/picocontainer/visitors/VerifyingVisitor.java (revision 4677)
+++ container/src/java/org/picocontainer/visitors/VerifyingVisitor.java (working copy)
@@ -27,7 +27,7 @@
*/
public class VerifyingVisitor extends TraversalCheckingVisitor {
- private final List nestedVerificationExceptions;
+ private final List<RuntimeException> nestedVerificationExceptions;
private final Set<ComponentAdapter> verifiedComponentAdapters;
private final Set<ComponentFactory> verifiedComponentFactories;
private final PicoVisitor componentAdapterCollector;
@@ -37,7 +37,7 @@
* Construct a VerifyingVisitor.
*/
public VerifyingVisitor() {
- nestedVerificationExceptions = new ArrayList();
+ nestedVerificationExceptions = new ArrayList<RuntimeException>();
verifiedComponentAdapters = new HashSet<ComponentAdapter>();
verifiedComponentFactories = new HashSet<ComponentFactory>();
componentAdapterCollector = new ComponentAdapterCollector();
@@ -55,7 +55,7 @@
try {
super.traverse(node);
if (!nestedVerificationExceptions.isEmpty()) {
- throw new PicoVerificationException(new ArrayList(nestedVerificationExceptions));
+ throw new PicoVerificationException(new ArrayList<RuntimeException>(nestedVerificationExceptions));
}
} finally {
nestedVerificationExceptions.clear();
@@ -64,12 +64,13 @@
return Void.TYPE;
}
- public void visitContainer(PicoContainer pico) {
+ public boolean visitContainer(PicoContainer pico) {
super.visitContainer(pico);
currentPico = pico;
+ return CONTINUE_TRAVERSAL;
}
- public void visitComponentAdapter(ComponentAdapter componentAdapter) {
+ public void visitComponentAdapter(ComponentAdapter<?> componentAdapter) {
super.visitComponentAdapter(componentAdapter);
if (!verifiedComponentAdapters.contains(componentAdapter)) {
try {
@@ -79,6 +80,7 @@
}
componentAdapter.accept(componentAdapterCollector);
}
+
}
public void visitComponentFactory(ComponentFactory componentFactory) {
@@ -92,6 +94,7 @@
}
componentFactory.accept(componentAdapterCollector);
}
+
}
@@ -102,7 +105,8 @@
return null;
}
- public void visitContainer(PicoContainer pico) {
+ public boolean visitContainer(PicoContainer pico) {
+ return CONTINUE_TRAVERSAL;
}
// /CLOVER:ON
@@ -116,6 +120,7 @@
}
public void visitParameter(Parameter parameter) {
+
}
}
}
Index: container/src/test/org/picocontainer/containers/ImmutablePicoContainerTestCase.java
===================================================================
--- container/src/test/org/picocontainer/containers/ImmutablePicoContainerTestCase.java (revision 4677)
+++ container/src/test/org/picocontainer/containers/ImmutablePicoContainerTestCase.java (working copy)
@@ -55,7 +55,7 @@
final PicoVisitor fooVisitor = mockery.mock(PicoVisitor.class);
mockery.checking(new Expectations() {{
- one(fooVisitor).visitContainer(with(same(pico)));
+ one(fooVisitor).visitContainer(with(same(pico))); will(returnValue(true));
one(fooVisitor).visitComponentFactory(with(same(ai)));
one(fooVisitor).visitComponentAdapter(with(same(componentAdapter)));
}});
Index: container/src/test/org/picocontainer/tck/AbstractComponentAdapterTest.java
===================================================================
--- container/src/test/org/picocontainer/tck/AbstractComponentAdapterTest.java (revision 4677)
+++ container/src/test/org/picocontainer/tck/AbstractComponentAdapterTest.java (working copy)
@@ -519,8 +519,9 @@
static class RecordingVisitor extends AbstractPicoVisitor {
private final List visitedElements = new LinkedList();
- public void visitContainer(PicoContainer pico) {
+ public boolean visitContainer(PicoContainer pico) {
visitedElements.add(pico);
+ return CONTINUE_TRAVERSAL;
}
public void visitComponentAdapter(ComponentAdapter componentAdapter) {
Index: container/src/test/org/picocontainer/tck/AbstractPicoContainerTest.java
===================================================================
--- container/src/test/org/picocontainer/tck/AbstractPicoContainerTest.java (revision 4677)
+++ container/src/test/org/picocontainer/tck/AbstractPicoContainerTest.java (working copy)
@@ -66,6 +66,7 @@
import org.picocontainer.testmodel.Washable;
import org.picocontainer.testmodel.WashableTouchable;
import org.picocontainer.visitors.AbstractPicoVisitor;
+import org.picocontainer.visitors.TraversalCheckingVisitor;
import org.picocontainer.visitors.VerifyingVisitor;
/** This test tests (at least it should) all the methods in MutablePicoContainer. */
@@ -719,8 +720,9 @@
this.list = list;
}
- public void visitContainer(PicoContainer pico) {
+ public boolean visitContainer(PicoContainer pico) {
list.add(pico.getClass());
+ return CONTINUE_TRAVERSAL;
}
public void visitComponentAdapter(ComponentAdapter componentAdapter) {
@@ -783,7 +785,42 @@
}
assertEquals(0, visitedList.size());
}
+
+ /**
+ * Verifies that you can halt a container traversal.
+ */
+ @Test
+ public void testAcceptIsAbortable() {
+ final MutablePicoContainer parent = createPicoContainer(null);
+ final MutablePicoContainer child = parent.makeChildContainer();
+ child.addComponent("This is a test");
+
+ TraversalCheckingVisitor visitor = new TraversalCheckingVisitor() {
+ private int containerCount = 0;
+
+ @Override
+ public void visitComponentAdapter(ComponentAdapter<?> componentAdapter) {
+ if (containerCount == 0) {
+ fail("Should have visited a container first");
+ }
+ fail("Should never have visited an adapter.");
+ }
+ @Override
+ public boolean visitContainer(PicoContainer pico) {
+ containerCount++;
+ if (containerCount > 1) {
+ return ABORT_TRAVERSAL;
+ }
+
+ return CONTINUE_TRAVERSAL;
+ }
+
+ };
+
+ visitor.traverse(parent);
+ }
+
protected void addContainers(List expectedList) {
expectedList.add(DefaultPicoContainer.class);
}
Index: container/src/test/org/picocontainer/visitors/TraversalCheckingVisitorTest.java
===================================================================
--- container/src/test/org/picocontainer/visitors/TraversalCheckingVisitorTest.java (revision 4677)
+++ container/src/test/org/picocontainer/visitors/TraversalCheckingVisitorTest.java (working copy)
@@ -120,9 +120,10 @@
final int expectedNumberOfContainers = 2;
PicoVisitor containerCollector = new TraversalCheckingVisitor() {
- public void visitContainer(PicoContainer pico) {
+ public boolean visitContainer(PicoContainer pico) {
super.visitContainer(pico); //Calls checkTraversal for us.
allContainers.add(pico);
+ return CONTINUE_TRAVERSAL;
}
};
Index: gems/src/java/org/picocontainer/gems/jmx/JMXVisitor.java
===================================================================
--- gems/src/java/org/picocontainer/gems/jmx/JMXVisitor.java (revision 4677)
+++ gems/src/java/org/picocontainer/gems/jmx/JMXVisitor.java (working copy)
@@ -86,10 +86,11 @@
* Provides the PicoContainer, that can resolve the components to register as MBean.
* @see org.picocontainer.PicoVisitor#visitContainer(org.picocontainer.PicoContainer)
*/
- public void visitContainer(final PicoContainer pico) {
+ public boolean visitContainer(final PicoContainer pico) {
super.visitContainer(pico);
picoContainer = pico;
visited.clear();
+ return CONTINUE_TRAVERSAL;
}
/**
@@ -112,6 +113,7 @@
}
}
}
+
}
/**
Index: gems/src/java/org/picocontainer/gems/jndi/JNDIContainerVisitor.java
===================================================================
--- gems/src/java/org/picocontainer/gems/jndi/JNDIContainerVisitor.java (revision 4677)
+++ gems/src/java/org/picocontainer/gems/jndi/JNDIContainerVisitor.java (working copy)
@@ -15,7 +15,6 @@
import org.picocontainer.ComponentAdapter;
import org.picocontainer.PicoContainer;
-import org.picocontainer.PicoException;
import org.picocontainer.visitors.TraversalCheckingVisitor;
/**
@@ -40,15 +39,17 @@
if(componentAdapter instanceof JNDIExposed) {
componentAdapter.getComponentInstance(container);
}
+
}
/**
* Provides the PicoContainer, that can resolve the components to register as MBean.
* @see org.picocontainer.PicoVisitor#visitContainer(org.picocontainer.PicoContainer)
*/
- public void visitContainer(final PicoContainer pico) {
+ public boolean visitContainer(final PicoContainer pico) {
super.visitContainer(pico);
container = pico;
+ return CONTINUE_TRAVERSAL;
}
/**
Index: gems/src/test/org/picocontainer/gems/containers/AbstractTracingContainerDecoratorTest.java
===================================================================
--- gems/src/test/org/picocontainer/gems/containers/AbstractTracingContainerDecoratorTest.java (revision 4677)
+++ gems/src/test/org/picocontainer/gems/containers/AbstractTracingContainerDecoratorTest.java (working copy)
@@ -124,7 +124,7 @@
throw new UnsupportedOperationException();
}
- public void visitContainer(PicoContainer pico) {
+ public boolean visitContainer(PicoContainer pico) {
throw new UnsupportedOperationException();
}