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 java.lang.reflect.Constructor;
014 import java.util.ArrayList;
015 import java.util.Collections;
016 import java.util.HashSet;
017 import java.util.List;
018 import java.util.Set;
019
020 import org.picocontainer.ComponentAdapter;
021 import org.picocontainer.ComponentMonitor;
022 import org.picocontainer.PicoContainer;
023 import org.picocontainer.monitors.AbstractComponentMonitor;
024
025 @SuppressWarnings("serial")
026 public final class DotDependencyGraphComponentMonitor extends AbstractComponentMonitor implements ComponentMonitor {
027
028
029 final List<Instantiation> allInstantiated = new ArrayList<Instantiation>();
030
031 public DotDependencyGraphComponentMonitor(final ComponentMonitor delegate) {
032 super(delegate);
033 }
034
035 public DotDependencyGraphComponentMonitor() {
036 }
037
038 @Override
039 public <T> void instantiated(final PicoContainer container, final ComponentAdapter<T> componentAdapter,
040 final Constructor<T> constructor,
041 final Object instantiated,
042 final Object[] injected,
043 final long duration) {
044
045 this.allInstantiated.add(new Instantiation(constructor, instantiated, injected, duration));
046
047 super.instantiated(container, componentAdapter, constructor, instantiated, injected, duration);
048 }
049
050
051 public String getClassDependencyGraph() {
052
053 Set<String> lines = new HashSet<String>();
054
055 for (Object anAllInstantiated : allInstantiated) {
056 Instantiation instantiation = (Instantiation)anAllInstantiated;
057 for (int j = 0; j < instantiation.getInjected().length; j++) {
058 Object instantiated = instantiation.getInstantiated();
059 Object injected = instantiation.getInjected()[j];
060 lines.add(
061 " '" + instantiated.getClass().getName() + "' -> '" + injected.getClass().getName() + "';\n");
062 }
063 }
064
065 return sortLines(lines);
066 }
067
068 private String sortLines(final Set<String> lines) {
069 List<String> list = new ArrayList<String>(lines);
070 Collections.sort(list);
071
072 String dependencies = "";
073 for (Object aList : list) {
074 String dep = (String)aList;
075 dependencies = dependencies + dep;
076 }
077 return dependencies.replaceAll("'","\"");
078 }
079
080 public String getInterfaceDependencyGraph() {
081 Set<String> lines = new HashSet<String>();
082
083 for (Object anAllInstantiated : allInstantiated) {
084 Instantiation instantiation = (Instantiation)anAllInstantiated;
085 for (int j = 0; j < instantiation.getInjected().length; j++) {
086 Object injected = instantiation.getInjected()[j];
087 Class<?> injectedType = instantiation.getConstructor().getParameterTypes()[j];
088 Object instantiated = instantiation.getInstantiated();
089 if (injected.getClass() != injectedType) {
090 lines.add(" '" + instantiated.getClass().getName() + "' -> '" + injectedType.getName() +
091 "' [style=dotted,label='needs'];\n");
092 lines.add(" '" + injected.getClass().getName() + "' -> '" + injectedType.getName() +
093 "' [style=dotted, color=red,label='isA'];\n");
094 lines.add(" '" + injectedType.getName() + "' [shape=box, label=" + printClassName(injectedType) +
095 "];\n");
096 } else {
097 lines.add(" '" + instantiated.getClass().getName() + "' -> '" + injected.getClass().getName() +
098 "' [label='needs'];\n");
099 }
100 lines.add(" '" + instantiated.getClass().getName() + "' [label=" +
101 printClassName(instantiated.getClass()) + "];\n");
102
103 }
104 }
105
106 return sortLines(lines);
107 }
108
109 private String printClassName(final Class<?> clazz) {
110 String className = clazz.getName();
111 return "'" + className.substring(className.lastIndexOf(".")+1) + "\\n" + clazz.getPackage().getName() + "'";
112
113 }
114
115 private static final class Instantiation {
116 final Constructor<?> constructor;
117 final Object instantiated;
118 final Object[] injected;
119 final long duration;
120
121 public Instantiation(final Constructor<?> constructor, final Object instantiated, final Object[] injected, final long duration) {
122 this.constructor = constructor;
123 this.instantiated = instantiated;
124 this.injected = injected;
125 this.duration = duration;
126 }
127
128 public Constructor<?> getConstructor() {
129 return constructor;
130 }
131
132 public Object getInstantiated() {
133 return instantiated;
134 }
135 public Object[] getInjected() {
136 return injected;
137 }
138 }
139 }