/**
*
*/
package org.commcare.android.database;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Vector;
import org.commcare.android.storage.framework.MetaField;
import org.commcare.android.storage.framework.Table;
import org.javarosa.core.services.storage.IMetaData;
import org.javarosa.core.services.storage.Persistable;
import android.util.Pair;
/**
* @author ctsims
*
*/
public class TableBuilder {
private String name;
private Class c;
private Vector<String> cols;
private Vector<String> rawCols;
public TableBuilder(Class c) {
this.c = c;
Table t = (Table)c.getAnnotation(Table.class);
this.name = t.value();
cols = new Vector<String>();
rawCols = new Vector<String>();
addData(c);
}
public void addData(Class c) {
cols.add(DbUtil.ID_COL + " INTEGER PRIMARY KEY");
rawCols.add(DbUtil.ID_COL);
for(Field f : c.getDeclaredFields()) {
if(f.isAnnotationPresent(MetaField.class)) {
MetaField mf = f.getAnnotation(MetaField.class);
addMetaField(mf);
}
}
for(Method m : c.getDeclaredMethods()) {
if(m.isAnnotationPresent(MetaField.class)) {
MetaField mf = m.getAnnotation(MetaField.class);
addMetaField(mf);
}
}
cols.add(DbUtil.DATA_COL + " BLOB");
rawCols.add(DbUtil.DATA_COL);
}
private void addMetaField(MetaField mf) {
String key = mf.value();
String columnName = scrubName(key);
rawCols.add(columnName);
String columnDef;
columnDef = columnName;
//Modifiers
if(unique.contains(columnName) || mf.unique()) {
columnDef += " UNIQUE";
}
cols.add(columnDef);
}
//Option Two - For models not made natively
public TableBuilder(String name) {
this.name = name;
cols = new Vector<String>();
rawCols = new Vector<String>();
}
public void addData(Persistable p) {
cols.add(DbUtil.ID_COL + " INTEGER PRIMARY KEY");
rawCols.add(DbUtil.ID_COL);
if(p instanceof IMetaData) {
String[] keys = ((IMetaData)p).getMetaDataFields();
for(String key : keys) {
String columnName = scrubName(key);
rawCols.add(columnName);
String columnDef = columnName;
//Modifiers
if(unique.contains(columnName)) {
columnDef += " UNIQUE";
}
cols.add(columnDef);
}
}
cols.add(DbUtil.DATA_COL + " BLOB");
rawCols.add(DbUtil.DATA_COL);
}
HashSet<String> unique = new HashSet<String>();
public void setUnique(String columnName) {
unique.add(scrubName(columnName));
}
public String getTableCreateString() {
String built = "CREATE TABLE " + scrubName(name) + " (";
for(int i = 0 ; i < cols.size() ; ++i) {
built += cols.elementAt(i);
if(i < cols.size() - 1) {
built += ",";
}
}
built += ");";
return built;
}
public static String scrubName(String input) {
//Scrub
return input.replace("-", "_");
}
//TODO: Read this from SQL, not assume from context
private static final int MAX_SQL_ARGS = 950;
public static List<Pair<String, String[]>> sqlList(List<Integer> input) {
return sqlList(input, MAX_SQL_ARGS);
}
public static List<Pair<String, String[]>> sqlList(List<Integer> input, int maxArgs) {
List<Pair<String, String[]>> ops = new ArrayList<Pair<String, String[]>>();
//figure out how many iterations we'll need
int numIterations = (int)Math.ceil(((double)input.size()) / maxArgs);
for(int currentRound = 0 ; currentRound < numIterations ; ++currentRound) {
int startPoint = currentRound * maxArgs;
int lastIndex = Math.min((currentRound + 1) * maxArgs, input.size());
String ret = "(";
for(int i = startPoint ; i < lastIndex ; ++i) {
ret += "?" + ",";
}
String[] array = new String[lastIndex - startPoint];
int count = 0 ;
for(int i = startPoint ; i < lastIndex ; ++i) {
array[count++] = String.valueOf(input.get(i));
}
ops.add(new Pair<String, String[]>(ret.substring(0, ret.length()-1) + ")", array));
}
return ops;
}
public String getColumns() {
String columns = "";
for(int i = 0 ; i < rawCols.size() ; ++i) {
columns += rawCols.elementAt(i);
if(i < rawCols.size() - 1) {
columns += ",";
}
}
return columns;
}
}