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<String[]> lines=quote.read(text).iterator();
ActDB db=null;
List<String> fieldNames=new ArrayList<String>();
List<Class> fieldTypes=new ArrayList<Class>();
List<Integer> fieldSizes=new ArrayList<Integer>();
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<Field> 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<String> 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(TFModel model, BufferedWriter out) throws Exception {
write(model.getDB().all(), out);
}
}