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.defaults;
009    
010    import org.picocontainer.ComponentAdapter;
011    import org.picocontainer.Parameter;
012    import org.picocontainer.PicoContainer;
013    import org.picocontainer.PicoVerificationException;
014    import org.picocontainer.PicoVisitor;
015    
016    import java.util.ArrayList;
017    import java.util.HashSet;
018    import java.util.List;
019    import java.util.Set;
020    
021    
022    /**
023     * Visitor to verify {@link PicoContainer} instances. The visitor walks down the logical container hierarchy.
024     * 
025     * @author Jörg Schaible
026     * @since 1.1
027     */
028    public class VerifyingVisitor extends TraversalCheckingVisitor {
029    
030        private final List nestedVerificationExceptions;
031        private final Set verifiedComponentAdapters;
032        private final PicoVisitor componentAdapterCollector;
033        private PicoContainer currentPico;
034    
035        /**
036         * Construct a VerifyingVisitor.
037         */
038        public VerifyingVisitor() {
039            nestedVerificationExceptions = new ArrayList();
040            verifiedComponentAdapters = new HashSet();
041            componentAdapterCollector = new ComponentAdapterCollector();
042        }
043    
044        /**
045         * Traverse through all components of the {@link PicoContainer} hierarchy and verify the components.
046         * 
047         * @throws PicoVerificationException if some components could not be verified.
048         * @see org.picocontainer.PicoVisitor#traverse(java.lang.Object)
049         */
050        public Object traverse(Object node) throws PicoVerificationException {
051            nestedVerificationExceptions.clear();
052            verifiedComponentAdapters.clear();
053            try {
054                super.traverse(node);
055                if (!nestedVerificationExceptions.isEmpty()) {
056                    throw new PicoVerificationException(new ArrayList(nestedVerificationExceptions));
057                }
058            } finally {
059                nestedVerificationExceptions.clear();
060                verifiedComponentAdapters.clear();
061            }
062            return Void.TYPE;
063        }
064    
065        public void visitContainer(PicoContainer pico) {
066            super.visitContainer(pico);
067            currentPico = pico;
068        }
069    
070        public void visitComponentAdapter(ComponentAdapter componentAdapter) {
071            super.visitComponentAdapter(componentAdapter);
072            if (!verifiedComponentAdapters.contains(componentAdapter)) {
073                try {
074                    componentAdapter.verify(currentPico);
075                } catch (RuntimeException e) {
076                    nestedVerificationExceptions.add(e);
077                }
078                componentAdapter.accept(componentAdapterCollector);
079            }
080        }
081    
082        private class ComponentAdapterCollector implements PicoVisitor {
083            // /CLOVER:OFF
084            public Object traverse(Object node) {
085                return null;
086            }
087    
088            public void visitContainer(PicoContainer pico) {
089            }
090    
091            // /CLOVER:ON
092    
093            public void visitComponentAdapter(ComponentAdapter componentAdapter) {
094                verifiedComponentAdapters.add(componentAdapter);
095            }
096    
097            public void visitParameter(Parameter parameter) {
098            }
099        }
100    }