1 package com.thoughtworks.xstream.converters.reflection; 2 3 import java.lang.reflect.Field ; 4 import java.util.Iterator ; 5 import java.util.Map ; 6 import java.util.TreeMap ; 7 8 public class FieldDictionary { 9 10 private static final Map keyedByFieldNameCache = new TreeMap (); 11 private static final Map keyedByFieldKeyCache = new TreeMap (); 12 13 public Iterator serializableFieldsFor(Class cls) { 14 return buildMap(cls, true).values().iterator(); 15 } 16 17 public Field field(Class cls, String name, Class definedIn) { 18 Map fields = buildMap(cls, definedIn != null); 19 Field field = (Field ) fields.get(definedIn != null ? (Object ) new FieldKey(name, definedIn) : (Object ) name); 20 if (field == null) { 21 throw new ObjectAccessException("No such field " + cls.getName() + "." + name); 22 } else { 23 return field; 24 } 25 } 26 27 private Map buildMap(Class cls, boolean tupleKeyed) { 28 final String clsName = cls.getName(); 29 if (!keyedByFieldNameCache.containsKey(clsName)) { 30 final Map keyedByFieldName = new TreeMap (); 31 final Map keyedByFieldKey = new TreeMap (); 32 while (!Object .class.equals(cls)) { 33 Field [] fields = cls.getDeclaredFields(); 34 for (int i = 0; i < fields.length; i++) { 35 Field field = fields[i]; 36 if (field.getName().startsWith("this$")) { 37 continue; 38 } 39 field.setAccessible(true); 40 if (!keyedByFieldName.containsKey(field.getName())) { 41 keyedByFieldName.put(field.getName(), field); 42 } 43 keyedByFieldKey.put(new FieldKey(field.getName(), field.getDeclaringClass()), field); 44 } 45 cls = cls.getSuperclass(); 46 } 47 keyedByFieldNameCache.put(clsName, keyedByFieldName); 48 keyedByFieldKeyCache.put(clsName, keyedByFieldKey); 49 } 50 return (Map ) (tupleKeyed ? keyedByFieldKeyCache.get(clsName) : keyedByFieldNameCache.get(clsName)); 51 } 52 53 private static class FieldKey implements Comparable { 54 private String fieldName; 55 private Class declaringClass; 56 private Integer depth; 57 58 public FieldKey(String fieldName, Class declaringClass) { 59 this.fieldName = fieldName; 60 this.declaringClass = declaringClass; 61 Class c = declaringClass; 62 int i = 0; 63 while (c.getSuperclass() != null) { 64 i++; 65 c = c.getSuperclass(); 66 } 67 depth = new Integer (i); 68 } 69 70 public int compareTo(Object o) { 71 FieldKey t = (FieldKey) o; 72 int result = fieldName.compareTo(t.fieldName); 73 if (result == 0) { 74 result = 0 - depth.compareTo(t.depth); 75 } 76 if (result == 0) { 77 result = declaringClass.getName().compareTo(t.declaringClass.getName()); 78 } 79 return result; 80 } 81 } 82 83 } 84 | Popular Tags |