package timeflow.data.db; import java.net.URL; import java.util.*; import timeflow.data.db.filter.*; import timeflow.data.time.*; public class ArrayDB implements ActDB { private Schema schema; private List data = new ArrayList(); private Field[] fields; private String source = "[unknown]"; private String description = ""; public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getSource() { return source; } public void setSource(String source) { this.source = source; } @Override public void setAlias(Field field, String name) { schema.addAlias(field, name); } public ArrayDB(String[] fieldNames, Class[] types, String source) { this.schema = new Schema(); this.source = source; int n = fieldNames.length; fields = new Field[n]; for (int i = 0; i < n; i++) { fields[i] = schema.add(fieldNames[i], types[i]); fields[i].index = i; } } public Field[] getFieldArray() { return fields; } @Override public Field addField(String name, Class type) { int n = fields.length; // make new Field. Field field = new Field(name, type); field.index = n; // make new array of fields. Field[] moreFields = new Field[n + 1]; System.arraycopy(fields, 0, moreFields, 0, n); moreFields[n] = field; this.fields = moreFields; // go through all the data items and expand their arrays, too. for (Act d : data) { IndexedAct item = (IndexedAct) d; Object[] old = item.data; item.data = new Object[n + 1]; System.arraycopy(old, 0, item.data, 0, n); } //System.out.println("Field added: "+field); schema.add(field); return field; } public Field getField(String name) { return schema.getField(name); } @Override public ActList all() { return select(null); } @Override public Act createAct() { IndexedAct act = new IndexedAct(this, fields.length); data.add(act); return act; } @Override public void delete(Act act) { data.remove(act); } @Override public void deleteField(Field deadField) { System.out.println("Deleting: " + deadField); schema.delete(deadField); int n = fields.length; int m = deadField.index; // make new array of fields. Field[] fewerFields = new Field[n - 1]; removeItem(fields, fewerFields, m); fields = fewerFields; // go through all the data items and contract their arrays, too. for (Act d : data) { IndexedAct item = (IndexedAct) d; Object[] old = item.data; item.data = new Object[n - 1]; removeItem(old, item.data, m); } // change field indices for (int i = 0; i < fields.length; i++) { System.out.println("fields[" + i + "]=" + fields[i]); if (fields[i].index > deadField.index) { fields[i].index--; } } } private static void removeItem(Object[] a, Object[] b, int m) { int n = a.length; if (m > 0) { System.arraycopy(a, 0, b, 0, m); } if (m < n - 1) { System.arraycopy(a, m + 1, b, m, n - m - 1); } } @Override public List getFields(Class type) { return schema.getFields(type); } @Override public ActList select(ActFilter filter) { ActList set = new ActList(this); for (Act a : data) { if (filter == null || filter.accept(a)) { set.add(a); } } return set; } @Override public List getFields() { return schema.getFields(); } @Override public Act get(int i) { return data.get(i); } @Override public int size() { return data.size(); } @Override public Iterator iterator() { return data.iterator(); } @Override public List getFieldKeys() { return schema.getKeys(); } @Override public void setNewFieldOrder(List newOrder) { schema.setNewFieldOrder(newOrder); } class IndexedAct implements Act { Object[] data; ActDB db; IndexedAct(ActDB db, int numFields) { this.db = db; data = new Object[numFields]; } @Override public String getString(Field field) { Object obj = data[field.index]; if (obj == null) return null; if (obj instanceof String[]) { String[] strings = (String[]) obj; String string = ""; for (String s : strings) { string += s + ", "; } return string; } else { return obj.toString(); } } public void setText(Field field, String text) { data[field.index] = text; } @Override public String[] getTextList(Field field) { Object obj = data[field.index]; if (obj == null) return null; if (obj instanceof String[]) { return (String[]) obj; } else { return new String[] { obj.toString() }; } } public void setTextList(Field field, String[] list) { data[field.index] = list; } @Override public double getValue(Field field) { Double d = (Double) data[field.index]; return d == null ? Double.NaN : d.doubleValue(); } public void setValue(Field field, double value) { data[field.index] = value; } @Override public Object get(Field field) { return data[field.index]; } @Override public ActDB getDB() { return db; } @Override public void set(Field field, Object value) { data[field.index] = value; } @Override public RoughTime getTime(Field field) { return (RoughTime) data[field.index]; } @Override public void setTime(Field field, RoughTime time) { data[field.index] = time; } @Override public URL getURL(Field field) { return (URL) data[field.index]; } @Override public void setURL(Field field, URL url) { data[field.index] = url; } } @Override public void renameField(Field field, String name) { schema.renameField(field, name); } }