By default, empty rows are skipped and so are lines that start with the
// # character. Using # at the beginning of a line indicates a comment.
+// attempt at a CSV spec: http://tools.ietf.org/html/rfc4180
/**
*
Generic class for handling tabular data, typically from a CSV, TSV, or
@@ -62,7 +66,7 @@ import processing.core.PConstants;
*
* @webref data:composite
*/
-public class Table implements Iterable {
+public class Table {
protected int rowCount;
// protected boolean skipEmptyRows = true;
@@ -108,6 +112,8 @@ public class Table implements Iterable {
// double[][] doubleData;
// Object[][] objectData;
+ PApplet sketch;
+
/**
* Creates a new, empty table. Use addRow() to add additional rows.
@@ -119,6 +125,12 @@ public class Table implements Iterable {
}
+ public Table(PApplet parent) {
+ this();
+ this.sketch = parent;
+ }
+
+
public Table(File file) {
this(PApplet.createReader(file));
}
@@ -130,11 +142,17 @@ public class Table implements Iterable {
* @param filename
*/
public Table(PApplet parent, String filename) {
- this(parent.createReader(filename));
+ this.sketch = parent;
+ read(parent.createReader(filename));
}
public Table(BufferedReader reader) {
+ read(reader);
+ }
+
+
+ protected void read(BufferedReader reader) {
columns = new Object[0];
columnTypes = new int[0];
columnCategories = new HashMapBlows[0];
@@ -550,6 +568,272 @@ public class Table implements Iterable {
}
+ // A 'Class' object is used here, so the syntax for this function is:
+ // Table t = loadTable("cars3.tsv", "header");
+ // Record[] records = (Record[]) t.parse(Record.class);
+ // While t.parse("Record") might be nicer, the class is likely to be an
+ // inner class (another tab in a PDE sketch) or even inside a package,
+ // so additional information would be needed to locate it. The name of the
+ // inner class would be "SketchName$Record" which isn't acceptable syntax
+ // to make people use. Better to just introduce the '.class' syntax.
+
+ // Unlike the Table class itself, this accepts char and boolean fields in
+ // the target class, since they're much more prevalent, and don't require
+ // a zillion extra methods and special cases in the rest of the class here.
+
+ // since this is likely an inner class, needs a reference to its parent,
+ // because that's passed to the constructor parameter (inserted by the
+ // compiler) of an inner class by the runtime.
+
+ /** incomplete, do not use */
+ public void parseInto(String fieldName) {
+ Class> target = null;
+ Object outgoing = null;
+ Field targetField = null;
+ try {
+ // Object targetObject,
+ // Class target -> get this from the type of fieldName
+ Class sketchClass = sketch.getClass();
+ targetField = sketchClass.getDeclaredField(fieldName);
+ PApplet.println("found " + targetField);
+ Class targetArray = targetField.getType();
+ if (!targetArray.isArray()) {
+ // fieldName is not an array
+ } else {
+ target = targetArray.getComponentType();
+ outgoing = Array.newInstance(target, getRowCount());
+ }
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ }
+
+ Object enclosingObject = sketch;
+ PApplet.println("enclosing obj is " + enclosingObject);
+ Class enclosingClass = target.getEnclosingClass();
+ Constructor con = null;
+
+ try {
+ if (enclosingClass == null) {
+ con = target.getDeclaredConstructor(); //new Class[] { });
+ PApplet.println("no enclosing class");
+ } else {
+ con = target.getDeclaredConstructor(new Class[] { enclosingClass });
+// con = target.getConstructor(enclosingClass);
+ PApplet.println("enclosed by " + enclosingClass.getName());
+ }
+ if (!con.isAccessible()) {
+ System.out.println("setting constructor to public");
+ con.setAccessible(true);
+ }
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ }
+
+ Field[] fields = target.getDeclaredFields();
+ ArrayList inuse = new ArrayList();
+ for (Field field : fields) {
+ String name = field.getName();
+ if (getColumnIndex(name, false) != -1) {
+ System.out.println("found field " + name);
+ if (!field.isAccessible()) {
+ PApplet.println(" changing field access");
+ field.setAccessible(true);
+ }
+ inuse.add(field);
+ } else {
+ System.out.println("skipping field " + name);
+ }
+ }
+// Constructor[] cons = target.getDeclaredConstructors();
+// //for (Method m : methods) {
+// Constructor defaultCons = null;
+// for (Constructor c : cons) {
+// //System.out.println("found " + c.getParameterTypes());
+// if (c.getParameterTypes().length == 0) {
+// System.out.println("found default");
+// defaultCons = c;
+// c.setAccessible(true);
+// } else {
+// PApplet.println(c.getParameterTypes());
+// }
+// }
+
+ int index = 0;
+// ArrayList