package edu.berkeley.nlp.util;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/**
* Created by IntelliJ IDEA.
* User: aria42
* Date: Oct 7, 2008
* Time: 1:06:08 PM
*/
public class SmartMapUtils {
/**
* Groups <code>objs</code> by the field <code>field</code>. Tries
* to find public method getField, ignoring case, then to directly
* access the field if that fails.
* @param objs
* @param field
* @return
*/
public static<K,O> Map<K,List<O>> groupBy(Iterable<O> objs, String field) throws Exception {
Class c = objs.iterator().next().getClass();
Method[] methods = c.getDeclaredMethods();
String trgMethName = "get" + field;
Method trgMeth = null;
Field trgField = null;
for (Method m: methods) {
if (m.getName().equalsIgnoreCase(trgMethName)) {
trgMeth = m;
break;
}
}
if (trgMeth == null) {
Field[] fields = c.getDeclaredFields();
for (Field f: fields) {
if (f.getName().equalsIgnoreCase(field)) {
trgField = f;
break;
}
}
}
if (trgMeth == null && trgField == null) {
throw new RuntimeException("Couldn't find field or method to access " + field);
}
Map<K,List<O>> map = new HashMap<K,List<O>>();
for (O obj: objs) {
K key = null;
try {
if (trgMeth != null) {
key = (K) trgMeth.invoke(obj);
} else {
key = (K) trgField.get(obj);
}
} catch (Exception e) { throw new RuntimeException(); }
CollectionUtils.addToValueList(map,key,obj);
}
return map;
}
/**
* Testing Purposes
*/
private static class Person {
public String prefix ;
public String name;
public Person(String name) {
this.name = name;
this.prefix = name.substring(0,3);
}
public String toString() { return "Person(" + name + ")"; }
}
public static void main(String[] args) throws Exception {
List<Person> objs = CollectionUtils.makeList(
new Person("david"),
new Person("davs"),
new Person("maria"),
new Person("marshia")
);
Map<String, List<Person>> grouped = groupBy(objs,"prefix");
System.out.printf("groupd: %s",grouped);
}
}