View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.java.symboltable;
5   
6   import java.util.HashSet;
7   import java.util.Set;
8   
9   /**
10   * Just stores a type image and a actual type.
11   * And makes it easy to compare these.
12   */
13  public class SimpleTypedNameDeclaration implements TypedNameDeclaration {
14  
15      final private String typeImage;
16      final private Class<?> type;
17  
18      /**
19       * Creates a new {@link SimpleTypedNameDeclaration} with the given type
20       * @param typeImage the type image
21       * @param type the actual type
22       */
23      public SimpleTypedNameDeclaration(String typeImage, Class<?> type) {
24          this.typeImage = typeImage;
25          this.type = type;
26      }
27  
28      @Override
29      public String getTypeImage() {
30          return typeImage;
31      }
32  
33      @Override
34      public Class<?> getType() {
35          return type;
36      }
37  
38      @Override
39      public String toString() {
40          return "SimpleType:" + type + "/" + typeImage;
41      }
42  
43      @Override
44      public int hashCode() {
45          final int prime = 31;
46          int result = 1;
47          result = prime * result + ((type == null) ? 0 : type.hashCode());
48          result = prime * result + ((typeImage == null) ? 0 : typeImage.hashCode());
49          return result;
50      }
51  
52      /**
53       * {@inheritDoc}
54       * <p>
55       * Additionally - two {@link SimpleTypedNameDeclaration} are equal, if
56       * they contain types, that can be cast into each other.
57       * </p>
58       */
59      @Override
60      public boolean equals(Object obj) {
61          if (this == obj)
62              return true;
63          if (obj == null)
64              return false;
65          if (getClass() != obj.getClass())
66              return false;
67          SimpleTypedNameDeclaration other = (SimpleTypedNameDeclaration) obj;
68          if (type == null) {
69              if (other.type != null)
70                  return false;
71          }
72          if (type != null && type.equals(other.type))
73              return true;
74  
75          // if the type is given, only compare the type and don't care about the type image
76          if (type != null && other.type != null && (type.isAssignableFrom(other.type) || other.type.isAssignableFrom(type)))
77              return true;
78  
79          if (typeImage == null) {
80              if (other.typeImage != null)
81                  return false;
82          } else if (!typeImage.equals(other.typeImage)) {
83              // consider auto-boxing
84              if (other.typeImage != null) {
85                  String lcType = typeImage.toLowerCase();
86                  String otherLcType = other.typeImage.toLowerCase();
87                  if (primitiveTypes.contains(lcType) && primitiveTypes.contains(otherLcType)) {
88                      if (lcType.equals(otherLcType)) {
89                          return true;
90                      } else if ((lcType.equals("char") || lcType.equals("character"))
91                              && (otherLcType.equals("char") || otherLcType.equals("character"))) {
92                          return true;
93                      } else if ((lcType.equals("int") || lcType.equals("integer")) && (
94                              otherLcType.equals("int")
95                              || otherLcType.equals("integer")
96                              || otherLcType.equals("short")
97                              || otherLcType.equals("char")
98                              || otherLcType.equals("character")
99                              || otherLcType.equals("byte")
100                             )) {
101                         return true;
102                     } else if (lcType.equals("double") && (
103                             otherLcType.equals("float")
104                             || otherLcType.equals("int")
105                             || otherLcType.equals("integer")
106                             || otherLcType.equals("long")
107                             )) {
108                         return true;
109                     } else if (lcType.equals("float") && (
110                             otherLcType.equals("int")
111                             || otherLcType.equals("integer")
112                             || otherLcType.equals("long")
113                             )) {
114                         return true;
115                     } else if (lcType.equals("long") && (
116                             otherLcType.equals("int")
117                             || otherLcType.equals("integer")
118                             || otherLcType.equals("char")
119                             || otherLcType.equals("character")
120                             )) {
121                         return true;
122                     }
123                 }
124             }
125             return false;
126         }
127         return true;
128     }
129 
130     private static Set<String> primitiveTypes = new HashSet<String>();
131     static {
132         primitiveTypes.add("float");
133         primitiveTypes.add("double");
134         primitiveTypes.add("int");
135         primitiveTypes.add("integer");
136         primitiveTypes.add("long");
137         primitiveTypes.add("byte");
138         primitiveTypes.add("short");
139         primitiveTypes.add("boolean");
140         primitiveTypes.add("char");
141         primitiveTypes.add("character");
142     }
143 }