net.java.ao.ReadOnlyEntityProxyFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of activeobjects Show documentation
Show all versions of activeobjects Show documentation
This is the full Active Objects library, if you don't know which one to use, you probably want this one.
package net.java.ao;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.java.ao.schema.FieldNameConverter;
/**
* Factory for building large number of {@link ReadOnlyEntityProxy} instances. Reflectively fetching information
* about the implemented type is expensive and unnecessary to be done more than once.
*
* @author ahennecke
*
* @param the entity type
* @param the primary key type
*/
public class ReadOnlyEntityProxyFactory, K>
{
private final EntityManager entityManager;
private final Class type;
private final Set accessors;
private final Map fieldNames;
private final Map polymorphicFieldNames;
private final Map> returnTypes;
/**
* Cache information about the accessors (can be getters or annotated) and field names.
* All instances built by this factory will make use of this information.
*/
public ReadOnlyEntityProxyFactory(EntityManager entityManager, Class type)
{
this.entityManager = entityManager;
this.type = type;
final FieldNameConverter fieldNameConverter = entityManager.getNameConverters().getFieldNameConverter();
// iterate over the class hierarchy and find the converted field names and accessors.
// this is needed for the getter implementation of the proxy as well as reading/converting the data values
// go through the current interface and all superinterfaces to collect accessor information
Set> types = new HashSet>();
readTypeHierarchy(types, type);
Set accessors = new HashSet();;
Map fieldNames = new HashMap();
Map polymorphicFieldNames = new HashMap();
Map> returnTypes = new HashMap>();
for (Class> search : types)
{
for (Method method : search.getDeclaredMethods()) {
if (Common.isAccessor(method)) {
String fieldName = fieldNameConverter.getName(method);
if (fieldName != null) {
fieldNames.put(method, fieldName);
accessors.add(method);
// figure out if there's a polymorphic annotation and keep track of the respective field name
Class> attributeType = Common.getAttributeTypeFromMethod(method);
if (attributeType != null) {
String polyFieldName = (attributeType.getAnnotation(Polymorphic.class) == null ? null : fieldNameConverter.getPolyTypeName(method));
polymorphicFieldNames.put(fieldName, polyFieldName);
}
// keep track of the return types, so we can use the db field types to convert the values
returnTypes.put(fieldName, method.getReturnType());
}
}
}
}
// create immutable caches which will be shared by ReadOnlyEntityProxy instances
this.accessors = Collections.unmodifiableSet(accessors);
this.fieldNames = Collections.unmodifiableMap(fieldNames);
this.polymorphicFieldNames = Collections.unmodifiableMap(polymorphicFieldNames);
this.returnTypes = Collections.unmodifiableMap(returnTypes);
}
/**
* Recursively read the interface hierarchy of the given AO type interface
*/
private void readTypeHierarchy(Set> types, Class> type)
{
types.add(type);
for (Class> superType : type.getInterfaces())
{
readTypeHierarchy(types, superType);
}
}
/**
* @param primaryKey the primary key object
* @return a new read only proxy instance, using cached class structure information
*/
public ReadOnlyEntityProxy build(K primaryKey) {
return new ReadOnlyEntityProxy(entityManager, type, primaryKey, fieldNames, polymorphicFieldNames, returnTypes, accessors);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy