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/ExternalClass.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  
32  
33  import java.lang.reflect.Constructor;
34  import java.lang.reflect.Field;
35  import java.lang.reflect.Method;
36  import java.util.ArrayList;
37  import java.util.Collection;
38  import java.util.HashSet;
39  import java.util.Iterator;
40  import java.util.List;
41  import java.util.Set;
42  import java.util.SortedSet;
43  import java.util.TreeSet;
44  
45  //import com.puppycrawl.tools.checkstyle.checks.lint.parser.DotUtils;
46  
47  public class ExternalClass extends ExternalDefinition implements IClass {
48    private Class _javaClass;
49  
50    private List _subclasses;
51    private List _implementors;
52  
53    private Set _methods;
54  
55    public ExternalClass(Class javaClass) {
56      _javaClass = javaClass;
57      _subclasses = new ArrayList();
58      _implementors = new ArrayList();
59    }
60  
61    public Class getJavaClass() {
62      return _javaClass;
63    }
64  
65    public String getName() {
66      return getLocalName();
67    }
68  
69    private String getLocalName() {
70      String fullName = _javaClass.getName();
71      return fullName.substring(fullName.lastIndexOf(".") + 1);
72    }
73  
74    public IClass getSuperclass() {
75      IClass result = null;
76      Class javaSuperclass = _javaClass.getSuperclass();
77  
78      if (javaSuperclass != null) {
79        result = new ExternalClass(javaSuperclass);
80      }
81      else {
82        if (_javaClass.isInterface()) {
83          // according to Java, java.lang.Object is not the superclass of
84          // interfaces, which makes sense.  However, we need Object to be
85          // the superclass of everything to make type compatibility work.
86          result = new ExternalClass(Object.class);
87        }
88      }
89  
90      return result;
91    }
92  
93    public IClass[] getInterfaces() {
94      Class[] javaInterfaces = _javaClass.getInterfaces();
95  
96      IClass[] result = new IClass[javaInterfaces.length];
97  
98      // should we cache this?
99      for (int i = 0; i < javaInterfaces.length; i++) {
100       result[i] = new ExternalClass(javaInterfaces[i]);
101     }
102 
103     return result;
104   }
105 
106   public IClass getClassDefinition(String name) {
107     IClass result = null;
108 
109     String qualifiedName = getQualifiedName() + "$" + name;
110 
111     Class[] classes = getJavaClass().getClasses();
112     for (int i = 0; i < classes.length; i++) {
113       String candidateQualifiedName = classes[i].getName();
114 
115       if (qualifiedName.equals(candidateQualifiedName)) {
116         result = new ExternalClass(classes[i]);
117         break;
118       }
119     }
120 
121     return result;
122   }
123 
124   // REDTAG -- this should be a template method!
125   public IVariable getVariableDefinition(String name) {
126     IVariable result = null;
127     Field javaField = null;
128 
129     try {
130       javaField = _javaClass.getDeclaredField(name);
131     }
132     catch (NoSuchFieldException ignoreMe) {}
133 
134     if (javaField == null) {
135       Class[] interfaces = _javaClass.getInterfaces();
136       for (int i = 0; i < interfaces.length && javaField == null; i++) {
137         try {
138           javaField = interfaces[i].getDeclaredField(name);
139         }
140         catch (NoSuchFieldException ignoreMe) {}
141       }
142     }
143 
144     if (javaField != null) {
145       result = new ExternalVariable(javaField);
146     }
147     else {
148       if (getSuperclass() != null) {
149         result = getSuperclass().getVariableDefinition(name);
150       }
151     }
152 
153     return result;
154   }
155 
156   public IMethod getMethodDefinition(String name,
157                                      ISignature signature) {
158     IMethod result = null;
159 
160     if (name.equals(getName())) {
161       result = getConstructorDefinition(signature);
162     }
163     else {
164       Method[] methods = _javaClass.getDeclaredMethods();
165 
166       for (int i = 0; i < methods.length; i++) {
167         if (name.equals(methods[i].getName())) {
168           IMethod method = new ExternalMethod(methods[i]);
169           if (method.hasSameSignature(signature)) {
170             result = method;
171             break;
172           }
173         }
174       }
175 
176       if (result == null) {
177         result = getMostCompatibleMethod(name, signature);
178       }
179 
180       if (result == null) {
181         if (getSuperclass() != null) {
182           result = getSuperclass().getMethodDefinition(name, signature);
183         }
184       }
185 
186       if (result == null) {
187         IClass[] interfaces = getInterfaces();
188         for (int i = 0; i < interfaces.length; i++) {
189           result = interfaces[i].getMethodDefinition(name, signature);
190 
191           if (result != null) {
192             break;
193           }
194 
195         }
196       }
197     }
198 
199     return result;
200   }
201 
202   public IMethod getMostCompatibleMethod(String name, ISignature signature) {
203     IMethod result = null;
204 
205     SortedSet compatibleMethods
206       = new TreeSet(new MethodSpecificityComparator());
207 
208     Iterator it = getMethods().iterator();
209     while (it.hasNext()) {
210       IMethod method = (IMethod)it.next();
211       if ( name.equals( method.getName() ) ) {
212         if ( method.hasCompatibleSignature( signature ) ) {
213           compatibleMethods.add(method);
214         }
215       }
216     }
217 
218     if (!compatibleMethods.isEmpty()) {
219       result = (IMethod)compatibleMethods.first();
220     }
221 
222     return result;
223   }
224 
225   private Collection getMethods() {
226     if (_methods == null) {
227       _methods = new HashSet();
228 
229       Method[] methods = _javaClass.getDeclaredMethods();
230       for (int i = 0; i < methods.length; i++) {
231         _methods.add(new ExternalMethod(methods[i]));
232       }
233 
234     }
235 
236     return _methods;
237   }
238 
239   public IMethod getConstructorDefinition(ISignature signature) {
240     IMethod result = null;
241 
242     if (_javaClass.isInterface()) {
243       result = getInterfaceConstructor(signature);
244     }
245     else {
246       result = getClassConstructor(signature);
247     }
248 
249     return result;
250   }
251 
252   private IMethod getInterfaceConstructor(ISignature signature) {
253     IMethod result = null;
254 
255     if (signature.getParameters().length == 0) {
256       result = new InterfaceConstructor(_javaClass);
257     }
258 
259     return result;
260   }
261 
262   private IMethod getClassConstructor(ISignature signature) {
263     IMethod result = null;
264 
265     Constructor[] constructors = _javaClass.getConstructors();
266 
267     for (int i = 0; i < constructors.length; i++) {
268       IMethod constructor = new ExternalConstructor(constructors[i]);
269       if (constructor.hasSameSignature(signature)) {
270         result = constructor;
271         break;
272       }
273     }
274 
275     if (result == null) {
276       for (int i = 0; i < constructors.length; i++) {
277         IMethod constructor = new ExternalConstructor(constructors[i]);
278         if (constructor.hasCompatibleSignature(signature)) {
279           result = constructor;
280           break;
281         }
282       }
283     }
284 
285     return result;
286   }
287 
288   public boolean isCompatibleWith(IClass type) {
289     boolean result = false;
290 
291     if (isPrimitive() && type.isPrimitive()) {
292       result = PrimitiveClasses.typesAreCompatible((ExternalClass)type,
293                                                      this);
294     }
295     else {
296       // check myself
297       if (type.equals(this)) {
298         result = true;
299       }
300       // check my superclass
301       else if (getSuperclass() != null && getSuperclass().isCompatibleWith(type)) {
302         result = true;
303       }
304       // check my interfaces
305       else if (_javaClass.getInterfaces().length > 0) {
306         Class[] interfaces = _javaClass.getInterfaces();
307         for (int i = 0; i < interfaces.length; i++) {
308           if (new ExternalClass(interfaces[i]).isCompatibleWith(type)) {
309             result = true;
310             break;
311           }
312         }
313       }
314     }
315 
316     return result;
317   }
318 
319   private boolean isPrimitiveCompatibleWith(IClass type) {
320     boolean result = false;
321 
322     return result;
323   }
324 
325   public void addImplementor(ClassDef implementor) {
326     _implementors.add(implementor);
327   }
328 
329   public List getImplementors() {
330     return _implementors;
331   }
332 
333   public void addSubclass(ClassDef subclass) {
334     _subclasses.add(subclass);
335   }
336 
337   public List getSubclasses() {
338     return _subclasses;
339   }
340 
341   public String getQualifiedName() {
342     return _javaClass.getName();
343   }
344 
345   public boolean isPrimitive() {
346     return getJavaClass().isPrimitive();
347   }
348 
349   public IClass[] getInnerClasses() {
350     Class[] innerJavaClasses = getJavaClass().getDeclaredClasses();
351     IClass[] result = new IClass[innerJavaClasses.length];
352 
353     for (int i = 0; i < result.length; i++) {
354       result[i] = new ExternalClass(innerJavaClasses[i]);
355     }
356 
357     return result;
358   }
359 
360   public String toString() {
361      return getClass() + "[" + getQualifiedName() + "]";
362    }
363 
364   public boolean equals(Object o) {
365     boolean result = false;
366 
367     if (o instanceof ExternalClass) {
368       ExternalClass compared = (ExternalClass)o;
369       result = (getJavaClass().equals(compared.getJavaClass()));
370     }
371 
372     return result;
373   }
374 
375   public int hashCode() {
376     return getJavaClass().hashCode();
377   }
378 
379 }