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 Paul Hammant                                             *
009     *****************************************************************************/
010    
011    package org.picocontainer.gems.monitors;
012    
013    import org.picocontainer.ComponentMonitor;
014    import org.picocontainer.defaults.DelegatingComponentMonitor;
015    
016    import java.lang.reflect.Constructor;
017    import java.util.*;
018    
019    public class DotDependencyGraphComponentMonitor extends DelegatingComponentMonitor implements ComponentMonitor {
020    
021        ArrayList allInstantiated = new ArrayList();
022    
023        public DotDependencyGraphComponentMonitor(ComponentMonitor delegate) {
024            super(delegate);
025        }
026    
027        public DotDependencyGraphComponentMonitor() {
028        }
029    
030        public void instantiated(Constructor constructor, Object instantiated, Object[] injected, long duration) {
031    
032            this.allInstantiated.add(new Instantiation(constructor, instantiated, injected, duration));
033    
034            super.instantiated(constructor, instantiated, injected, duration);
035        }
036    
037    
038        public String getClassDependencyGraph() {
039    
040            HashSet lines = new HashSet();
041    
042            for (int i = 0; i < allInstantiated.size(); i++) {
043                Instantiation instantiation = (Instantiation) allInstantiated.get(i);
044                for (int j = 0; j < instantiation.getInjected().length; j++) {
045                    Object instantiated = instantiation.getInstantiated();
046                    Object injected = instantiation.getInjected()[j];
047                    lines.add("  '" + instantiated.getClass().getName() + "' -> '" + injected.getClass().getName() + "';\n");
048                }
049            }
050    
051            return sortLines(lines);
052        }
053    
054        private String sortLines(HashSet lines) {
055            ArrayList list = new ArrayList(lines);
056            Collections.sort(list);
057    
058            String dependencies = "";
059            for (Iterator iterator = list.iterator(); iterator.hasNext();) {
060                String dep = (String) iterator.next();
061                dependencies = dependencies + dep;
062            }
063            return dependencies.replaceAll("'","\"");
064        }
065    
066        public String getInterfaceDependencyGraph() {
067            HashSet lines = new HashSet();
068    
069            for (int i = 0; i < allInstantiated.size(); i++) {
070                Instantiation instantiation = (Instantiation) allInstantiated.get(i);
071                for (int j = 0; j < instantiation.getInjected().length; j++) {
072                    Object injected = instantiation.getInjected()[j];
073                    Class injectedType = instantiation.getConstructor().getParameterTypes()[j];
074                    Object instantiated = instantiation.getInstantiated();
075                    if (injected.getClass() != injectedType) {
076                        lines.add("  '" + instantiated.getClass().getName() + "' -> '" + injectedType.getName() + "' [style=dotted,label='needs'];\n");
077                        lines.add("  '" + injected.getClass().getName() + "' -> '" + injectedType.getName() + "' [style=dotted, color=red,label='isA'];\n");
078                        lines.add("  '" + injectedType.getName() + "' [shape=box, label=" + printClassName(injectedType) + "];\n");
079                    } else {
080                        lines.add("  '" + instantiated.getClass().getName() + "' -> '" + injected.getClass().getName() + "' [label='needs'];\n");
081                    }
082                    lines.add("  '" + instantiated.getClass().getName() + "' [label=" + printClassName(instantiated.getClass()) + "];\n");
083    
084                }
085            }
086    
087            return sortLines(lines);
088        }
089    
090        private String printClassName(Class clazz) {
091            String className = clazz.getName();
092            return "'" + className.substring(className.lastIndexOf(".")+1) + "\\n" + clazz.getPackage().getName() + "'";
093    
094        }
095    
096        private static class Instantiation {
097            Constructor constructor;
098            Object instantiated;
099            Object[] injected;
100            long duration;
101            public Instantiation(Constructor constructor, Object instantiated, Object[] injected, long duration) {
102                this.constructor = constructor;
103                this.instantiated = instantiated;
104                this.injected = injected;
105                this.duration = duration;
106            }
107    
108            public Constructor getConstructor() {
109                return constructor;
110            }
111    
112            public Object getInstantiated() {
113                return instantiated;
114            }
115            public Object[] getInjected() {
116                return injected;
117            }
118        }
119    }