View Javadoc
1   /*
2    * ObjectLab, http://www.objectlab.co.uk/open is supporting FlatPack.
3    *
4    * Based in London, we are world leaders in the design and development
5    * of bespoke applications for the securities financing markets.
6    *
7    * <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
8    *           ___  _     _           _   _          _
9    *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
10   *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
11   *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
12   *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
13   *                   |__/
14   *
15   *                     www.ObjectLab.co.uk
16   *
17   * $Id: ColorProvider.java 74 2006-10-24 22:19:05Z benoitx $
18   *
19   * Copyright 2006 the original author or authors.
20   *
21   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
22   * use this file except in compliance with the License. You may obtain a copy of
23   * the License at
24   *
25   * http://www.apache.org/licenses/LICENSE-2.0
26   *
27   * Unless required by applicable law or agreed to in writing, software
28   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
29   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
30   * License for the specific language governing permissions and limitations under
31   * the License.
32   */
33  package net.sf.flatpack.brparse;
34  
35  import java.io.BufferedReader;
36  import java.io.File;
37  import java.io.IOException;
38  import java.io.InputStream;
39  import java.io.Reader;
40  import java.util.List;
41  import java.util.Map;
42  
43  import org.slf4j.Logger;
44  import org.slf4j.LoggerFactory;
45  
46  import net.sf.flatpack.DataSet;
47  import net.sf.flatpack.DefaultDataSet;
48  import net.sf.flatpack.FixedLengthParser;
49  import net.sf.flatpack.structure.ColumnMetaData;
50  import net.sf.flatpack.structure.Row;
51  import net.sf.flatpack.util.FPConstants;
52  import net.sf.flatpack.util.FPException;
53  import net.sf.flatpack.util.FixedWidthParserUtils;
54  import net.sf.flatpack.util.ParserUtils;
55  
56  /**
57   *
58   *
59   * @author Paul Zepernick
60   */
61  public class BuffReaderFixedParser extends FixedLengthParser implements InterfaceBuffReaderParse {
62      private static final Logger LOGGER = LoggerFactory.getLogger(BuffReaderFixedParser.class);
63      private BufferedReader br = null;
64      private int lineCount = 0;
65      private Map recordLengths = null;
66  
67      /**
68       *
69       * @param pzmapXMLStream
70       * @param dataSourceStream
71       */
72      public BuffReaderFixedParser(final InputStream pzmapXMLStream, final InputStream dataSourceStream) {
73          super(pzmapXMLStream, dataSourceStream);
74      }
75  
76      /**
77       *
78       * @param pzmapXML
79       * @param dataSource
80       */
81      public BuffReaderFixedParser(final File pzmapXML, final File dataSource) {
82          super(pzmapXML, dataSource);
83      }
84  
85      /**
86       *
87       *
88       * @param pzmapXML
89       * @param dataSource
90       */
91      public BuffReaderFixedParser(final Reader pzmapXML, final Reader dataSource) {
92          super(pzmapXML, dataSource);
93      }
94  
95      protected BuffReaderFixedParser(final Reader dataSourceReader, final String dataDefinition) {
96          super(dataSourceReader, dataDefinition);
97      }
98  
99      @Override
100     protected DataSet doParse() {
101         final DataSet ds = new BuffReaderDataSet(getPzMetaData(), this);
102         lineCount = 0;
103         recordLengths = ParserUtils.calculateRecordLengths(getPzMetaData());
104         try {
105             // gather the conversion properties
106             ds.setPZConvertProps(ParserUtils.loadConvertProperties());
107 
108             br = new BufferedReader(getDataSourceReader());
109 
110             return ds;
111 
112         } catch (final IOException ex) {
113             LOGGER.error("error accessing/creating inputstream", ex);
114         }
115 
116         return null;
117     }
118 
119     /**
120      * Reads in the next record on the file and return a row
121      *
122      * @param ds
123      * @return Row
124      */
125     @Override
126     public Row buildRow(final DefaultDataSet ds) {
127         String line = null;
128         try {
129             while ((line = br.readLine()) != null) {
130                 lineCount++;
131                 // empty line skip past it
132                 if (line.trim().length() == 0) {
133                     continue;
134                 }
135 
136                 final String mdkey = FixedWidthParserUtils.getCMDKey(getPzMetaData(), line);
137 
138                 final Row row = new Row();
139                 row.setRowNumber(lineCount);
140                 row.setMdkey(mdkey.equals(FPConstants.DETAIL_ID) ? null : mdkey);
141 
142                 final List<ColumnMetaData> cmds = ParserUtils.getColumnMetaData(mdkey, getPzMetaData());
143 
144                 final int recordLength = ((Integer) recordLengths.get(mdkey)).intValue();
145 
146                 if (line.length() > recordLength) {
147                     // Incorrect record length on line log the error. Line will not
148                     // be included in the
149                     // dataset
150                     if (isIgnoreExtraColumns()) {
151                         addError(ds, "TRUNCATED LINE TO CORRECT LENGTH", lineCount, 1, isStoreRawDataToDataError() ? line : null);
152                         // user has chosen to ignore the fact that we have too many bytes in the fixed
153                         // width file. Truncate the line to the correct length
154                         row.addColumn(FixedWidthParserUtils.splitFixedText(cmds, line.substring(0, recordLength), isPreserveLeadingWhitespace(),
155                                 isPreserveTrailingWhitespace()));
156                     } else {
157                         addError(ds, "LINE TOO LONG. LINE IS " + line.length() + " LONG. SHOULD BE " + recordLength, lineCount, 2,
158                                 isStoreRawDataToDataError() ? line : null);
159                         continue;
160                     }
161                 } else if (line.length() < recordLength) {
162                     if (isHandlingShortLines()) {
163                         // log a warning
164                         addError(ds, "PADDED LINE TO CORRECT RECORD LENGTH", lineCount, 1, isStoreRawDataToDataError() ? line : null);
165                         // We can pad this line out
166                         row.addColumn(FixedWidthParserUtils.splitFixedText(cmds, line + ParserUtils.padding(recordLength - line.length(), ' '),
167                                 isPreserveLeadingWhitespace(), isPreserveTrailingWhitespace()));
168 
169                     } else {
170                         addError(ds, "LINE TOO SHORT. LINE IS " + line.length() + " LONG. SHOULD BE " + recordLength, lineCount, 2,
171                                 isStoreRawDataToDataError() ? line : null);
172                         continue;
173                     }
174                 } else {
175                     row.addColumn(FixedWidthParserUtils.splitFixedText(cmds, line, isPreserveLeadingWhitespace(), isPreserveTrailingWhitespace()));
176                 }
177 
178                 if (isFlagEmptyRows()) {
179                     // user has elected to have the parser flag rows that are empty
180                     row.setEmpty(ParserUtils.isListElementsEmpty(row.getCols()));
181                 }
182                 if (isStoreRawDataToDataSet()) {
183                     // user told the parser to keep a copy of the raw data in the row
184                     // WARNING potential for high memory usage here
185                     row.setRawData(line);
186                 }
187 
188                 return row;
189             }
190 
191         } catch (final IOException e) {
192             throw new FPException("Error Fetching Record From File...", e);
193         }
194 
195         return null;
196     }
197 
198     /**
199      * Closes out the file readers
200      *
201      *@throws IOException
202      */
203     @Override
204     public void close() throws IOException {
205         if (br != null) {
206             br.close();
207         }
208     }
209 
210     // try to clean up the file handles automatically if
211     // the close was not called
212     @Override
213     protected void finalize() throws Throwable {
214         try {
215             close();
216         } catch (final IOException ex) {
217             LOGGER.warn("Problem trying to auto close file handles...", ex);
218         } finally {
219             super.finalize();
220         }
221     }
222 }