View Javadoc

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      // TODO cite the JLS section on implicit imports
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         // we don't build the resolvers until now since we first want to get all the imports
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 }