001: package org.acm.seguin.pmd.symboltable;
002:
003: import java.util.ArrayList;
004: import java.util.HashMap;
005: import java.util.HashSet;
006: import java.util.Iterator;
007: import java.util.List;
008: import java.util.Map;
009: import java.util.Set;
010:
011: /**
012: * Keeps track of the types encountered in a ASTCompilationUnit
013: */
014: public class TypeSet {
015:
016: /**
017: * TODO should Resolver provide a canResolve() and a resolve()?
018: * Requiring 2 calls seems clunky... but so does this
019: * throwing an exception for flow control...
020: */
021: public interface Resolver {
022: Class resolve(String name) throws ClassNotFoundException;
023: }
024:
025: public static class ExplicitImportResolver implements Resolver {
026: private Set importStmts;
027:
028: public ExplicitImportResolver(Set importStmts) {
029: this .importStmts = importStmts;
030: }
031:
032: public Class resolve(String name) throws ClassNotFoundException {
033: for (Iterator i = importStmts.iterator(); i.hasNext();) {
034: String importStmt = (String) i.next();
035: if (importStmt.endsWith(name)) {
036: return Class.forName(importStmt);
037: }
038: }
039: throw new ClassNotFoundException("Type " + name
040: + " not found");
041: }
042: }
043:
044: public static class CurrentPackageResolver implements Resolver {
045: private String pkg;
046:
047: public CurrentPackageResolver(String pkg) {
048: this .pkg = pkg;
049: }
050:
051: public Class resolve(String name) throws ClassNotFoundException {
052: return Class.forName(pkg + name);
053: }
054: }
055:
056: // TODO cite the JLS section on implicit imports
057: public static class ImplicitImportResolver implements Resolver {
058: public Class resolve(String name) throws ClassNotFoundException {
059: return Class.forName("java.lang." + name);
060: }
061: }
062:
063: public static class ImportOnDemandResolver implements Resolver {
064: private Set importStmts;
065:
066: public ImportOnDemandResolver(Set importStmts) {
067: this .importStmts = importStmts;
068: }
069:
070: public Class resolve(String name) throws ClassNotFoundException {
071: for (Iterator i = importStmts.iterator(); i.hasNext();) {
072: String importStmt = (String) i.next();
073: if (importStmt.endsWith("*")) {
074: try {
075: String importPkg = importStmt.substring(0,
076: importStmt.indexOf("*") - 1);
077: return Class.forName(importPkg + "." + name);
078: } catch (ClassNotFoundException cnfe) {
079: }
080: }
081: }
082: throw new ClassNotFoundException("Type " + name
083: + " not found");
084: }
085: }
086:
087: public static class PrimitiveTypeResolver implements Resolver {
088: private Map primitiveTypes = new HashMap();
089:
090: public PrimitiveTypeResolver() {
091: primitiveTypes.put("int", int.class);
092: primitiveTypes.put("float", float.class);
093: primitiveTypes.put("double", double.class);
094: primitiveTypes.put("long", long.class);
095: primitiveTypes.put("boolean", boolean.class);
096: primitiveTypes.put("byte", byte.class);
097: primitiveTypes.put("short", short.class);
098: primitiveTypes.put("char", char.class);
099: }
100:
101: public Class resolve(String name) throws ClassNotFoundException {
102: if (!primitiveTypes.containsKey(name)) {
103: throw new ClassNotFoundException();
104: }
105: return (Class) primitiveTypes.get(name);
106: }
107: }
108:
109: public static class VoidResolver implements Resolver {
110: public Class resolve(String name) throws ClassNotFoundException {
111: if (name.equals("void")) {
112: return void.class;
113: }
114: throw new ClassNotFoundException();
115: }
116: }
117:
118: public static class FullyQualifiedNameResolver implements Resolver {
119: public Class resolve(String name) throws ClassNotFoundException {
120: return Class.forName(name);
121: }
122: }
123:
124: private String pkg;
125: private Set imports = new HashSet();
126: private List resolvers = new ArrayList();
127:
128: public void setASTCompilationUnitPackage(String pkg) {
129: this .pkg = pkg;
130: }
131:
132: public String getASTCompilationUnitPackage() {
133: return pkg;
134: }
135:
136: public void addImport(String importString) {
137: imports.add(importString);
138: }
139:
140: public int getImportsCount() {
141: return imports.size();
142: }
143:
144: public Class findClass(String name) throws ClassNotFoundException {
145: // we don't build the resolvers until now since we first want to get all the imports
146: if (resolvers.isEmpty()) {
147: buildResolvers();
148: }
149:
150: for (Iterator i = resolvers.iterator(); i.hasNext();) {
151: Resolver resolver = (Resolver) i.next();
152: try {
153: return resolver.resolve(name);
154: } catch (ClassNotFoundException cnfe) {
155: }
156: }
157:
158: throw new ClassNotFoundException("Type " + name + " not found");
159: }
160:
161: private void buildResolvers() {
162: resolvers.add(new PrimitiveTypeResolver());
163: resolvers.add(new VoidResolver());
164: resolvers.add(new ExplicitImportResolver(imports));
165: resolvers.add(new CurrentPackageResolver(pkg));
166: resolvers.add(new ImplicitImportResolver());
167: resolvers.add(new ImportOnDemandResolver(imports));
168: resolvers.add(new FullyQualifiedNameResolver());
169: }
170:
171: }
|