From: <be...@us...> - 2012-04-16 22:44:55
|
Revision: 440 http://flatpack.svn.sourceforge.net/flatpack/?rev=440&view=rev Author: benoitx Date: 2012-04-16 22:44:49 +0000 (Mon, 16 Apr 2012) Log Message: ----------- Re-org the printHeader or not depending on the way the factory is called. Modified Paths: -------------- trunk/flatpack/src/main/java/net/sf/flatpack/writer/AbstractWriter.java trunk/flatpack/src/main/java/net/sf/flatpack/writer/DelimiterWriter.java trunk/flatpack/src/main/java/net/sf/flatpack/writer/DelimiterWriterFactory.java trunk/flatpack/src/main/java/net/sf/flatpack/writer/FixedLengthWriter.java trunk/flatpack/src/main/java/net/sf/flatpack/writer/Writer.java Added Paths: ----------- trunk/flatpack/src/main/java/net/sf/flatpack/writer/WriterOptions.java Modified: trunk/flatpack/src/main/java/net/sf/flatpack/writer/AbstractWriter.java =================================================================== --- trunk/flatpack/src/main/java/net/sf/flatpack/writer/AbstractWriter.java 2012-04-16 22:42:45 UTC (rev 439) +++ trunk/flatpack/src/main/java/net/sf/flatpack/writer/AbstractWriter.java 2012-04-16 22:44:49 UTC (rev 440) @@ -4,21 +4,14 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.Set; -import net.sf.flatpack.util.FPConstants; - /** * This class encapsulates the writer that's used to output the data. * @author Dirk Holmes and Holger Holger Hoffstatte */ -public abstract class AbstractWriter extends Object implements Writer { +public abstract class AbstractWriter implements Writer { private final BufferedWriter writer; - - private Map rowMap; //used when using column headers - - //the record ID that is currently being written. The default is the DETAIL_ID which are <columns> that are mapped outside of <record> elements - private String recordId = FPConstants.DETAIL_ID; + private Map rowMap; public AbstractWriter(final java.io.Writer output) { super(); @@ -35,20 +28,6 @@ } rowMap.put(columnName, value); } - - //TODO implement writing for no column titles -// public void addRecordEntry(final Object value) { -// if ( -// -// if (rowMap == null) { -// rowMap = new HashMap(); -// } -// -// if (!validateColumnTitle(columnName)) { -// throw new IllegalArgumentException("unknown column: \"" + columnName + "\""); -// } -// rowMap.put(columnName, value); -// } /** * Subclasses must implement this method to perform validation of @@ -71,8 +50,6 @@ // the row should have been written out by the subclass so it's safe to // discard it here rowMap = null; - //default the recordId when we go to the next record - recordId = FPConstants.DETAIL_ID; writer.newLine(); } @@ -101,30 +78,8 @@ writer.flush(); writer.close(); } - protected Map getRowMap() { return rowMap; } - - /** - * @return the recordId - */ - public String getRecordId() { - return recordId; - } - - /** - * Sets the record ID for the record that is being written. This should be used when mapping <record> elements. - * The "id" attribute of the record element should be specified here and needs to be called before calling addRecordEntry(). - * This will throw an exception if addRecordEntry() has been called for the record currently being processed. - * - * @param recordId the recordId to set - */ - public void setRecordId(String recordId) { - if (rowMap != null && !rowMap.isEmpty()) { - throw new RuntimeException("addRecordEntry() has already been called for this row. Please set the record id prior to adding data to this row."); - } - this.recordId = recordId; - } } Modified: trunk/flatpack/src/main/java/net/sf/flatpack/writer/DelimiterWriter.java =================================================================== --- trunk/flatpack/src/main/java/net/sf/flatpack/writer/DelimiterWriter.java 2012-04-16 22:42:45 UTC (rev 439) +++ trunk/flatpack/src/main/java/net/sf/flatpack/writer/DelimiterWriter.java 2012-04-16 22:44:49 UTC (rev 440) @@ -1,14 +1,14 @@ package net.sf.flatpack.writer; import java.io.IOException; -import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.math.BigDecimal; import net.sf.flatpack.structure.ColumnMetaData; import net.sf.flatpack.util.FPConstants; -import net.sf.flatpack.xml.XMLRecordElement; /** * @@ -16,50 +16,29 @@ */ public class DelimiterWriter extends AbstractWriter { private char delimiter; - private char qualifier; - - //private List columnTitles = null; - + private List columnTitles = null; private boolean columnTitlesWritten = false; - - private Map columnMapping; - - private DelimiterWriterOptions writerOptions; - - //this is used when using addRecordEntry() and no column names - private boolean delimitNextEntry = false; protected DelimiterWriter(final Map columnMapping, final java.io.Writer output, final char delimiter, - final char qualifier) throws IOException { - - this(columnMapping, output, delimiter, qualifier, new DelimiterWriterOptions()); - } - - protected DelimiterWriter(final Map columnMapping, - final java.io.Writer output, final char delimiter, - final char qualifier, DelimiterWriterOptions writerOptions) throws IOException { + final char qualifier, + final WriterOptions options) throws IOException { super(output); this.delimiter = delimiter; this.qualifier = qualifier; -// columnTitles = new ArrayList(); -// final List columns = (List) columnMapping.get(FPConstants.DETAIL_ID); -// final Iterator columnIter = columns.iterator(); -// while (columnIter.hasNext()) { -// final ColumnMetaData element = (ColumnMetaData) columnIter.next(); -// columnTitles.add(element.getColName()); -// } - this.columnMapping = columnMapping; - this.writerOptions = writerOptions; - if (!writerOptions.isNoColumnMappings()) { - // write the column headers - this.nextRecord(); - } else { - //flag the headers as written so that we don't try to write them when calling nextRecord() - columnTitlesWritten = true; - } + columnTitles = new ArrayList(); + final List columns = (List) columnMapping.get(FPConstants.DETAIL_ID); + final Iterator columnIter = columns.iterator(); + while (columnIter.hasNext()) { + final ColumnMetaData element = (ColumnMetaData) columnIter.next(); + columnTitles.add(element.getColName()); + } + // write the column headers + if (options.isAutoPrintHeader()) { + printHeader(); + } } protected void writeWithDelimiter(final Object value) throws IOException { @@ -80,7 +59,9 @@ } } - final boolean needsQuoting = stringValue.indexOf(delimiter) != -1 || (qualifier != FPConstants.NO_QUALIFIER && stringValue.indexOf(qualifier) != -1); + final boolean needsQuoting = stringValue.indexOf(delimiter) != -1 + || (qualifier != FPConstants.NO_QUALIFIER && stringValue + .indexOf(qualifier) != -1); if (needsQuoting) { super.write(qualifier); @@ -92,75 +73,18 @@ super.write(qualifier); } } - - public void addRecordEntry(String columnName, Object value) { - if (writerOptions.isNoColumnMappings()) { - throw new UnsupportedOperationException("Column Names Cannot Be Bound To Values When Column Mappings Have Been Turned Off..."); + + protected void addColumnTitle(final String string) { + if (string == null) { + throw new IllegalArgumentException("column title may not be null"); } - super.addRecordEntry(columnName, value); + columnTitles.add(string); } - - /** - * Adds a record entry when not using column names in the file - * - * @param value - * @throws IOException - */ - public void addRecordEntry(Object value) throws IOException{ - if (!writerOptions.isNoColumnMappings()) { - throw new UnsupportedOperationException("Must use addRecordEntry(String,Object) When Using Column Names..."); - } - - if (delimitNextEntry) { - //need to use the super write here. The write in this class will try and qualify the delimiter. - //we also cannot use the writeWithDelimiter() here. It puts the delimiter after the value. We don't - //know the last column to be written so we cannot utilize that here as we did with the mappings - super.write(this.delimiter); - - } - - this.write(value.toString()); - delimitNextEntry = true; - } - //TODO find out if these are needed since the titles can already be added from the Factory -// protected void addColumnTitle(final String string) { -// addColumnTitle(string, FPConstants.DETAIL_ID); -// } -// -// protected void addColumnTitle(final String string, final String recordId) { -// if (string == null) { -// throw new IllegalArgumentException("column title may not be null"); -// } -// List cols = null; -// if (FPConstants.DETAIL_ID.equals(recordId)) { -// //the key for the detail key contains a List in the Map -// cols = (List)this.columnMapping.get(FPConstants.DETAIL_ID); -// if (cols == null) { -// cols = new ArrayList(); -// this.columnMapping.put(FPConstants.DETAIL_ID, cols); -// } -// -// } else { -// //the map contains an XMLRecord element and then the list is contained under that -// XMLRecordElement xmlRec = (XMLRecordElement)this.columnMapping.get(recordId); -// if (xmlRec == null) { -// cols = new ArrayList(); -// xmlRec = new XMLRecordElement(); -// xmlRec.setColumns(cols, null); -// this.columnMapping.put(recordId, xmlRec); -// } else { -// cols = xmlRec.getColumns(); -// } -// } -// -// cols.add(string); -// } - protected void writeColumnTitles() throws IOException { - final Iterator titleIter = ((List)this.columnMapping.get(FPConstants.DETAIL_ID)).iterator(); + final Iterator titleIter = columnTitles.iterator(); while (titleIter.hasNext()) { - final String title = ((ColumnMetaData)titleIter.next()).getColName(); + final String title = (String) titleIter.next(); if (titleIter.hasNext()) { this.writeWithDelimiter(title); @@ -171,15 +95,9 @@ } protected void writeRow() throws IOException { - Iterator titlesIter = null; - if (FPConstants.DETAIL_ID.equals(getRecordId())) { - titlesIter = ((List)this.columnMapping.get(FPConstants.DETAIL_ID)).iterator(); - } else { - final XMLRecordElement xmlRec = (XMLRecordElement)this.columnMapping.get(getRecordId()); - titlesIter = xmlRec.getColumns().iterator(); - } + final Iterator titlesIter = columnTitles.iterator(); while (titlesIter.hasNext()) { - final String columnTitle = ((ColumnMetaData)titlesIter.next()).getColName(); + final String columnTitle = (String) titlesIter.next(); if (getRowMap() != null) { if (titlesIter.hasNext()) { writeWithDelimiter(getRowMap().get(columnTitle)); @@ -189,33 +107,31 @@ } } } - public final void nextRecord() throws IOException { - if (!writerOptions.isNoColumnMappings()) { - if (!columnTitlesWritten) { - this.writeColumnTitles(); - columnTitlesWritten = true; - } else { - this.writeRow(); - } - } - - delimitNextEntry = false; + // if (!columnTitlesWritten) { + // this.writeColumnTitles(); + // columnTitlesWritten = true; + // } else { + this.writeRow(); + // } + super.nextRecord(); } - protected boolean validateColumnTitle(final String columnTitle) { - //return columnTitles.contains(columnTitle); - - //the column index for <record> elements is stored in the Map as the COL_IDX constant_<record id attribute> - final Map columnNameToIndex = (Map) columnMapping - .get(getRecordId().equals(FPConstants.DETAIL_ID) ? FPConstants.COL_IDX : FPConstants.COL_IDX + "_" + getRecordId()); - if (columnNameToIndex == null) { - //TODO this needs to be moved to the AbstractWriter, but the columnMapping is not exposed to it currently - //This should only happen if the getRecordId() contained an invalid record id - throw new RuntimeException("The record ID[" + getRecordId() + "] Is Not Mapped"); + public void printFooter() throws IOException { + // TODO DO: implement footer handling + } + + public void printHeader() throws IOException { + if (!columnTitlesWritten) { + this.writeColumnTitles(); + columnTitlesWritten = true; + super.nextRecord(); } - return columnNameToIndex.keySet().contains(columnTitle); } + + protected boolean validateColumnTitle(final String columnTitle) { + return columnTitles.contains(columnTitle); + } } Modified: trunk/flatpack/src/main/java/net/sf/flatpack/writer/DelimiterWriterFactory.java =================================================================== --- trunk/flatpack/src/main/java/net/sf/flatpack/writer/DelimiterWriterFactory.java 2012-04-16 22:42:45 UTC (rev 439) +++ trunk/flatpack/src/main/java/net/sf/flatpack/writer/DelimiterWriterFactory.java 2012-04-16 22:44:49 UTC (rev 440) @@ -2,14 +2,11 @@ import java.io.IOException; import java.io.Reader; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.flatpack.structure.ColumnMetaData; import net.sf.flatpack.util.FPConstants; -import net.sf.flatpack.xml.XMLRecordElement; import org.jdom.JDOMException; @@ -23,7 +20,6 @@ private final char delimiter; private final char qualifier; - public DelimiterWriterFactory(final char delimiter, final char qualifier) { super(); @@ -66,76 +62,26 @@ public char getQualifier() { return qualifier; } - - public Writer createWriter(final java.io.Writer out) throws IOException { - return createWriter(out, new DelimiterWriterOptions()); - + public Writer createWriter(final java.io.Writer out, final WriterOptions options) throws IOException { + return new DelimiterWriter(this.getColumnMapping(), out, delimiter, qualifier, options); } - - /** - * Create an instance of the DelimterWriter - * - * @param out - * @param delimiterWriterOptions - * Options for Writing - * @return {@link DelimiterWriter} - * @throws IOException - */ - public Writer createWriter(final java.io.Writer out, final DelimiterWriterOptions delimiterWriterOptions) throws IOException { - return new DelimiterWriter(this.getColumnMapping(), out, delimiter, qualifier, delimiterWriterOptions); + + public Writer createWriter(final java.io.Writer out) throws IOException { + return new DelimiterWriter(this.getColumnMapping(), out, delimiter, qualifier, WriterOptions.getInstance()); } - /** - * Add column titles for mapping. This can be done in lieu of using an XML Mapping. This needs to be done before calling createWriter() - * - * @param columnTitle - * @param recordId - */ - public void addColumnTitle(final String columnTitle, final String recordId) { - final String colIdxKey = FPConstants.DETAIL_ID.equals(recordId) ? FPConstants.COL_IDX : FPConstants.COL_IDX + "_" + recordId; + // TODO DO: check that no column titles can be added after first nextRecord + public void addColumnTitle(final String columnTitle) { final Map columnMapping = this.getColumnMapping(); - List columnMetaDatas = null; - if (FPConstants.DETAIL_ID.equals(recordId)) { - //the detail record will always be there. It is being setup by the AbstractWriter if it - //is not coming off of the XML - columnMetaDatas = (List) columnMapping.get(FPConstants.DETAIL_ID); - } else { - //this has a XMLRecord in the map, for anything other than the detail id - XMLRecordElement xmlRec = (XMLRecordElement)columnMapping.get(recordId); - if (xmlRec == null) { - columnMetaDatas = new ArrayList(); - xmlRec = new XMLRecordElement(); - xmlRec.setColumns(columnMetaDatas, null); - columnMapping.put(recordId, xmlRec); - } else { - columnMetaDatas = xmlRec.getColumns(); - } - } - - Map columnIndices = (Map) columnMapping.get(colIdxKey); - if (columnIndices == null) { - columnIndices = new HashMap(); - columnMapping.put(recordId, columnIndices); - } + final List columnMetaDatas = (List) columnMapping.get(FPConstants.DETAIL_ID); + final Map columnIndices = (Map) columnMapping.get(FPConstants.COL_IDX); final ColumnMetaData metaData = new ColumnMetaData(); metaData.setColName(columnTitle); columnMetaDatas.add(metaData); final Integer columnIndex = Integer.valueOf(columnMetaDatas.indexOf(metaData)); - columnIndices.put(columnTitle, columnIndex); + columnIndices.put(columnIndex, columnTitle); } - - /** - * Add column titles for mapping. This can be done in lieu of using an XML Mapping. This needs to be done before calling createWriter() - * - * @param string - */ - public void addColumnTitle(final String string) { - addColumnTitle(string, FPConstants.DETAIL_ID); - } - - - } Modified: trunk/flatpack/src/main/java/net/sf/flatpack/writer/FixedLengthWriter.java =================================================================== --- trunk/flatpack/src/main/java/net/sf/flatpack/writer/FixedLengthWriter.java 2012-04-16 22:42:45 UTC (rev 439) +++ trunk/flatpack/src/main/java/net/sf/flatpack/writer/FixedLengthWriter.java 2012-04-16 22:44:49 UTC (rev 440) @@ -9,7 +9,6 @@ import net.sf.flatpack.structure.ColumnMetaData; import net.sf.flatpack.util.FPConstants; -import net.sf.flatpack.xml.XMLRecordElement; /** * @@ -97,27 +96,27 @@ } protected boolean validateColumnTitle(final String columnTitle) { - //the column index for <record> elements is stored in the Map as the COL_IDX constant_<record id attribute> final Map columnNameToIndex = (Map) columnMapping - .get(getRecordId().equals(FPConstants.DETAIL_ID) ? FPConstants.COL_IDX : FPConstants.COL_IDX + "_" + getRecordId()); - if (columnNameToIndex == null) { - //TODO this needs to be moved to the AbstractWriter, but the columnMapping is not exposed to it currently - //This should only happen if the getRecordId() contained an invalid record id - throw new RuntimeException("The record ID[" + getRecordId() + "] Is Not Mapped"); - } + .get(FPConstants.COL_IDX); return columnNameToIndex.keySet().contains(columnTitle); } + public void printFooter() { + // TODO DO: implement footer handling + + } + + public void printHeader() { + // TODO DO: implement header handling + + } + /** * @return List of ColumnMetaData objects describing the mapping defined in * the XML file. */ private List getColumnMetaData() { - if (getRecordId().equals(FPConstants.DETAIL_ID)) { - return (List) columnMapping.get(getRecordId()); - } - - return ((XMLRecordElement)columnMapping.get(getRecordId())).getColumns(); + return (List) columnMapping.get(FPConstants.DETAIL_ID); } private ColumnMetaData getColumnMetaData(final String columnName) { @@ -129,7 +128,7 @@ } } - throw new IllegalArgumentException("Record ID[" + getRecordId() + "] Column \"" + columnName + throw new IllegalArgumentException("Column \"" + columnName + "\" unknown"); } } Modified: trunk/flatpack/src/main/java/net/sf/flatpack/writer/Writer.java =================================================================== --- trunk/flatpack/src/main/java/net/sf/flatpack/writer/Writer.java 2012-04-16 22:42:45 UTC (rev 439) +++ trunk/flatpack/src/main/java/net/sf/flatpack/writer/Writer.java 2012-04-16 22:44:49 UTC (rev 440) @@ -7,21 +7,17 @@ * @author Dirk Holmes and Holger Holger Hoffstatte */ public interface Writer { + /** Export header */ + void printHeader() throws IOException; - void addRecordEntry(String columnName, Object value); + /** Export footer */ + void printFooter() throws IOException; + void addRecordEntry(String columnName, Object value); + void nextRecord() throws IOException; void flush() throws IOException; void close() throws IOException; - - /** - * Sets the record ID for the record that is being written. This should be used when mapping <record> elements. - * The "id" attribute of the record element should be specified here and needs to be called before calling addRecordEntry(). - * This will throw an exception if addRecordEntry() has been called for the record currently being processed. - * - * @param recordId the recordId to set - */ - void setRecordId(String recordId); } Copied: trunk/flatpack/src/main/java/net/sf/flatpack/writer/WriterOptions.java (from rev 436, trunk/flatpack/src/main/java/net/sf/flatpack/writer/DelimiterWriterOptions.java) =================================================================== --- trunk/flatpack/src/main/java/net/sf/flatpack/writer/WriterOptions.java (rev 0) +++ trunk/flatpack/src/main/java/net/sf/flatpack/writer/WriterOptions.java 2012-04-16 22:44:49 UTC (rev 440) @@ -0,0 +1,45 @@ +package net.sf.flatpack.writer; + +/** + * Defines options for various Writer behaviours + * + * @author Paul Zepernick + */ +public class WriterOptions { + + private boolean autoPrintHeader = true; + + + + /** + * Returns a DelimiterWriterOptions instance + * + * @return DelimiterWriterOptions + */ + public static WriterOptions getInstance() { + return new WriterOptions(); + } + + + + /** + * @return the noColumnMappings + */ + public boolean isAutoPrintHeader() { + return autoPrintHeader; + } + + + + /** + * When this is set to true, the addRecordEntry(column, value) will throw an exception. You + * must use addRecordEntry(value). + * + * @param noColumnMappings the noColumnMappings to set + */ + public WriterOptions autoPrintHeader(boolean autoPrintHeader) { + this.autoPrintHeader = autoPrintHeader; + return this; + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |