/**
* Translates a List of maps into a normailzed structure. Choose any number
* of column names and pass them in as an array. The result will be an object
* graph grouped in the same order as the order of the column names passed in.
* Each parent is a map with an element called "child" that holds a List of
* Maps which in turn have their own child list. An added feature is that the
* root holds the sum of its children on each level in a key called
* 'numChildLevels*'. Just substitute an integer for the *.
*
* This is most often used for reports. This allow you to get all the data
* with one call and then create the structure you need. This saves
* potentially hundreds of database calls while recursing.
*/
public static List normalizeListOfMaps(List dataList, String[] colHeaders){
List focus = null;
List lastRowVals = new ArrayList(
colHeaders.length);
List childList = null;
Map currRow = null;
Map lastRow = null;
Map rootMap = null;
int n = 0;
String key = null;
String curr = null;
String last = null;
// The focus holds a reference to the active parent at each level.
List[] focusLevel = new List[colHeaders.length];
focusLevel[0] = new ArrayList();
Iterator i = dataList.iterator();
while (i.hasNext()) {
currRow= (Map) i.next();
for (n = 0; n < colHeaders.length; n++) {
key = (String) colHeaders[n];
curr = (String) currRow.get(key);
if (lastRow != null)
last = (String)
lastRow.get(key);
if (last == null || !curr.equals(last)) {
if (n == 0) {
rootMap = currRow;
}
focus = focusLevel[n];
focus.add(currRow);
// Keep a sum of all the levels in each root record.
Integer sum = (Integer)
rootMap.get("numChildLevels" + (n));
if (sum != null)
rootMap.put("numChildLevels" + (n), new Integer(sum.intValue() + 1));
else
rootMap.put("numChildLevels" + (n), new Integer(1));
// When not a leaf node.
if (n < colHeaders.length - 1) {
childList = new ArrayList();
focusLevel[n+1] = childList;
currRow.put("child",childList);
// Create a copy so it can have its own child pointer.
currRow = new HashMap(currRow);
}
}
}
lastRow = currRow;
}
return focusLevel[0];
}