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