/*
* Author: tdanford
* Date: Aug 20, 2008
*/
package org.seqcode.gseutils.models;
import java.util.*;
import java.awt.Color;
import java.lang.reflect.*;
public class ModelFieldAnalysis<T extends Model> {
protected Class<? extends T> modelClass;
protected Vector<Field> fields;
protected Map<String,Field> staticFields;
/**
* @param cls A Class object that represents a java class which is a subclass of Model.
*/
public ModelFieldAnalysis(Class<? extends T> cls) {
modelClass = cls;
fields = new Vector<Field>();
staticFields = new HashMap<String,Field>();
if(Model.isSubclass(modelClass, Model.class)) {
Field[] fa = modelClass.getFields();
for(int i = 0; i < fa.length; i++) {
Class type = fa[i].getType();
if((fa[i].getModifiers() & Modifier.STATIC) == 0) {
fields.add(fa[i]);
} else {
staticFields.put(fa[i].getName(), fa[i]);
}
}
} else {
String msg = String.format("%s is not a subclass of Model", modelClass.getName());
throw new IllegalArgumentException(msg);
}
}
public Object get(String compositeFieldName, Object value) {
String[] fieldNameArray = compositeFieldName.split("\\.");
for(int i = 0; i < fieldNameArray.length; i++) {
Class valueClass = value.getClass();
String fieldName = fieldNameArray[i];
if(!Model.isSubclass(valueClass, Model.class)) { return null; }
try {
Field field = valueClass.getField(fieldName);
int modifiers = field.getModifiers();
if((modifiers & Modifier.STATIC) != 0) { return null; }
if(field == null) { return null; }
if(value == null) { return null; }
value = field.get(value);
} catch (IllegalAccessException e) {
return null;
} catch (NoSuchFieldException e) {
return null;
}
}
return value;
}
public Class<? extends T> getModelClass() { return modelClass; }
public Vector<Field> getFields() { return fields; }
public boolean getStaticSwitch(String name, boolean defaultValue) {
if(!staticFields.containsKey(name)) { return defaultValue; }
if(!Model.isSubclass(staticFields.get(name).getType(), Boolean.class)) { return defaultValue; }
try {
Boolean val = (Boolean) staticFields.get(name).get(modelClass);
return val;
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new IllegalArgumentException(String.format("Can't access field %s in class %s",
name, modelClass.getSimpleName()));
}
}
public Field[] findFields(String... fieldNames) {
Field[] array = new Field[fieldNames.length];
for(int i = 0; i < fieldNames.length; i++) {
array[i] = findField(fieldNames[i]);
}
return array;
}
public Field findField(String fieldName) {
try {
return modelClass.getField(fieldName);
} catch (SecurityException e) {
return null;
} catch (NoSuchFieldException e) {
return null;
}
}
public Field findStaticField(String fieldName) {
return staticFields.get(fieldName);
}
public Vector<String> getFieldNames() {
Vector<String> fns = new Vector<String>();
for(Field f : fields) {
fns.add(f.getName());
}
return fns;
}
public Field findTypedField(String name, Class c) {
for(int i = 0; i < fields.size(); i++) {
if((fields.get(i).getModifiers() & Modifier.STATIC) == 0) {
Class type = fields.get(i).getType();
if(fields.get(i).getName().equals(name) && Model.isSubclass(type, c)) {
return fields.get(i);
}
}
}
return null;
}
public Vector<Field> findTypedFields(Class c) {
Vector<Field> fs = new Vector<Field>();
for(int i = 0; i < fields.size(); i++) {
if((fields.get(i).getModifiers() & Modifier.STATIC) == 0) {
Class type = fields.get(i).getType();
if(Model.isSubclass(type, c)) {
fs.add(fields.get(i));
}
}
}
return fs;
}
public Vector<Field> findArrayFields() {
Vector<Field> fs = new Vector<Field>();
for(int i = 0; i < fields.size(); i++) {
if((fields.get(i).getModifiers() & Modifier.STATIC) == 0) {
Class type = fields.get(i).getType();
if (type.isArray()) {
fs.add(fields.get(i));
}
}
}
return fs;
}
public Vector<Field> findTypedArrayFields(Class c) {
Vector<Field> fs = new Vector<Field>();
for(int i = 0; i < fields.size(); i++) {
if((fields.get(i).getModifiers() & Modifier.STATIC) == 0) {
Class type = fields.get(i).getType();
if (type.isArray() && Model.isSubclass(type.getComponentType(), c)) {
fs.add(fields.get(i));
}
}
}
return fs;
}
public Vector<Field> foreignKeyFields() {
return findTypedFields(Model.class);
}
public Vector<Field> nonForeignKeyFields() {
Vector<Field> fs = new Vector<Field>();
for(int i = 0; i < fields.size(); i++) {
if((fields.get(i).getModifiers() & Modifier.STATIC) == 0) {
Class type = fields.get(i).getType();
if(!Model.isSubclass(type, Model.class)) {
fs.add(fields.get(i));
}
}
}
return fs;
}
}