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;
34  
35  import java.math.BigDecimal;
36  import java.text.ParseException;
37  import java.text.SimpleDateFormat;
38  import java.util.ArrayList;
39  import java.util.Collections;
40  import java.util.Date;
41  import java.util.Iterator;
42  import java.util.List;
43  import java.util.Locale;
44  import java.util.Properties;
45  
46  import net.sf.flatpack.ordering.OrderBy;
47  import net.sf.flatpack.structure.ColumnMetaData;
48  import net.sf.flatpack.structure.Row;
49  import net.sf.flatpack.util.FPConstants;
50  import net.sf.flatpack.util.FPException;
51  import net.sf.flatpack.util.FPInvalidUsageException;
52  import net.sf.flatpack.util.FPStringUtils;
53  import net.sf.flatpack.util.ParserUtils;
54  import net.sf.flatpack.xml.MetaData;
55  
56  /**
57   * @author Benoit Xhenseval
58   * @author Paul Zepernick
59   *
60   */
61  public class DefaultDataSet implements DataSet {
62      private final List rows = new ArrayList();
63  
64      private final List errors = new ArrayList();
65  
66      private Properties pzConvertProps = null;
67  
68      /** Pointer for the current row in the array we are on */
69      private int pointer = -1;
70  
71      /** flag to indicate if data should be pulled as lower case */
72      private boolean lowerCase = false;
73  
74      /** flag to inidicate if data should be pulled as upper case */
75      private boolean upperCase = false;
76  
77      /**
78       * flag to indicate if a strict parse should be used when getting doubles
79       * and ints
80       */
81      private boolean strictNumericParse = false;
82  
83      private MetaData metaData;
84  
85      private Parser parser;
86  
87      public DefaultDataSet(final MetaData pzMetaData, final Parser pzparser) {
88          this.metaData = pzMetaData;
89          this.parser = pzparser;
90      }
91  
92      public void addRow(final Row row) {
93          rows.add(row);
94      }
95  
96      public void addError(final DataError dataError) {
97          errors.add(dataError);
98      }
99  
100     /*
101      * (non-Javadoc)
102      *
103      * @see net.sf.flatpack.DataSet#getColumns()
104      */
105     public String[] getColumns() {
106         ColumnMetaData column = null;
107         String[] array = null;
108 
109         if (/*columnMD != null || */metaData != null) {
110             final List cmds = metaData.getColumnsNames();// ParserUtils.getColumnMetaData(PZConstants.DETAIL_ID, columnMD);
111 
112             array = new String[cmds.size()];
113             for (int i = 0; i < cmds.size(); i++) {
114                 column = (ColumnMetaData) cmds.get(i);
115                 array[i] = column.getColName();
116             }
117         }
118 
119         return array;
120     }
121 
122     /*
123      * (non-Javadoc)
124      *
125      * @see net.sf.flatpack.DataSet#getColumns(java.lang.String)
126      */
127     public String[] getColumns(final String recordID) {
128         String[] array = null;
129 
130         if (metaData != null) {
131             final List cmds = ParserUtils.getColumnMetaData(recordID, metaData);
132             array = new String[cmds.size()];
133             for (int i = 0; i < cmds.size(); i++) {
134                 final ColumnMetaData column = (ColumnMetaData) cmds.get(i);
135                 array[i] = column.getColName();
136             }
137         }
138 
139         return array;
140     }
141 
142     /*
143      * (non-Javadoc)
144      *
145      * @see net.sf.flatpack.DataSet#getDate(java.lang.String)
146      */
147     public Date getDate(final String column) throws ParseException {
148         return getDate(column, new SimpleDateFormat("yyyyMMdd"));
149     }
150 
151     /*
152      * (non-Javadoc)
153      *
154      * @see net.sf.flatpack.DataSet#getDate(java.lang.String,
155      *      java.text.SimpleDateFormat)
156      */
157     public Date getDate(final String column, final SimpleDateFormat sdf) throws ParseException {
158         final String s = getStringValue(column);
159         if (FPStringUtils.isBlank(s)) {
160             //don't do the parse on empties
161             return null;
162         }
163         return sdf.parse(s);
164     }
165 
166     /*
167      * (non-Javadoc)
168      *
169      * @see net.sf.flatpack.DataSet#getDouble(java.lang.String)
170      */
171     public double getDouble(final String column) {
172         final StringBuffer newString = new StringBuffer();
173         final String s = getStringValue(column);
174 
175         if (!strictNumericParse) {
176             newString.append(ParserUtils.stripNonDoubleChars(s));
177         } else {
178             newString.append(s);
179         }
180 
181         return Double.parseDouble(newString.toString());
182     }
183 
184     /*
185      * (non-Javadoc)
186      *
187      * @see net.sf.flatpack.DataSet#getBigDecimal(java.lang.String)
188      */
189     public BigDecimal getBigDecimal(final String column) {
190         final String s = getStringValue(column);
191 
192         return new BigDecimal(s);
193     }
194 
195     private String getStringValue(final String column) {
196         final Row row = (Row) rows.get(pointer);
197         return row.getValue(ParserUtils.getColumnIndex(row.getMdkey(), metaData, column, parser));
198     }
199 
200     public Object getObject(final String column, final Class classToConvertTo) {
201         final String s = getStringValue(column);
202         return ParserUtils.runPzConverter(pzConvertProps, s, classToConvertTo);
203     }
204 
205     /*
206      * (non-Javadoc)
207      *
208      * @see net.sf.flatpack.DataSet#getErrorCount()
209      */
210     public int getErrorCount() {
211         if (getErrors() != null) {
212             return getErrors().size();
213         }
214 
215         return 0;
216     }
217 
218     /*
219      * (non-Javadoc)
220      *
221      * @see net.sf.flatpack.DataSet#getErrors()
222      */
223     public List getErrors() {
224         return errors;
225     }
226 
227     /*
228      * (non-Javadoc)
229      *
230      * @see net.sf.flatpack.DataSet#getIndex()
231      */
232     public int getIndex() {
233         return pointer;
234     }
235 
236     /*
237      * (non-Javadoc)
238      *
239      * @see net.sf.flatpack.DataSet#getInt(java.lang.String)
240      */
241     public int getInt(final String column) {
242         final String s = getStringValue(column);
243 
244         if (!strictNumericParse) {
245             return Integer.parseInt(ParserUtils.stripNonLongChars(s));
246         }
247 
248         return Integer.parseInt(s);
249     }
250     
251     public long getLong(final String column) {
252         final String s = getStringValue(column);
253 
254         if (!strictNumericParse) {
255             return Long.parseLong(ParserUtils.stripNonLongChars(s));
256         }
257 
258         return Long.parseLong(s);
259     }
260 
261     /*
262      * (non-Javadoc)
263      *
264      * @see net.sf.flatpack.DataSet#getRowCount()
265      */
266     public int getRowCount() {
267         return rows.size();
268     }
269 
270     /*
271      * (non-Javadoc)
272      *
273      * @see net.sf.flatpack.DataSet#getRowNo()
274      */
275     public int getRowNo() {
276         return ((Row) rows.get(pointer)).getRowNumber();
277     }
278 
279     /*
280      * (non-Javadoc)
281      *
282      * @see net.sf.flatpack.DataSet#getString(java.lang.String)
283      */
284     public String getString(final String column) {
285         String s = getStringValue(column);
286 
287         if (parser.isNullEmptyStrings() && FPStringUtils.isBlank(s)) {
288             s = null;
289         } else if (upperCase) {
290             // convert data to uppercase before returning
291             // return row.getValue(ParserUtils.findColumn(column,
292             // cmds)).toUpperCase(Locale.getDefault());
293             s = s.toUpperCase(Locale.getDefault());
294         }else if (lowerCase) {
295             // convert data to lowercase before returning
296             // return row.getValue(ParserUtils.findColumn(column,
297             // cmds)).toLowerCase(Locale.getDefault());
298             s = s.toLowerCase(Locale.getDefault());
299         }
300 
301         // return value as how it is in the file
302         return s;
303     }
304 
305     public void setValue(final String column, final String value) {
306         final Row row = (Row) rows.get(pointer);
307         final int colIndex = ParserUtils.getColumnIndex(row.getMdkey(), metaData, column, parser);
308 
309         row.setValue(colIndex, value);
310     }
311 
312     /*
313      * (non-Javadoc)
314      *
315      * @see net.sf.flatpack.DataSet#goBottom()
316      */
317     public void goBottom() {
318         pointer = rows.size() - 1;
319     }
320 
321     /*
322      * (non-Javadoc)
323      *
324      * @see net.sf.flatpack.DataSet#goTop()
325      */
326     public void goTop() {
327         pointer = -1;
328     }
329 
330     /*
331      * (non-Javadoc)
332      *
333      * @see net.sf.flatpack.DataSet#isAnError(int)
334      */
335     public boolean isAnError(final int lineNo) {
336         for (int i = 0; i < errors.size(); i++) {
337             if (((DataError) errors.get(i)).getLineNo() == lineNo && ((DataError) errors.get(i)).getErrorLevel() > 1) {
338                 return true;
339             }
340         }
341         return false;
342     }
343 
344     /*
345      * (non-Javadoc)
346      *
347      * @see net.sf.flatpack.DataSet#next()
348      */
349     public boolean next() {
350         if (pointer < rows.size() && pointer + 1 != rows.size()) {
351             pointer++;
352             return true;
353         }
354         return false;
355     }
356 
357     /*
358      * (non-Javadoc)
359      *
360      * @see net.sf.flatpack.DataSet#orderRows(net.sf.flatpack.ordering.OrderBy)
361      */
362     public void orderRows(final OrderBy ob) {
363         // PZ try to handle other <records> by sending them to
364         // the bottom of the sort
365         // if (columnMD.size() > 1) {
366         // throw new Exception("orderRows does not currently support ordering
367         // with <RECORD> mappings");
368         // }
369         if (ob != null && rows != null) {
370             final List cmds = metaData.getColumnsNames();
371             //            final List cmds = ParserUtils.getColumnMetaData(PZConstants.DETAIL_ID, columnMD);
372             //ob.setColumnMD(cmds);
373             ob.setMetaData(getMetaData());
374             ob.setParser(parser);
375             Collections.sort(rows, ob);
376             goTop();
377         }
378     }
379 
380     /*
381      * (non-Javadoc)
382      *
383      * @see net.sf.flatpack.DataSet#previous()
384      */
385     public boolean previous() {
386         if (pointer <= 0) {
387             return false;
388         }
389         pointer--;
390         return true;
391     }
392 
393     /**
394      * Sets data in the DataSet to lowercase
395      */
396     public void setLowerCase() {
397         upperCase = false;
398         lowerCase = true;
399     }
400 
401     /**
402      * Sets data in the DataSet to uppercase
403      */
404     public void setUpperCase() {
405         upperCase = true;
406         lowerCase = false;
407     }
408 
409     /**
410      * Checks to see if the row has the given <RECORD> id
411      *
412      * @param recordID
413      * @return boolean
414      */
415     public boolean isRecordID(final String recordID) {
416         String rowID = ((Row) rows.get(pointer)).getMdkey();
417         if (rowID == null) {
418             rowID = FPConstants.DETAIL_ID;
419         }
420 
421         return rowID.equals(recordID);
422     }
423 
424     /**
425      * Sets the absolute position of the record pointer
426      *
427      * @param localPointer -
428      *            int
429      * @exception IndexOutOfBoundsException
430      */
431     public void absolute(final int localPointer) {
432         if (localPointer < 0 || localPointer > rows.size() - 1) {
433             throw new IndexOutOfBoundsException("INVALID POINTER LOCATION: " + localPointer);
434         }
435 
436         pointer = localPointer;
437     }
438 
439     /**
440      * Setting this to True will parse text as is and throw a
441      * NumberFormatException. Setting to false, which is the default, will
442      * remove any non numeric charcter from the field. The remaining numeric
443      * chars's will be returned. If it is an empty string,or there are no
444      * numeric chars, 0 will be returned for getInt() and getDouble()
445      *
446      * @param strictNumericParse
447      *            The strictNumericParse to set.
448      */
449     public void setStrictNumericParse(final boolean strictNumericParse) {
450         this.strictNumericParse = strictNumericParse;
451     }
452 
453     /*
454      * (non-Javadoc)
455      *
456      * @see net.sf.flatpack.DataSet#remove()
457      */
458     public void remove() {
459         rows.remove(pointer);
460         pointer--;
461     }
462 
463     public void setPZConvertProps(final Properties props) {
464         this.pzConvertProps = props;
465     }
466 
467     /**
468      * @param pointer the pointer to set
469      */
470     protected void setPointer(final int pointer) {
471         this.pointer = pointer;
472     }
473 
474     public void clearRows() {
475         pointer = -1; //set the pointer back to -1 directly just in case this instance is a BuffReaderDataSet.
476         rows.clear();
477     }
478 
479     public void clearAll() {
480         clearRows();
481         clearErrors();
482     }
483 
484     public void clearErrors() {
485         errors.clear();
486     }
487 
488     public MetaData getMetaData() {
489         return metaData;
490     }
491 
492     public void setMetaData(final MetaData metaData) {
493         this.metaData = metaData;
494     }
495 
496     public String toString() {
497         final StringBuffer buf = new StringBuffer();
498         buf.append("Errors:").append(errors.size()).append(System.getProperty("line.separator"));
499         buf.append("Rows:").append(rows.size()).append(System.getProperty("line.separator"));
500         buf.append("Position:").append(pointer).append(System.getProperty("line.separator"));
501         buf.append("Conversion Props:").append(pzConvertProps).append(System.getProperty("line.separator"));
502         buf.append("MetaData:").append(metaData).append(System.getProperty("line.separator"));
503         return buf.toString();
504     }
505 
506     public boolean contains(final String column) {
507         if (pointer == -1) {
508             throw new IndexOutOfBoundsException("dataset on invalid row. need to call next()");
509         }
510 
511         final Iterator cmds = ParserUtils.getColumnMetaData(((Row) rows.get(pointer)).getMdkey(), metaData).iterator();
512         while (cmds.hasNext()) {
513             final ColumnMetaData cmd = (ColumnMetaData) cmds.next();
514             if (cmd.getColName().equalsIgnoreCase(column)) {
515                 return true;
516             }
517         }
518 
519         return false;
520 
521     }
522     
523     /**
524      * @throws FPInvalidUsageException Parser.isFlagEmptyRows() must be set to true before using this
525      * @throws FPException if cursor is on an invalid row
526      */
527     public boolean isRowEmpty() {
528         if (!parser.isFlagEmptyRows()) {
529             //flag empty rows needs to be set for this functionality
530             //throw an exception
531             throw new FPInvalidUsageException("Parser.isFlagEmptyRows(true) must be set before using isRowEmpty()");
532         }
533         
534         if (pointer < 0) {
535             throw new FPException("Cursor on invalid row..  Make sure next() is called and returns true");
536         }
537         
538         return ((Row)rows.get(pointer)).isEmpty();
539     }
540 
541     /**
542      * @throws FPInvalidUsageException
543      * @throws FPException if cursor is on an invalid row
544      */
545     public String getRawData() {
546         if (!parser.isStoreRawDataToDataSet()) {
547             //option needs to be set for this functionality
548             //throw an exception
549             throw new FPInvalidUsageException("Parser.isStoreRawDataToDataSet(true) must be set before using getRawData()");
550         }
551         
552         if (pointer < 0) {
553             throw new FPException("Cursor on invalid row.. Make sure next() is called and returns true");
554         }
555         
556         return ((Row)rows.get(pointer)).getRawData();
557     }
558 }