/*
* (c) Copyright 2007-2011 by Volker Bergmann. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted under the terms of the
* GNU General Public License.
*
* For redistributing this software or a derivative work under a license other
* than the GPL-compatible Free Software License as defined by the Free
* Software Foundation or approved by OSI, you must first obtain a commercial
* license to this software product from Volker Bergmann.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
* REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
* HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.databene.platform.fixedwidth;
import org.databene.model.data.Entity;
import org.databene.model.data.ComponentAccessor;
import org.databene.document.fixedwidth.FixedWidthColumnDescriptor;
import org.databene.benerator.consumer.TextFileExporter;
import org.databene.commons.*;
import org.databene.commons.converter.AccessingConverter;
import org.databene.commons.converter.ConverterChain;
import org.databene.commons.converter.FormatFormatConverter;
import org.databene.commons.format.Alignment;
import org.databene.commons.format.PadFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.ParsePosition;
import java.text.ParseException;
/**
* Exports Entities to fixed-width files.<br/>
* <br/>
* Created: 26.08.2007 06:17:41
* @author Volker Bergmann
*/
public class FixedWidthEntityExporter extends TextFileExporter {
private static final Logger LOGGER = LoggerFactory.getLogger(FixedWidthEntityExporter.class);
private Converter<Entity, String> converters[];
public FixedWidthEntityExporter() {
this("export.fcw", null);
}
public FixedWidthEntityExporter(String uri, String columnFormatList) {
this(uri, null, columnFormatList);
}
public FixedWidthEntityExporter(String uri, String encoding, String columnFormatList) {
super(uri, encoding, null);
this.uri = uri;
setColumns(columnFormatList);
setDecimalPattern("0.##");
}
// properties ------------------------------------------------------------------------------------------------------
@SuppressWarnings({ "unchecked", "rawtypes" })
public void setColumns(String columnFormatList) {
if (columnFormatList == null) {
converters = null;
return;
}
try {
String[] columnFormats = StringUtil.tokenize(columnFormatList, ',');
this.converters = new Converter[columnFormats.length];
for (int i = 0; i < columnFormats.length; i++) {
String columnFormat = columnFormats[i];
int lbIndex = columnFormat.indexOf('[');
if (lbIndex < 0)
throw new ConfigurationError("'[' expected in column format descriptor '" + columnFormat + "'");
int rbIndex = columnFormat.indexOf(']');
if (rbIndex < 0)
throw new ConfigurationError("']' expected in column format descriptor '" + columnFormat + "'");
String columnName = columnFormat.substring(0, lbIndex);
// parse width
ParsePosition pos = new ParsePosition(lbIndex + 1);
int width = (int) ParseUtil.parseNonNegativeInteger(columnFormat, pos);
// parse fractionDigits
int minFractionDigits = 0;
int maxFractionDigits = 2;
if (pos.getIndex() < rbIndex && columnFormat.charAt(pos.getIndex()) == '.') {
pos.setIndex(pos.getIndex() + 1);
minFractionDigits = (int) ParseUtil.parseNonNegativeInteger(columnFormat, pos);
maxFractionDigits = minFractionDigits;
}
// parse alignment
Alignment alignment = Alignment.LEFT;
if (pos.getIndex() < rbIndex) {
char alignmentCode = columnFormat.charAt(pos.getIndex());
switch (alignmentCode) {
case 'l' : alignment = Alignment.LEFT; break;
case 'r' : alignment = Alignment.RIGHT; break;
case 'c' : alignment = Alignment.CENTER; break;
default: throw new ConfigurationError("Illegal alignment code '" + alignmentCode + "'" +
" in colun format descriptor '" + columnFormat + "'");
}
pos.setIndex(pos.getIndex() + 1);
}
// parse pad char
char padChar = ' ';
if (pos.getIndex() < rbIndex) {
padChar = columnFormat.charAt(pos.getIndex());
pos.setIndex(pos.getIndex() + 1);
}
assert pos.getIndex() == rbIndex;
FixedWidthColumnDescriptor descriptor = new FixedWidthColumnDescriptor(columnName, width, alignment, padChar);
PadFormat format = new PadFormat(descriptor.getWidth(), minFractionDigits, maxFractionDigits, descriptor.getAlignment(), padChar);
ConverterChain<Entity, String> chain = new ConverterChain<Entity, String>();
chain.addComponent(new AccessingConverter<Entity, Object>(Entity.class, Object.class, new ComponentAccessor(descriptor.getName())));
if (format.getMinimumFractionDigits() == 0)
chain.addComponent(plainConverter);
chain.addComponent(new FormatFormatConverter(String.class, format, true));
this.converters[i] = chain;
}
} catch (ParseException e) {
throw new ConfigurationError("Invalid column definition: " + columnFormatList, e);
}
}
// Consumer interface ----------------------------------------------------------------------------------------------
@Override
public void flush() {
if (printer != null)
printer.flush();
}
@Override
public void close() {
IOUtil.close(printer);
}
// Callback methods for TextFileExporter ---------------------------------------------------------------------------
@Override
protected void postInitPrinter(Object object) {
if (this.converters == null)
throw new ConfigurationError("Property 'columns' not set on bean " + getClass().getName());
}
@Override
protected void startConsumingImpl(Object object) {
LOGGER.debug("exporting {}", object);
if (!(object instanceof Entity))
throw new IllegalArgumentException("Expected Entity");
Entity entity = (Entity) object;
for (Converter<Entity, String> converter : converters)
printer.print(converter.convert(entity));
printer.print(lineSeparator);
}
// java.lang.Object overrrides -------------------------------------------------------------------------------------
@Override
public String toString() {
return getClass().getSimpleName() + '[' + ArrayFormat.format() + ']';
}
}