1 /** 2 * ServingXML 3 * 4 * Copyright (C) 2006 Daniel Parker 5 * daniel.parker@servingxml.com 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 **/ 20 21 package com.servingxml.components.flatfile.layout; 22 23 import java.io.BufferedWriter; 24 import java.io.OutputStreamWriter; 25 import java.io.Writer; 26 27 import com.servingxml.app.ServiceContext; 28 import com.servingxml.util.ServingXmlException; 29 import com.servingxml.util.Name; 30 import com.servingxml.app.Flow; 31 import com.servingxml.components.recordio.RecordWriter; 32 import com.servingxml.components.recordio.AbstractRecordWriter; 33 import com.servingxml.io.streamsink.StreamSink; 34 import com.servingxml.components.streamsink.StreamSinkFactory; 35 import com.servingxml.util.record.Record; 36 import com.servingxml.util.record.Value; 37 import com.servingxml.util.record.FieldType; 38 import com.servingxml.components.quotesymbol.QuoteSymbol; 39 import com.servingxml.components.flatfile.options.Delimiter; 40 41 /** 42 * 43 * 44 * @author Daniel A. Parker 45 */ 46 47 public class DefaultFlatFileWriter extends AbstractRecordWriter implements RecordWriter { 48 private final StreamSinkFactory sinkFactory; 49 private final Delimiter fieldDelimiter; 50 private final Delimiter recordDelimiter; 51 private final QuoteSymbol quoteSymbol; 52 private StreamSink sink = null; 53 private int row; 54 private Writer writer = null; 55 private final StringBuilder buf; 56 DefaultFlatFileWriter(StreamSinkFactory sinkFactory, Delimiter fieldDelimiter, Delimiter recordDelimiter, QuoteSymbol quoteSymbol)57 public DefaultFlatFileWriter(StreamSinkFactory sinkFactory, Delimiter fieldDelimiter, 58 Delimiter recordDelimiter, QuoteSymbol quoteSymbol) { 59 this.sinkFactory = sinkFactory; 60 this.fieldDelimiter = fieldDelimiter; 61 this.recordDelimiter = recordDelimiter; 62 this.quoteSymbol = quoteSymbol; 63 this.buf = new StringBuilder(); 64 } 65 startRecordStream(ServiceContext context, Flow flow)66 public void startRecordStream(ServiceContext context, Flow flow) { 67 //System.out.println(getClass().getName()+".startRecordStream enter"); 68 try { 69 70 this.sink = sinkFactory.createStreamSink(context, flow); 71 if (sink.getCharset() != null) { 72 this.writer = new BufferedWriter(new OutputStreamWriter(sink.getOutputStream(), sink.getCharset())); 73 } else { 74 this.writer = new BufferedWriter(new OutputStreamWriter(sink.getOutputStream())); 75 } 76 row = 0; 77 } catch (ServingXmlException e) { 78 throw e; 79 } catch (Exception e) { 80 throw new ServingXmlException(e.getMessage(),e); 81 } 82 //System.out.println(getClass().getName()+".startRecordStream leave"); 83 } 84 writeRecord(ServiceContext context, Flow flow)85 public void writeRecord(ServiceContext context, Flow flow) { 86 //System.out.println(getClass().getName()+".writeRecord enter"); 87 try { 88 89 Record record = flow.getRecord(); 90 int fieldCount = record.fieldCount(); 91 if (row == 0) { 92 for (int i = 0; i < fieldCount; ++i) { 93 if (i > 0) { 94 writer.write(fieldDelimiter.toString()); 95 } 96 FieldType fieldType = record.getRecordType().getFieldType(i); 97 String value = fieldType.getLabel(); 98 boolean insertQuotes = fieldDelimiter.occursIn(value) || recordDelimiter.occursIn(value); 99 if (insertQuotes) { 100 buf.setLength(0); 101 buf.append(quoteSymbol.getCharacter()); 102 quoteSymbol.escape(value, buf); 103 buf.append(quoteSymbol.getCharacter()); 104 writer.write(buf.toString()); 105 } else { 106 writer.write(value); 107 } 108 } 109 writer.write(recordDelimiter.toString()); 110 } 111 for (int i = 0; i < fieldCount; ++i) { 112 if (i > 0) { 113 writer.write(fieldDelimiter.toString()); 114 } 115 Name fieldName = record.getFieldName(i); 116 String value = record.getValue(i).getString(); 117 boolean insertQuotes = fieldDelimiter.occursIn(value) || recordDelimiter.occursIn(value); 118 if (insertQuotes) { 119 buf.setLength(0); 120 buf.append(quoteSymbol.getCharacter()); 121 quoteSymbol.escape(value, buf); 122 buf.append(quoteSymbol.getCharacter()); 123 writer.write(buf.toString()); 124 } else { 125 writer.write(value); 126 } 127 } 128 writer.write(recordDelimiter.toString()); 129 ++row; 130 } catch (ServingXmlException e) { 131 throw e; 132 } catch (Exception e) { 133 throw new ServingXmlException(e.getMessage(),e); 134 } 135 //System.out.println(getClass().getName()+".writeRecord leave"); 136 } 137 endRecordStream(ServiceContext context, Flow flow)138 public void endRecordStream(ServiceContext context, Flow flow) { 139 //System.out.println(getClass().getName()+".endRecordStream enter"); 140 try { 141 writer.flush(); 142 } catch (Exception e) { 143 throw new ServingXmlException(e.getMessage(),e); 144 } 145 //System.out.println(getClass().getName()+".endRecordStream leave"); 146 } 147 close()148 public void close() { 149 if (sink != null) { 150 sink.close(); 151 sink = null; 152 } 153 } 154 } 155 156 157