1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.symboltable;
5
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13
14 /***
15 * Keeps track of the types encountered in a ASTCompilationUnit
16 */
17 public class TypeSet {
18
19
20 /***
21 * TODO should Resolver provide a canResolve() and a resolve()?
22 * Requiring 2 calls seems clunky... but so does this
23 * throwing an exception for flow control...
24 */
25 public interface Resolver {
26 Class resolve(String name) throws ClassNotFoundException;
27 }
28
29 public static class ExplicitImportResolver implements Resolver {
30 private Set importStmts;
31
32 public ExplicitImportResolver(Set importStmts) {
33 this.importStmts = importStmts;
34 }
35
36 public Class resolve(String name) throws ClassNotFoundException {
37 for (Iterator i = importStmts.iterator(); i.hasNext();) {
38 String importStmt = (String) i.next();
39 if (importStmt.endsWith(name)) {
40 return Class.forName(importStmt);
41 }
42 }
43 throw new ClassNotFoundException("Type " + name + " not found");
44 }
45 }
46
47 public static class CurrentPackageResolver implements Resolver {
48 private String pkg;
49
50 public CurrentPackageResolver(String pkg) {
51 this.pkg = pkg;
52 }
53
54 public Class resolve(String name) throws ClassNotFoundException {
55 return Class.forName(pkg + name);
56 }
57 }
58
59
60 public static class ImplicitImportResolver implements Resolver {
61 public Class resolve(String name) throws ClassNotFoundException {
62 return Class.forName("java.lang." + name);
63 }
64 }
65
66 public static class ImportOnDemandResolver implements Resolver {
67 private Set importStmts;
68
69 public ImportOnDemandResolver(Set importStmts) {
70 this.importStmts = importStmts;
71 }
72
73 public Class resolve(String name) throws ClassNotFoundException {
74 for (Iterator i = importStmts.iterator(); i.hasNext();) {
75 String importStmt = (String) i.next();
76 if (importStmt.endsWith("*")) {
77 try {
78 String importPkg = importStmt.substring(0, importStmt.indexOf("*") - 1);
79 return Class.forName(importPkg + "." + name);
80 } catch (ClassNotFoundException cnfe) {
81 }
82 }
83 }
84 throw new ClassNotFoundException("Type " + name + " not found");
85 }
86 }
87
88 public static class PrimitiveTypeResolver implements Resolver {
89 private Map primitiveTypes = new HashMap();
90
91 public PrimitiveTypeResolver() {
92 primitiveTypes.put("int", int.class);
93 primitiveTypes.put("float", float.class);
94 primitiveTypes.put("double", double.class);
95 primitiveTypes.put("long", long.class);
96 primitiveTypes.put("boolean", boolean.class);
97 primitiveTypes.put("byte", byte.class);
98 primitiveTypes.put("short", short.class);
99 primitiveTypes.put("char", char.class);
100 }
101
102 public Class resolve(String name) throws ClassNotFoundException {
103 if (!primitiveTypes.containsKey(name)) {
104 throw new ClassNotFoundException();
105 }
106 return (Class) primitiveTypes.get(name);
107 }
108 }
109
110 public static class VoidResolver implements Resolver {
111 public Class resolve(String name) throws ClassNotFoundException {
112 if (name.equals("void")) {
113 return void.class;
114 }
115 throw new ClassNotFoundException();
116 }
117 }
118
119 public static class FullyQualifiedNameResolver implements Resolver {
120 public Class resolve(String name) throws ClassNotFoundException {
121 return Class.forName(name);
122 }
123 }
124
125 private String pkg;
126 private Set imports = new HashSet();
127 private List resolvers = new ArrayList();
128
129 public void setASTCompilationUnitPackage(String pkg) {
130 this.pkg = pkg;
131 }
132
133 public String getASTCompilationUnitPackage() {
134 return pkg;
135 }
136
137 public void addImport(String importString) {
138 imports.add(importString);
139 }
140
141 public int getImportsCount() {
142 return imports.size();
143 }
144
145 public Class findClass(String name) throws ClassNotFoundException {
146
147 if (resolvers.isEmpty()) {
148 buildResolvers();
149 }
150
151 for (Iterator i = resolvers.iterator(); i.hasNext();) {
152 Resolver resolver = (Resolver) i.next();
153 try {
154 return resolver.resolve(name);
155 } catch (ClassNotFoundException cnfe) {
156 }
157 }
158
159 throw new ClassNotFoundException("Type " + name + " not found");
160 }
161
162 private void buildResolvers() {
163 resolvers.add(new PrimitiveTypeResolver());
164 resolvers.add(new VoidResolver());
165 resolvers.add(new ExplicitImportResolver(imports));
166 resolvers.add(new CurrentPackageResolver(pkg));
167 resolvers.add(new ImplicitImportResolver());
168 resolvers.add(new ImportOnDemandResolver(imports));
169 resolvers.add(new FullyQualifiedNameResolver());
170 }
171
172 }