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     * Original code by                                                          *
009     *****************************************************************************/
010    package org.picocontainer.gems.monitors;
011    
012    import java.lang.reflect.Constructor;
013    
014    import org.picocontainer.monitors.AbstractComponentMonitor;
015    import org.picocontainer.gems.monitors.prefuse.ComponentDependencyListener;
016    import org.picocontainer.ComponentAdapter;
017    import org.picocontainer.PicoContainer;
018    
019    /**
020     * Understands how to capture component dependency information from
021     * picocontainer.
022     * 
023     * @author Peter Barry
024     * @author Kent R. Spillner
025     */
026    @SuppressWarnings("serial")
027    public final class ComponentDependencyMonitor extends AbstractComponentMonitor {
028    
029            
030            
031            private final ComponentDependencyListener listener;
032    
033        public ComponentDependencyMonitor(final ComponentDependencyListener listener) {
034            this.listener = listener;
035        }
036    
037        @Override
038            public <T> void instantiated(final PicoContainer container, final ComponentAdapter<T> componentAdapter,
039                                 final Constructor<T> constructor,
040                                 final Object instantiated,
041                                 final Object[] injected,
042                                 final long duration) {
043            Class<?> componentType = instantiated.getClass();
044            int count = injected.length;
045    
046            if (count == 0) {
047                listener.addDependency(new Dependency(componentType, null));
048            }
049    
050            for (int i = 0; i < count; i++) {
051                Object dependent = injected[i];
052                Dependency dependency = new Dependency(componentType, dependent.getClass());
053                listener.addDependency(dependency);
054            }
055        }
056    
057        /**
058         * Understands which other classes are required to instantiate a component.
059         * 
060         * @author Peter Barry
061         * @author Kent R. Spillner
062         */
063        public static final class Dependency {
064    
065            private final Class<?> componentType;
066    
067            private final Class<?> dependencyType;
068    
069            public Dependency(final Class<?> componentType, final Class<?> dependencyType) {
070                this.componentType = componentType;
071                this.dependencyType = dependencyType;
072            }
073    
074            public boolean dependsOn(final Class<?> type) {
075                return (type != null) && type.equals(dependencyType);
076            }
077    
078            @Override
079                    public boolean equals(final Object other) {
080                if (other instanceof Dependency) {
081                    Dependency otherDependency = (Dependency) other;
082                    return areEqualOrNull(componentType, otherDependency.componentType)
083                            && areEqualOrNull(dependencyType, otherDependency.dependencyType);
084                }
085                return false;
086            }
087    
088            public Class<?> getComponentType() {
089                return componentType;
090            }
091    
092            public Class<?> getDependencyType() {
093                return dependencyType;
094            }
095    
096            @Override
097                    public String toString() {
098                return componentType + " depends on " + dependencyType;
099            }
100    
101            private static boolean areEqualOrNull(final Class<?> type, final Class<?> otherType) {
102                if (type != null) {
103                    return type.equals(otherType);
104                }
105                return (otherType == null);
106            }
107        }
108    }