    001    /*****************************************************************************
    002     * Copyright (C) PicoContainer Organization. All rights reserved.            *
    003     * ------------------------------------------------------------------------- *
    004     * The software in this package is published under the terms of the BSD      *
    005     * style license a copy of which has been included with this distribution in *
    006     * the LICENSE.txt file.                                                     *
    007     *****************************************************************************/
    008    package org.picocontainer.visitors;
    009
    010    import java.util.ArrayList;
    011    import java.util.HashSet;
    012    import java.util.List;
    013    import java.util.Set;
    014
    015    import org.picocontainer.ComponentAdapter;
    016    import org.picocontainer.ComponentFactory;
    017    import org.picocontainer.Parameter;
    018    import org.picocontainer.PicoContainer;
    019    import org.picocontainer.PicoVerificationException;
    020    import org.picocontainer.PicoVisitor;
    021
    022
    023    /**
    024     * Visitor to verify {@link PicoContainer} instances. The visitor walks down the logical container hierarchy.
    025     *
    026     * @author J&ouml;rg Schaible
    027     */
    028    public class VerifyingVisitor extends TraversalCheckingVisitor {
    029
    030        private final List<RuntimeException> nestedVerificationExceptions;
    031        private final Set<ComponentAdapter> verifiedComponentAdapters;
    032        private final Set<ComponentFactory> verifiedComponentFactories;
    033        private final PicoVisitor componentAdapterCollector;
    034        private PicoContainer currentPico;
    035
    036        /**
    037         * Construct a VerifyingVisitor.
    038         */
    039        public VerifyingVisitor() {
    040            nestedVerificationExceptions = new ArrayList<RuntimeException>();
    041            verifiedComponentAdapters = new HashSet<ComponentAdapter>();
    042            verifiedComponentFactories = new HashSet<ComponentFactory>();
    043            componentAdapterCollector = new ComponentAdapterCollector();
    044        }
    045
    046        /**
    047         * Traverse through all components of the {@link PicoContainer} hierarchy and verify the components.
    048         *
    049         * @throws PicoVerificationException if some components could not be verified.
    050         * @see org.picocontainer.PicoVisitor#traverse(java.lang.Object)
    051         */
    052        public Object traverse(Object node) throws PicoVerificationException {
    053            nestedVerificationExceptions.clear();
    054            verifiedComponentAdapters.clear();
    055            try {
    056                super.traverse(node);
    057                if (!nestedVerificationExceptions.isEmpty()) {
    058                    throw new PicoVerificationException(new ArrayList<RuntimeException>(nestedVerificationExceptions));
    059                }
    060            } finally {
    061                nestedVerificationExceptions.clear();
    062                verifiedComponentAdapters.clear();
    063            }
    064            return Void.TYPE;
    065        }
    066
    067        public boolean visitContainer(PicoContainer pico) {
    068            super.visitContainer(pico);
    069            currentPico = pico;
    070            return CONTINUE_TRAVERSAL;
    071        }
    072
    073        public void visitComponentAdapter(ComponentAdapter<?> componentAdapter) {
    074            super.visitComponentAdapter(componentAdapter);
    075            if (!verifiedComponentAdapters.contains(componentAdapter)) {
    076                try {
    077                    componentAdapter.verify(currentPico);
    078                } catch (RuntimeException e) {
    079                    nestedVerificationExceptions.add(e);
    080                }
    081                componentAdapter.accept(componentAdapterCollector);
    082            }
    083
    084        }
    085
    086        public void visitComponentFactory(ComponentFactory componentFactory) {
    087            super.visitComponentFactory(componentFactory);
    088
    089            if (!verifiedComponentFactories.contains(componentFactory)) {
    090                try {
    091                    componentFactory.verify(currentPico);
    092                } catch (RuntimeException e) {
    093                    nestedVerificationExceptions.add(e);
    094                }
    095                componentFactory.accept(componentAdapterCollector);
    096            }
    097
    098        }
    099
    100
    101
    102        private class ComponentAdapterCollector implements PicoVisitor {
    103            // /CLOVER:OFF
    104            public Object traverse(Object node) {
    105                return null;
    106            }
    107
    108            public boolean visitContainer(PicoContainer pico) {
    109                return CONTINUE_TRAVERSAL;
    110            }
    111
    112            // /CLOVER:ON
    113
    114            public void visitComponentAdapter(ComponentAdapter componentAdapter) {
    115                verifiedComponentAdapters.add(componentAdapter);
    116            }
    117
    118            public void visitComponentFactory(ComponentFactory componentFactory) {
    119                verifiedComponentFactories.add(componentFactory);
    120            }
    121
    122            public void visitParameter(Parameter parameter) {
    123
    124            }
    125        }
    126    }