package timeflow.format.file; import timeflow.model.*; import timeflow.data.db.*; import timeflow.data.time.*; import timeflow.format.field.*; import timeflow.util.*; import java.io.*; import java.net.URL; import java.util.*; public class TimeflowFormat implements Import, Export { private static final String END_OF_SCHEMA = "#TIMEFLOW\tend-metadata"; private static final String END_OF_METADATA = "#TIMEFLOW\t====== End of Header. Data below is in tab-delimited format. ====="; public ActDB readFile(String fileName, PrintStream messages) throws Exception { return read(new File(fileName), messages); } public static ActDB read(File file, PrintStream out) throws Exception { String text = IO.read(file.getAbsolutePath()); DelimitedText quote = new DelimitedText('\t'); Iterator lines = quote.read(text).iterator(); ActDB db = null; List fieldNames = new ArrayList(); List fieldTypes = new ArrayList(); List fieldSizes = new ArrayList(); String source = "[unknown]", description = ""; for (;;) { String[] t = lines.next(); if (t[1].equals("field")) { fieldNames.add(t[2]); fieldTypes.add(FieldFormatCatalog.javaClass(t[3])); if (t.length > 4) { fieldSizes.add(Integer.parseInt(t[4])); } else { fieldSizes.add(-1); } } else if (t[1].equals("source")) { source = t[2]; } else if (t[1].equals("description")) { description = t[2]; } else if (t[1].equals("end-metadata")) { break; } } db = new ArrayDB((String[]) fieldNames.toArray(new String[0]), (Class[]) fieldTypes.toArray(new Class[0]), source); db.setDescription(description); for (int i = 0; i < fieldNames.size(); i++) { if (fieldSizes.get(i) > 0) { db.getField(fieldNames.get(i)).setRecommendedSize(fieldSizes.get(i)); } } for (;;) { String[] t = lines.next(); if (t[1].startsWith("===")) { break; } if (t[1].equals("alias")) { db.setAlias(db.getField(t[3]), t[2]); } } // note: in some cases headers may be in a different order than in // metadata section, so we will read these. String[] headers = lines.next(); if (headers.length != fieldNames.size()) { throw new IllegalArgumentException("Different number of headers than fields!"); } while (lines.hasNext()) { String[] t = lines.next(); Act a = db.createAct(); for (int i = 0; i < t.length; i++) { Field f = db.getField(headers[i]); FieldFormat format = FieldFormatCatalog.getFormat(f.getType()); a.set(f, format.parse(t[i])); } } return db; } public static void write(ActList acts, BufferedWriter bw) throws IOException { ActDB db = acts.getDB(); PrintWriter out = new PrintWriter(bw); DelimitedText tab = new DelimitedText('\t'); // Write version out.println("#TIMEFLOW\tformat version\t1"); // Write source of data. out.println("#TIMEFLOW\tsource\t" + tab.write(db.getSource())); // Write description of data. out.println("#TIMEFLOW\tdescription\t" + tab.write(db.getDescription())); // Write schema. List fields = db.getFields(); for (Field f : fields) { String recSize = f.getRecommendedSize() <= 0 ? "" : "\t" + f.getRecommendedSize(); out.println("#TIMEFLOW\tfield\t" + tab.write(f.getName()) + "\t" + FieldFormatCatalog.humanName(f.getType()) + recSize); } out.println(END_OF_SCHEMA); // Write column mappings. List aliases = DBUtils.getFieldAliases(db); for (String a : aliases) { out.println("#TIMEFLOW\talias\t" + a + "\t" + tab.write(db.getField(a).getName())); } // Write end of header indicator out.println(END_OF_METADATA); // Write data! new DelimitedFormat('\t').writeDelimited(db, acts, out); out.flush(); out.close(); } public static void main(String[] args) throws Exception { System.out.println("Reading"); ActDB db = read(new File("test/monet.txt"), System.out); System.out.println("# lines: " + db.size()); } @Override public String getName() { return "TimeFlow Format"; } @Override public ActDB importFile(File file) throws Exception { return read(file, System.out); } @Override public void export(TimeflowModel model, BufferedWriter out) throws Exception { write(model.getDB().all(), out); } }