1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jadira.scanner.classpath.types;
17
18 import java.lang.reflect.Field;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Set;
24
25 import javassist.bytecode.AnnotationsAttribute;
26 import javassist.bytecode.FieldInfo;
27 import javassist.bytecode.annotation.Annotation;
28
29 import org.apache.commons.lang3.builder.EqualsBuilder;
30 import org.apache.commons.lang3.builder.HashCodeBuilder;
31 import org.jadira.scanner.classpath.ClasspathResolver;
32 import org.jadira.scanner.classpath.visitor.IntrospectionVisitor;
33 import org.jadira.scanner.core.exception.ClasspathAccessException;
34
35 public class JField extends JVariable {
36
37 private FieldInfo fieldInfo;
38 private JClass jClass;
39
40 protected JField(FieldInfo fieldInfo, JClass jClass, ClasspathResolver resolver) {
41 super(fieldInfo.getName(), resolver);
42 this.fieldInfo = fieldInfo;
43 this.jClass = jClass;
44 }
45
46 public static JField getJField(FieldInfo fieldInfo, JClass jClass, ClasspathResolver resolver) {
47 return new JField(fieldInfo, jClass, resolver);
48 }
49
50 @Override
51 public JType getEnclosingType() {
52 return jClass;
53 }
54
55 @Override
56 public JType getType() throws ClasspathAccessException {
57
58 final JType retVal;
59
60 Class<?> clazz;
61 try {
62 Field field = getActualField();
63 clazz = field.getType();
64 } catch (SecurityException e) {
65 throw new ClasspathAccessException("Problem finding enclosing type: " + e.getMessage(), e);
66 }
67 if (clazz.isInterface()) {
68 retVal = JInterface.getJInterface(clazz.getName(), getResolver());
69 } else if (clazz.isPrimitive()) {
70 retVal = JPrimitiveClass.getJClass(clazz.getName(), getResolver());
71 } else if (clazz.isArray()) {
72 retVal = JArrayClass.getJClass(clazz, getResolver());
73 } else {
74 retVal = JClass.getJClass(clazz.getName(), getResolver());
75 }
76 return retVal;
77 }
78
79 public Class<?> decodeFieldType(String componentType) throws ClassNotFoundException {
80
81 char type = componentType.charAt(0);
82 String fieldContent = componentType.substring(1);
83
84 switch (type) {
85
86 case 'L':
87 return getResolver().loadClass(fieldContent.replace('/', '.'));
88
89 case 'B':
90 return Byte.class;
91
92 case 'C':
93 return Character.class;
94
95 case 'D':
96 return Double.class;
97
98 case 'F':
99 return Float.class;
100
101 case 'I':
102 return Integer.class;
103
104 case 'J':
105 return Long.class;
106
107 case 'S':
108 return Short.class;
109
110 case 'Z':
111 return Boolean.class;
112
113 case '[':
114 return getResolver().loadClass(componentType.replace('/', '.') + ";");
115 }
116 return null;
117 }
118
119 @Override
120 public Set<JAnnotation<?>> getAnnotations() {
121
122 AnnotationsAttribute visible = (AnnotationsAttribute) fieldInfo.getAttribute(AnnotationsAttribute.visibleTag);
123 AnnotationsAttribute invisible = (AnnotationsAttribute) fieldInfo.getAttribute(AnnotationsAttribute.invisibleTag);
124
125 Set<JAnnotation<?>> annotations = new HashSet<JAnnotation<?>>();
126
127 List<Annotation> annotationsList = new ArrayList<Annotation>();
128 if (visible != null) {
129 annotationsList.addAll(Arrays.asList(visible.getAnnotations()));
130 }
131 if (invisible != null) {
132 annotationsList.addAll(Arrays.asList(invisible.getAnnotations()));
133 }
134
135 for (Annotation nextAnnotation : annotationsList) {
136 annotations.add(JAnnotation.getJAnnotation(nextAnnotation, this, getResolver()));
137 }
138
139 return annotations;
140 }
141
142 @Override
143 public void acceptVisitor(IntrospectionVisitor visitor) {
144 visitor.visit(this);
145
146 for (JAnnotation<?> next : getAnnotations()) {
147 next.acceptVisitor(visitor);
148 }
149 }
150
151 public Field getActualField() {
152
153 try {
154 return getEnclosingType().getActualClass().getDeclaredField(getName());
155 } catch (SecurityException e) {
156 throw new ClasspathAccessException("Problem obtaining field: " + e.getMessage(), e);
157 } catch (NoSuchFieldException e) {
158 throw new ClasspathAccessException("Problem finding field: " + this.toString(), e);
159 }
160 }
161
162 public FieldInfo getFieldInfo() {
163 return fieldInfo;
164 }
165
166 @Override
167 public JClass getEnclosingElement() {
168 return jClass;
169 }
170
171 @Override
172 public boolean equals(Object obj) {
173 if (obj == null) {
174 return false;
175 }
176 if (obj == this) {
177 return true;
178 }
179 if (obj.getClass() != getClass()) {
180 return false;
181 }
182 JField rhs = (JField) obj;
183 return new EqualsBuilder()
184 .appendSuper(super.equals(obj))
185 .append(jClass, rhs.jClass).isEquals();
186 }
187
188 @Override
189 public int hashCode() {
190 return new HashCodeBuilder(11, 47).append(super.hashCode())
191 .append(jClass.getName()).toHashCode();
192 }
193 }