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 *****************************************************************************/
010package org.picocontainer.gems.monitors;
011
012import java.lang.reflect.Constructor;
013
014import org.picocontainer.monitors.AbstractComponentMonitor;
015import org.picocontainer.gems.monitors.prefuse.ComponentDependencyListener;
016import org.picocontainer.ComponentAdapter;
017import 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")
027public 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}