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