• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2008 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.inject.grapher;
18 
19 import com.google.common.base.Joiner;
20 import com.google.common.collect.Lists;
21 import com.google.inject.Key;
22 import com.google.inject.TypeLiteral;
23 import com.google.inject.internal.ProviderMethod;
24 import com.google.inject.internal.util.StackTraceElements;
25 import com.google.inject.spi.ElementSource;
26 
27 import java.lang.annotation.Annotation;
28 import java.lang.reflect.Constructor;
29 import java.lang.reflect.Member;
30 import java.lang.reflect.Method;
31 import java.util.List;
32 
33 /**
34  * Reasonable implementation for {@link NameFactory}. Mostly takes various
35  * {@link Object#toString()}s and strips package names out of them so that
36  * they'll fit on the graph.
37  *
38  * @author phopkins@gmail.com (Pete Hopkins)
39  */
40 public class ShortNameFactory implements NameFactory {
getMemberName(Member member)41   public String getMemberName(Member member) {
42     if (member instanceof Constructor) {
43       return "<init>";
44     } else if (member instanceof Method) {
45       return "#" + member.getName() + "(...)";
46     } else {
47       return member.getName();
48     }
49   }
50 
getAnnotationName(Key<?> key)51   public String getAnnotationName(Key<?> key) {
52     Annotation annotation = key.getAnnotation();
53     Class<? extends Annotation> annotationType = key.getAnnotationType();
54     if (annotation != null) {
55       annotationType = annotation.annotationType();
56 
57       String annotationString = annotation.toString();
58       String canonicalName = annotationType.getName();
59       String simpleName = annotationType.getSimpleName();
60 
61       return annotationString.replace(canonicalName, simpleName).replace("()", "");
62     } else if (annotationType != null) {
63       return "@" + annotationType.getSimpleName();
64     } else {
65       return "";
66     }
67   }
68 
getClassName(Key<?> key)69   public String getClassName(Key<?> key) {
70     TypeLiteral<?> typeLiteral = key.getTypeLiteral();
71     return stripPackages(typeLiteral.toString());
72   }
73 
getInstanceName(Object instance)74   public String getInstanceName(Object instance) {
75     if (instance instanceof ProviderMethod) {
76       return getMethodString(((ProviderMethod<?>) instance).getMethod());
77     }
78 
79     if (instance instanceof CharSequence) {
80       return "\"" + instance + "\"";
81     }
82 
83     try {
84       if (instance.getClass().getMethod("toString").getDeclaringClass().equals(Object.class)) {
85         return stripPackages(instance.getClass().getName());
86       }
87     } catch (SecurityException e) {
88       throw new AssertionError(e);
89     } catch (NoSuchMethodException e) {
90       throw new AssertionError(e);
91     }
92 
93     return instance.toString();
94   }
95 
96   /**
97    * Returns a name for a Guice "source" object. This will typically be either
98    * a {@link StackTraceElement} for when the binding is made to the instance,
99    * or a {@link Method} when a provider method is used.
100    */
getSourceName(Object source)101   public String getSourceName(Object source) {
102     if (source instanceof ElementSource) {
103       source = ((ElementSource) source).getDeclaringSource();
104     }
105     if (source instanceof Method) {
106       source = StackTraceElements.forMember((Method) source);
107     }
108 
109     if (source instanceof StackTraceElement) {
110       return getFileString((StackTraceElement) source);
111     }
112 
113     return stripPackages(source.toString());
114   }
115 
getFileString(StackTraceElement stackTraceElement)116   protected String getFileString(StackTraceElement stackTraceElement) {
117     return stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber();
118   }
119 
getMethodString(Method method)120   protected String getMethodString(Method method) {
121     List<String> paramStrings = Lists.newArrayList();
122     for (Class<?> paramType : method.getParameterTypes()) {
123       paramStrings.add(paramType.getSimpleName());
124     }
125 
126     String paramString = Joiner.on(", ").join(paramStrings);
127     return "#" + method.getName() + "(" + paramString + ")";
128   }
129 
130   /**
131    * Eliminates runs of lowercase characters and numbers separated by periods.
132    * Seems to remove packages from fully-qualified type names pretty well.
133    */
stripPackages(String str)134   private String stripPackages(String str) {
135     return str.replaceAll("(^|[< .\\(])([a-z0-9]+\\.)*", "$1");
136   }
137 }
138