package org.reldb.rel.v0.storage.relvars.external.csv; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import org.reldb.rel.exceptions.ExceptionSemantic; import org.reldb.rel.v0.generator.Generator; import org.reldb.rel.v0.storage.RelDatabase; import org.reldb.rel.v0.storage.relvars.RelvarCustomMetadata; import org.reldb.rel.v0.storage.relvars.RelvarExternal; import org.reldb.rel.v0.storage.relvars.RelvarGlobal; import org.reldb.rel.v0.storage.relvars.RelvarHeading; import org.reldb.rel.v0.storage.relvars.external.CSVLineParse; import org.reldb.rel.v0.storage.relvars.external.ColumnName; import org.reldb.rel.v0.storage.tables.TableExternal.DuplicateHandling; import org.reldb.rel.v0.types.Heading; import org.reldb.rel.v0.types.builtin.TypeCharacter; import org.reldb.rel.v0.types.builtin.TypeInteger; public class RelvarCSVMetadata extends RelvarCustomMetadata { public static final long serialVersionUID = 0; private String path; private DuplicateHandling duplicates; public static class CSVSpec { String filePath; boolean hasHeading = true; } public static CSVSpec obtainCSVSpec(String path) { String[] splitPath = CSVLineParse.parseTrimmed(path); CSVSpec spec = new CSVSpec(); spec.filePath = splitPath[0].trim(); for (int index = 1; index < splitPath.length; index++) { String part = splitPath[index].trim(); if (part.compareToIgnoreCase("NOHEADING") == 0) spec.hasHeading = false; else throw new ExceptionSemantic("RS0469: Invalid CSV file specification '" + part + "'."); } return spec; } private static String readFirstLineOfCSV(String path) { File f = new File(path); if (f.exists()) { BufferedReader br = null; try { String sCurrentLine; br = new BufferedReader(new FileReader(f)); sCurrentLine = br.readLine(); br.close(); // replaceAll to filter out Byte Order Mark (BOM), if present return (sCurrentLine != null) ? sCurrentLine.replaceAll("\ufeff", " ") : null; } catch (IOException e) { e.printStackTrace(); return null; } } else throw new ExceptionSemantic("EX0001: File not found at: " + path); } public static RelvarHeading getHeadingFromCSV(String path, DuplicateHandling duplicates) { CSVSpec spec = obtainCSVSpec(path); Heading heading = new Heading(); String firstLine = null; if (duplicates == DuplicateHandling.DUP_COUNT) heading.add("_DUP_COUNT", TypeInteger.getInstance()); else if (duplicates == DuplicateHandling.AUTOKEY) heading.add("_AUTOKEY", TypeInteger.getInstance()); firstLine = readFirstLineOfCSV(spec.filePath); String[] columns = null; if (firstLine != null) { columns = CSVLineParse.parse(firstLine); int blankCount = 0; if (spec.hasHeading) for (String column: columns) { String columnName = ColumnName.cleanName(column); if (columnName.length() == 0) columnName = "BLANK" + ++blankCount; heading.add(columnName, TypeCharacter.getInstance()); } else for (int i=0; i<columns.length; i++) heading.add("COLUMN" + ++blankCount, TypeCharacter.getInstance()); } return new RelvarHeading(heading); } public RelvarCSVMetadata(RelDatabase database, String owner, String path, DuplicateHandling duplicates) { super(database, getHeadingFromCSV(path, duplicates), owner); this.path = path; this.duplicates = duplicates; } @Override public String getSourceDefinition() { return "EXTERNAL CSV \"" + path.replace('\\', '/') + "\" " + duplicates; } @Override public RelvarGlobal getRelvar(String name, RelDatabase database) { CSVSpec spec = obtainCSVSpec(path); File file = new File(spec.filePath); if (!file.exists()) throw new ExceptionSemantic("EX0002: File at " + path + " not found."); return new RelvarExternal(name, database, new Generator(database, System.out), this, duplicates); } @Override public void dropRelvar(RelDatabase database) { } public String getPath() { return path; } @Override public String tableClassName() { return "TableCSV"; } @Override public String getType() { return "CSV"; } }