/src/g6/db/FastMapper.java

https://bitbucket.org/yangibaev/g6 · Java · 188 lines · 157 code · 31 blank · 0 comment · 38 complexity · 94d7d08b19208611c7609eb88029bcd8 MD5 · raw file

  1. package g6.db;
  2. import java.beans.BeanInfo;
  3. import java.beans.Introspector;
  4. import java.beans.PropertyDescriptor;
  5. import java.lang.reflect.Field;
  6. import java.lang.reflect.Method;
  7. import java.lang.reflect.ParameterizedType;
  8. import java.lang.reflect.Type;
  9. import java.util.ArrayList;
  10. import java.util.List;
  11. import java.util.concurrent.ConcurrentHashMap;
  12. import com.mongodb.BasicDBList;
  13. import com.mongodb.BasicDBObject;
  14. import net.sf.cglib.reflect.FastClass;
  15. import com.mongodb.DBObject;
  16. import org.bson.types.ObjectId;
  17. public class FastMapper implements IMapper {
  18. private ConcurrentHashMap<Class, FastBean> _cache = new ConcurrentHashMap<Class, FastBean>();
  19. private FastBean getFastBeanForClass(Class clazz) {
  20. FastBean result = _cache.get(clazz);
  21. if (result == null) {
  22. try {
  23. String idFieldName = null;
  24. for (Field field : clazz.getDeclaredFields()) {
  25. if (field.isAnnotationPresent(Id.class)) {
  26. idFieldName = field.getName();
  27. if (idFieldName.indexOf("_") == 0) {
  28. idFieldName = idFieldName.substring(1);
  29. }
  30. break;
  31. }
  32. }
  33. FastClass fastClass = FastClass.create(clazz);
  34. BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
  35. PropertyDescriptor[] propertyDescriptors = beanInfo
  36. .getPropertyDescriptors();
  37. ArrayList<FieldAccessor> writeAccessors = new ArrayList<FieldAccessor>();
  38. ArrayList<FieldAccessor> readAccessors = new ArrayList<FieldAccessor>();
  39. for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
  40. if (isPersistent(propertyDescriptor)) {
  41. String propertyName = propertyDescriptor.getName();
  42. boolean isIdField = propertyName.equals(idFieldName);
  43. Type genericParamType = null;
  44. Type genericType = propertyDescriptor.getReadMethod().getGenericReturnType();
  45. if (genericType instanceof ParameterizedType) {
  46. genericParamType = ((ParameterizedType) genericType).getActualTypeArguments()[0];
  47. if (isBuiltinType(genericParamType)) {
  48. genericParamType = null;
  49. }
  50. }
  51. Method writeMethod = propertyDescriptor
  52. .getWriteMethod();
  53. Class<?> propertyType = propertyDescriptor.getPropertyType();
  54. boolean isBuiltinType = isBuiltinType(propertyType);
  55. writeAccessors.add(new FieldAccessor(fastClass
  56. .getMethod(writeMethod), propertyName, propertyType, genericParamType, isBuiltinType, isIdField));
  57. Method readMethod = propertyDescriptor.getReadMethod();
  58. readAccessors.add(new FieldAccessor(fastClass
  59. .getMethod(readMethod), propertyName, propertyType, genericParamType, isBuiltinType, isIdField));
  60. }
  61. }
  62. result = new FastBean(
  63. readAccessors.toArray(new FieldAccessor[]{}),
  64. writeAccessors.toArray(new FieldAccessor[]{}));
  65. _cache.put(clazz, result);
  66. } catch (Exception e) {
  67. throw new RuntimeException(e);
  68. }
  69. }
  70. return result;
  71. }
  72. private boolean isPersistent(PropertyDescriptor propertyDescriptor) {
  73. return !propertyDescriptor.getName().equals("class")
  74. && propertyDescriptor.getWriteMethod() != null;
  75. }
  76. private boolean isBuiltinType(Type type) {
  77. return type.equals(String.class) ||
  78. type.equals(Long.class) ||
  79. type.equals(Integer.class) ||
  80. type.equals(Byte.class) ||
  81. type.equals(Short.class) ||
  82. type.equals(Float.class) ||
  83. type.equals(Double.class) ||
  84. type.equals(Character.class) ||
  85. type.equals(Boolean.class)||
  86. type.equals(DBObject.class)||
  87. type.equals(ObjectId.class);
  88. }
  89. @Override
  90. public void toPojo(DBObject dbObject, Object object) {
  91. try {
  92. Object valueFromDB = null;
  93. for (FieldAccessor fieldAccesor : getFastBeanForClass(object
  94. .getClass()).writeAccessors) {
  95. if (fieldAccesor.isIdField) {
  96. valueFromDB = dbObject.get("_id");
  97. } else {
  98. valueFromDB = dbObject.get(fieldAccesor.name);
  99. if (valueFromDB != null) {
  100. if (valueFromDB instanceof List && fieldAccesor.genericType != null) {
  101. List dbList = (BasicDBList) dbObject.get(fieldAccesor.name);
  102. ArrayList pojoList = new ArrayList();
  103. for (Object item : dbList) {
  104. Object pojoItem = ((Class) fieldAccesor.genericType).newInstance();
  105. toPojo((DBObject) item, pojoItem);
  106. pojoList.add(pojoItem);
  107. }
  108. valueFromDB = pojoList;
  109. } else if (!fieldAccesor.isBuiltinType && !(valueFromDB instanceof List)) {
  110. Object nestedPojo = fieldAccesor.fieldType.newInstance();
  111. toPojo((DBObject) valueFromDB, nestedPojo);
  112. valueFromDB = nestedPojo;
  113. }
  114. }
  115. }
  116. fieldAccesor.method.invoke(object, new Object[]{valueFromDB});
  117. }
  118. } catch (Exception e) {
  119. throw new RuntimeException(e);
  120. }
  121. }
  122. @Override
  123. public void fromPojo(Object object, DBObject dbObject) {
  124. try {
  125. for (FieldAccessor fieldAccesor : getFastBeanForClass(object
  126. .getClass()).readAccessors) {
  127. Object fieldValue = fieldAccesor.method.invoke(object, null);
  128. if (fieldValue != null) {
  129. if (fieldAccesor.isIdField) {
  130. dbObject.put("_id", fieldValue);
  131. } else {
  132. if (fieldValue instanceof List && fieldAccesor.genericType != null) {
  133. ArrayList sourceList = (ArrayList) fieldValue;
  134. BasicDBList dbList = new BasicDBList();
  135. for (Object item : sourceList) {
  136. DBObject dbItem = new BasicDBObject();
  137. fromPojo(item, dbItem);
  138. dbList.add(dbItem);
  139. }
  140. dbObject.put(fieldAccesor.name, dbList);
  141. } else if (!fieldAccesor.isBuiltinType && !(fieldValue instanceof List)) {
  142. DBObject dbObject2 = new BasicDBObject();
  143. fromPojo(fieldValue, dbObject2);
  144. dbObject.put(fieldAccesor.name, dbObject2);
  145. } else {
  146. dbObject.put(fieldAccesor.name, fieldValue);
  147. }
  148. }
  149. } else {
  150. dbObject.put(fieldAccesor.name, null);
  151. }
  152. }
  153. } catch (Exception e) {
  154. throw new RuntimeException(e);
  155. }
  156. }
  157. }