*
* parentEntity is used to make sure we don't attempt to associate the current
* entity with it's own parent creating an infinte recursion
*/
private Map<String, Object> buildEntityMap(AdaptrexSession session, Object entity, String entityFieldName, String parentEntityPath, Object parentEntity) {
AdaptrexPersistence persistence = session.getPersistence();
Map<String, Object> entityMap = new HashMap<String, Object>();
if (entity == null) {
return entityMap;
}
Class<?> entityClazz = entity.getClass();
boolean isRoot = parentEntityPath.equals("");
String entityPath = parentEntityPath + StringUtilities.capitalize(entityFieldName);
/*
* In order to determine whether or not a field on this entity should be
* included, we need to determine whether it has been explicitly
* included or excluded, or if it's a foreign association, we need to know
* if it's been explicitly included.
*
* The config object contains settings for the entire tree. We want to make
* sure we're only looking at the settings for this node (entity)
*/
List<String> entityIncludes = new ArrayList<String>();
List<String> entityExcludes = new ArrayList<String>();
List<String> entityJoins = new ArrayList<String>();
if (isRoot) {
/*
* Loop each include/exclude/join config and determine if they
* are set for the root entity.
*/
for (String incl : this.config.getIncludes()) {
if (!incl.contains(".")) {
entityIncludes.add(incl);
}
}
for (String excl : this.config.getExcludes()) {
if (!excl.contains(".")) {
entityExcludes.add(excl);
}
}
for (String join : this.config.getAssociationEntityNames()) {
if (!join.contains(".")) {
entityJoins.add(join);
}
}
} else {
/*
* Loop each include/exclude/join config and determine if they are set for
* the current entity at this position in the tree. If the full path to a
* specific field on this entity is set, we want to include it in the entity
* specific config. We only need the field portion when testing against
* the current entity so that gets split out before adding to the list
*/
for (String incl : this.config.getIncludes()) {
if (incl.contains(entityPath + ".")) {
entityIncludes.add(incl.split("\\.")[1]);
}
}
for (String excl : this.config.getExcludes()) {
if (excl.contains(entityPath + ".")) {
entityExcludes.add(excl.split("\\.")[1]);
}
}
for (String join : this.config.getAssociationEntityNames()) {
if (join.contains(entityPath + ".")) {
entityJoins.add(join = join.split("\\.")[1]);
}
}
}
/*
* Loop through fields on our entity and determine if they should be added
*/
for (Field field : entityClazz.getDeclaredFields()) {
/*
* Static fields don't get returned (reveng may add static fields
* to the class)
*/
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
/*
* Get the field name
*/
String fieldName = field.getName();
/*
* Confirm we should be including this field for this entity. ID fields
* get added regardless of whether they are explicitly included.
*
*/
if (!persistence.isIdField(entityClazz, fieldName)) {
if (this.config.getIncludes().size() > 0) {
if (entityIncludes.isEmpty()
|| (!entityIncludes.contains("*") && !entityIncludes.contains(fieldName))) {
continue;
}
}
if (this.config.getExcludes().size() > 0) {
if (entityExcludes.contains("*") || entityExcludes.contains(fieldName)) {
continue;
}
}
}
/*
* Get the field value and make sure it's not this entities parent (prevent infinite recursion)
*/
Object fieldValue = persistence.getFieldValue(entity, fieldName);
if (!isRoot && fieldValue != null && fieldValue.equals(parentEntity)) {
continue;
}
/*
* Process one to many
*/
if (persistence.isOneToMany(entityClazz, fieldName)) {
if (!entityJoins.contains(StringUtilities.capitalize(fieldName))) {
continue;
}
try {
List<Map<String, Object>> associatedData = new ArrayList<Map<String, Object>>();
@SuppressWarnings("unchecked")
List<Object> assocObjList = new ArrayList<Object>((Collection<? extends Object>) fieldValue);
for (Object assocObj : assocObjList) {
/*
* Don't loop back and add our parent entity (prevent infinite recursion)
*/
if (parentEntity != null && assocObj.equals(parentEntity)) {
continue;
}
associatedData.add(buildEntityMap(session, assocObj, fieldName, entityPath, entity));
}
entityMap.put(fieldName, associatedData);
} catch (Exception e) {
log.warn("Error", e);
}
continue;
}
/*
* Process many to one
*/
if (persistence.isManyToOne(entityClazz, fieldName)) {
try {
Method idGetter = fieldValue.getClass().getMethod("getId");
entityMap.put(fieldName + "Id", idGetter.invoke(fieldValue));
} catch (Exception e) {}
if (!entityJoins.contains(StringUtilities.capitalize(fieldName))) {
continue;
}
if (fieldValue == null) {
entityMap.put(fieldName, null);
continue;
}
try {
entityMap.put(fieldName, buildEntityMap(session, fieldValue, fieldName, entityPath, entity));
/*
* We also want the ID of our nested store... Ext should set this
* automatically I think. TODO: Need to customize "id" field
*/
//Method idGetter = fieldValue.getClass().getMethod("getId");
//entityMap.put(fieldName + "Id", idGetter.invoke(fieldValue));
} catch (Exception e) {
log.warn("Error", e);
}
continue;
}
/*
* Process standard fields
*/
try {
if (fieldValue == null) {
entityMap.put(fieldName, null);
continue;
}
String fieldType = persistence.getFieldType(entityClazz, fieldName);
if (fieldType.equals("date")) {
fieldValue = dateFormat.format(fieldValue);
} else if (fieldType.equals("time")) {
fieldValue = timeFormat.format(fieldValue);