1 package org.sourceforge.jemm.weaver.transformation.field;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 import javassist.CtClass;
7 import javassist.CtField;
8 import javassist.NotFoundException;
9 import javassist.bytecode.Descriptor;
10
11 import org.sourceforge.jemm.Entity;
12 import org.sourceforge.jemm.collections.JemmList;
13 import org.sourceforge.jemm.collections.JemmMap;
14 import org.sourceforge.jemm.collections.JemmSet;
15 import org.sourceforge.jemm.util.JEMMObject;
16 import org.sourceforge.jemm.weaver.transformation.ClassPoolFactory;
17 import org.sourceforge.jemm.weaver.transformation.ShadowTransformation;
18
19
20
21
22
23
24
25
26 public class FieldClassifier {
27 Set<String> jemmClasses;
28 Set<String> primitiveDescriptors;
29 Set<String> knownImmutables;
30
31
32
33
34
35 public enum Classification {
36
37 COLLECTION,
38
39 SHADOW,
40
41 KNOWNIMMUTABLE,
42
43 SUPPORTED,
44
45 NORMALOBJECT,
46
47 PRIMITIVE,
48
49 ALREADYTRANSFORMED
50 }
51
52
53
54
55 public FieldClassifier() {
56 jemmClasses = new HashSet<String>();
57 jemmClasses.add(Descriptor.of(JemmList.class.getName()));
58 jemmClasses.add(Descriptor.of(JemmMap.class.getName()));
59 jemmClasses.add(Descriptor.of(JemmSet.class.getName()));
60
61 primitiveDescriptors = new HashSet<String>();
62 primitiveDescriptors.add(Descriptor.of(CtClass.shortType));
63 primitiveDescriptors.add(Descriptor.of(CtClass.intType));
64 primitiveDescriptors.add(Descriptor.of(CtClass.longType));
65 primitiveDescriptors.add(Descriptor.of(CtClass.floatType));
66 primitiveDescriptors.add(Descriptor.of(CtClass.doubleType));
67 primitiveDescriptors.add(Descriptor.of(CtClass.booleanType));
68 primitiveDescriptors.add(Descriptor.of(CtClass.byteType));
69 primitiveDescriptors.add(Descriptor.of(CtClass.charType));
70
71 knownImmutables = new HashSet<String>();
72 knownImmutables.add(Descriptor.of("java.lang.Short"));
73 knownImmutables.add(Descriptor.of("java.lang.Integer"));
74 knownImmutables.add(Descriptor.of("java.lang.Long"));
75 knownImmutables.add(Descriptor.of("java.lang.Float"));
76 knownImmutables.add(Descriptor.of("java.lang.Double"));
77 knownImmutables.add(Descriptor.of("java.lang.Boolean"));
78 knownImmutables.add(Descriptor.of("java.lang.Byte"));
79 knownImmutables.add(Descriptor.of("java.lang.Character"));
80 knownImmutables.add(Descriptor.of("java.lang.String"));
81 knownImmutables.add(Descriptor.of("org.sourceforge.jemm.types.JemmDate"));
82 }
83
84
85
86
87
88
89
90
91
92 public Classification classifySingular(CtField field) throws NotFoundException {
93 CtClass type = field.getType();
94 String fieldName = field.getName();
95
96 if(isPrimitive(field))
97 return Classification.PRIMITIVE;
98 if(isJemmCollection(field))
99 return Classification.COLLECTION;
100 else if (fieldName.equals(ShadowTransformation.SHADOW_VARIABLE_NAME)
101 && type.getName().equals(ShadowTransformation.SHADOW_CLASS))
102 return Classification.SHADOW;
103 else if (isKnownImmutable(field))
104 return Classification.KNOWNIMMUTABLE;
105 else if (type.subtypeOf(ClassPoolFactory.getPool().get(JEMMObject.class.getName()))
106 || type.subtypeOf(ClassPoolFactory.getPool().get(JEMMObject.class.getName() + "[]")))
107 return Classification.SUPPORTED;
108 else if (isEntity(field))
109 return Classification.SUPPORTED;
110 return Classification.NORMALOBJECT;
111 }
112
113
114
115
116
117
118 public boolean isEntity(CtField field){
119 Object[] annotations;
120 try {
121 CtClass type = field.getType().isArray() ? field.getType().getComponentType() : field.getType();
122 annotations = type.getAnnotations();
123 } catch (Exception e) {
124 throw new RuntimeException("Couldn't find Entity class, shouldn't be possible");
125 }
126 for(Object each : annotations) {
127 if(Entity.class.isInstance(each))
128 return true;
129 }
130 return false;
131 }
132
133
134
135
136
137
138
139
140
141 public boolean isJemmSpecialField(CtField field) throws NotFoundException {
142 Classification c = classifySingular(field);
143 return c == Classification.COLLECTION || c == Classification.SHADOW;
144 }
145
146
147
148
149
150
151
152 public boolean isJEMMReferenceTransformable(CtField field) throws NotFoundException {
153 Classification c = classifySingular(field);
154 return c == Classification.SUPPORTED && !isArray(field);
155 }
156
157
158
159
160
161
162
163
164
165
166 public boolean isArrayReferenceTransformable(CtField field) throws NotFoundException {
167 Classification c = classifySingular(field);
168 return c == Classification.SUPPORTED && isArray(field);
169 }
170
171
172
173
174
175
176
177 public int arrayDimensions(CtField field) throws NotFoundException {
178 String desc = Descriptor.of(field.getType());
179 return Descriptor.arrayDimension(desc);
180 }
181
182
183
184
185
186
187
188 public boolean isArray(CtField field) throws NotFoundException {
189 return field.getType().isArray();
190 }
191
192
193
194
195
196
197
198
199
200
201 public boolean isJemmCollection(CtField field) throws NotFoundException {
202 String fieldType = underlyingDescriptor(field);
203
204 return jemmClasses.contains(fieldType);
205 }
206
207
208
209
210
211
212
213
214 private String underlyingDescriptor(CtField field) throws NotFoundException {
215 String fieldDesc = Descriptor.of(field.getType());
216
217 int toIgnoreCharacters = arrayDimensions(field);
218 String adjustedDescriptor = fieldDesc.substring(toIgnoreCharacters);
219 return adjustedDescriptor;
220 }
221
222
223
224
225
226
227
228
229
230
231 public boolean isPrimitive(CtField field) throws NotFoundException {
232 String fieldType = underlyingDescriptor(field);
233
234 return primitiveDescriptors.contains(fieldType);
235 }
236
237
238
239
240
241
242
243
244
245
246 public boolean isKnownImmutable(CtField field) throws NotFoundException {
247 String fieldType = underlyingDescriptor(field);
248
249 return knownImmutables.contains(fieldType);
250 }
251 }