Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/puppycrawl/tools/checkstyle/checks/usage/transmogrify/ClassDef.java


1   
2   // Transmogrify License
3   // 
4   // Copyright (c) 2001, ThoughtWorks, Inc.
5   // All rights reserved.
6   // Redistribution and use in source and binary forms, with or without
7   // modification, are permitted provided that the following conditions
8   // are met:
9   // - Redistributions of source code must retain the above copyright notice,
10  //   this list of conditions and the following disclaimer.
11  // - Redistributions in binary form must reproduce the above copyright
12  // notice, this list of conditions and the following disclaimer in the
13  // documentation and/or other materials provided with the distribution.
14  // Neither the name of the ThoughtWorks, Inc. nor the names of its
15  // contributors may be used to endorse or promote products derived from this
16  // software without specific prior written permission.
17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21  // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27  // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  
29  package com.puppycrawl.tools.checkstyle.checks.usage.transmogrify;
30  
31  import java.util.ArrayList;
32  import java.util.Enumeration;
33  import java.util.HashSet;
34  import java.util.Hashtable;
35  import java.util.Iterator;
36  import java.util.List;
37  import java.util.Set;
38  import java.util.SortedSet;
39  import java.util.TreeSet;
40  import java.util.Vector;
41  
42  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
43  
44  
45  
46  /**
47   * <code>ClassDef</code> contains all the information needed to
48   * represent a java class or interface.  This includes the superclass,
49   * whether it's a class or an interface, the interfaces it implements,
50   * a list of its (direct?) subclasses, and the classes that implement
51   * it if it is an interface
52   *
53   * @see Scope
54   */
55  public class ClassDef extends DefaultScope implements IClass {
56      private long id = 0;
57  
58      private IClass superclass = null;
59      private List interfaces = new Vector();
60  
61      private List subclasses = new Vector();
62      private List implementors = new Vector();
63  
64      private Set importedPackages = new HashSet();
65  
66      // variable definitions will use elements from parent
67      private Set methods = new HashSet();
68  
69      private Hashtable imports = new Hashtable();
70      private Vector unprocessedImports = null;
71  
72      protected MethodDef _defaultConstructor;
73  
74      public ClassDef(String name, Scope parentScope, SymTabAST node) {
75          super(name, parentScope, node);
76          _defaultConstructor = new DefaultConstructor(this);
77          addDefinition(_defaultConstructor);
78      }
79  
80      public long getNextAnonymousId() {
81          return ++id;
82      }
83  
84      public void setSuperclass(IClass superclass) {
85          this.superclass = superclass;
86      }
87  
88      public IClass getSuperclass() {
89          return superclass;
90      }
91  
92      public void addUnprocessedImports(Vector imports) {
93          unprocessedImports = (Vector) (imports.clone());
94      }
95  
96      public Vector getUnprocessedImports() {
97          return unprocessedImports;
98      }
99  
100     public void importPackage(IPackage pkg) {
101         importedPackages.add(pkg);
102     }
103 
104     public void importClass(IClass imported) {
105         imports.put(imported.getName(), imported);
106     }
107 
108     // begin definitions interface
109 
110     public void addDefinition(MethodDef method) {
111         if (method.getName().equals(getName())) {
112             methods.remove(_defaultConstructor);
113         }
114         methods.add(method);
115     }
116 
117     protected Enumeration getDefinitions() {
118         Vector allElements = new Vector();
119 
120         allElements.addAll(elements.values());
121         allElements.addAll(methods);
122         allElements.addAll(labels.values());
123         allElements.addAll(classes.values());
124 
125         return allElements.elements();
126     }
127 
128     public IClass getClassDefinition(String name) {
129         IClass result = null;
130 
131         result = (ClassDef) (classes.get(name));
132 
133         if (result == null) {
134             result = (IClass) (imports.get(name));
135         }
136 
137         if (result == null) {
138             Iterator it = importedPackages.iterator();
139             while (it.hasNext() && result == null) {
140                 IPackage pkg = (IPackage) it.next();
141                 result = pkg.getClass(name);
142             }
143         }
144 
145         if (result == null) {
146             result = getParentScope().getClassDefinition(name);
147         }
148         
149         //TODO: check for a class in the same package?
150         if (result == null) {
151             final String packageName = getParentScope().getQualifiedName();
152             final String fullName = packageName + "." + name;
153             Class theClass = null;
154             try {
155                 theClass = ClassManager.getClassLoader().loadClass(fullName);
156                 result = new ExternalClass(theClass);
157             }
158             catch (ClassNotFoundException e) {
159                 // no-op
160             }
161         }
162          
163         return result;
164     }
165 
166     public IMethod getMethodDefinition(String name, ISignature signature) {
167         IMethod result = null;
168 
169         result = getDeclaredMethod(name, signature);
170 
171         if (result == null) {
172             result = getMostCompatibleMethod(name, signature);
173         }
174 
175         if (result == null) {
176             if (superclass != null) {
177                 result = superclass.getMethodDefinition(name, signature);
178             }
179         }
180 
181         if (result == null) {
182             IClass[] interfaces = getInterfaces();
183             for (int index = 0;
184                 index < interfaces.length && result == null;
185                 index++) {
186                 result = interfaces[index].getMethodDefinition(name, signature);
187             }
188         }
189 
190         // not sure why this is here -- inner classes, maybe?
191         // regardless, write better
192         if (result == null) {
193             if (getParentScope() != null) {
194                 result = getParentScope().getMethodDefinition(name, signature);
195             }
196         }
197 
198         return result;
199     }
200 
201     public IMethod getMostCompatibleMethod(String name, ISignature signature) {
202         IMethod result = null;
203 
204         SortedSet compatibleMethods =
205             new TreeSet(new MethodSpecificityComparator());
206 
207         Iterator it = methods.iterator();
208         while (it.hasNext()) {
209             MethodDef method = (MethodDef) it.next();
210             if (name.equals(method.getName())) {
211                 if (method.hasCompatibleSignature(signature)) {
212                     compatibleMethods.add(method);
213                 }
214             }
215         }
216 
217         if (!compatibleMethods.isEmpty()) {
218             result = (IMethod) compatibleMethods.first();
219         }
220 
221         return result;
222     }
223 
224     public IMethod getDeclaredMethod(String name, ISignature signature) {
225         // finds methods declared by this class with the given signature
226 
227         IMethod result = null;
228 
229         Iterator it = methods.iterator();
230         while (it.hasNext()) {
231             MethodDef method = (MethodDef) it.next();
232             if (name.equals(method.getName())) {
233                 if (method.hasSameSignature(signature)) {
234                     result = method;
235                     break;
236                 }
237             }
238         }
239 
240         return result;
241     }
242 
243     public IVariable getVariableDefinition(String name) {
244         IVariable result = null;
245 
246         // in keeping with getField in java.lang.Class
247         // 1) current class
248         // 2) direct superinterfaces
249         // 3) superclass
250         // then we do the parent scope in case its an inner class
251 
252         result = (VariableDef) (elements.get(name));
253 
254         if (result == null) {
255             IClass[] superinterfaces = getInterfaces();
256             for (int i = 0;
257                 i < superinterfaces.length && result == null;
258                 i++) {
259                 result = superinterfaces[i].getVariableDefinition(name);
260             }
261         }
262 
263         if (result == null) {
264             if (superclass != null) {
265                 result = superclass.getVariableDefinition(name);
266             }
267         }
268 
269         if (result == null) {
270             if (getParentScope() != null) {
271                 result = getParentScope().getVariableDefinition(name);
272             }
273         }
274 
275         return result;
276     }
277 
278     // end definitions interface
279 
280     public void addInterface(IClass implemented) {
281         interfaces.add(implemented);
282     }
283 
284     public IClass[] getInterfaces() {
285         IClass[] type = new IClass[0];
286         return (IClass[]) interfaces.toArray(type);
287     }
288 
289     public ClassDef getEnclosingClass() {
290         return this;
291     }
292 
293     public void addSubclass(ClassDef subclass) {
294         subclasses.add(subclass);
295     }
296 
297     public List getSubclasses() {
298         return subclasses;
299     }
300 
301     public void addImplementor(ClassDef implementor) {
302         implementors.add(implementor);
303     }
304 
305     public List getImplementors() {
306         return implementors;
307     }
308 
309     public IClass[] getInnerClasses() {
310         Iterator it = getClasses();
311         List result = new ArrayList();
312 
313         while (it.hasNext()) {
314             result.add(it.next());
315         }
316 
317         return (IClass[]) result.toArray(new IClass[0]);
318     }
319 
320     public boolean isSuperclassOf(IClass possibleChild) {
321         // justify my existence
322         boolean result = subclasses.contains(possibleChild);
323 
324         /*
325         Iterator it = subclasses.iterator();
326         while (it.hasNext() && !result) {
327           IClass child = (IClass)it.next();
328           result = child.isSuperclassOf(possibleChild);
329         }
330         */
331         return result;
332     }
333 
334     public boolean isCompatibleWith(IClass type) {
335         boolean result = false;
336 
337         // check myself
338         if (type.equals(this)) {
339             result = true;
340         }
341         // check my superclass
342         else if (superclass != null && superclass.isCompatibleWith(type)) {
343             result = true;
344         }
345         // check my interfaces
346         else if (!interfaces.isEmpty()) {
347             Iterator it = interfaces.iterator();
348 
349             while (it.hasNext() && !result) {
350                 IClass current = (IClass) it.next();
351 
352                 if (current.isCompatibleWith(type)) {
353                     result = true;
354                 }
355             }
356         }
357 
358         return result;
359     }
360 
361     public boolean isPrimitive() {
362         return false;
363     }
364 
365     private SymTabAST getObjblock() {
366         return getTreeNode().findFirstToken(TokenTypes.OBJBLOCK);
367     }
368 
369 }