package com.google.sitebricks.persist; import javax.inject.Inject; import javax.inject.Singleton; import javax.persistence.Id; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.*; /** * @author dhanji@gmail.com (Dhanji R. Prasanna) */ @Singleton public class EntityMetadata { private final Map<Class<?>, EntityDescriptor> entityClasses; @Inject public EntityMetadata(Set<Class<?>> entityClasses) { this.entityClasses = new HashMap<Class<?>, EntityDescriptor>(); for (Class<?> clazz : entityClasses) { this.entityClasses.put(clazz, new EntityDescriptor(clazz)); } } public EntityDescriptor of(Class<?> clazz) { return entityClasses.get(clazz); } public static class EntityDescriptor { private final String idField; private final Map<String, MemberReader> fields; private final Class<?> entityType; public EntityDescriptor(Class<?> clazz) { String idField = null; this.entityType = clazz; Map<String, MemberReader> fields = new HashMap<String, MemberReader>(); for (Field field : clazz.getDeclaredFields()) { if (Modifier.isTransient(field.getModifiers())) continue; final Field swizzleField = field; final Collection<Annotation> annotations = new ArrayList<Annotation>(); for (Annotation annotation : field.getAnnotations()) { annotations.add(annotation); if (Id.class.isInstance(annotation)) { idField = field.getName(); } } // Look into privates! if (!field.isAccessible()) field.setAccessible(true); fields.put(field.getName(), new MemberReader() { @Override public Object value(Object from) { try { return swizzleField.get(from); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } @Override public Class<?> type() { return swizzleField.getType(); } @Override public Collection<Annotation> annotations() { return annotations; } }); } if (idField == null) throw new IllegalStateException("Entity class missing id field. At least one" + " serializable field must be marked with @Id but none found for: " + clazz.getName()); this.fields = Collections.unmodifiableMap(fields); this.idField = idField; } public Map<String, MemberReader> fields() { return fields; } public String idField() { return idField; } public Class<?> entityType() { return entityType; } } public static interface MemberReader { Object value(Object from); Class<?> type(); public Collection<Annotation> annotations(); } }