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 }