    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    }