/*
* $Id: DataRow.java,v 1.4 2005/12/19 12:31:29 oldman1004 Exp $
*
* Copyright(c) 2002 Infomata
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.infomata.data;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
/**
* Object representing collection of data items contained within one
* line of the data file
*
* @author <a href="mailto:oldman1004@gmail.com">Sam Kim</a>
* @version $Revision: 1.4 $
*/
public class DataRow {
/**
* column name to index reference table.
*/
private Hashtable index = null;
/**
* container for data items. (stored as string)
*/
private ArrayList items = null;
/**
* <code>NumberFormat</code> instance used to parse
* numeric values in specified format.
*/
private NumberFormat nf = null;
/**
* SimpleDateFormat instance used to parse date items.
*/
private SimpleDateFormat df = new SimpleDateFormat();
/**
* Creates a new <code>DataRow</code> instance.
* Uses JVM's locale for formatting numbers.
*/
public DataRow() {
items = new ArrayList();
nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(50);
}
/**
* Creates a new <code>DataRow</code> instance.
* Uses specified NumberFormat object to read
* or write numbers.
*
* @param format a <code>NumberFormat</code> object
*/
public DataRow(NumberFormat format) {
items = new ArrayList();
nf = format;
}
/**
* Adds a String datum to the next location
*
* @param datum String datum item
*/
public void add(String datum) {
items.add(datum);
}
/**
* Adds an int datum to the next location.
*
* @param datum int datum item
*/
public void add(int datum) {
items.add(nf.format(datum));
}
/**
* Adds a long datum to the next location.
*
* @param datum a <code>long</code> value
*/
public void add(long datum) {
items.add(nf.format(datum));
}
/**
* Adds a double datum to the next location.
*
* @param datum a <code>double</code> value
*/
public void add(double datum) {
items.add(nf.format(datum));
}
/**
* Adds an object with <code>toString()</code>
* method defined to the next item.
*
* @param obj an <code>Object</code> with
* <code>toString()</code> defined.
*/
public void add(Object obj) {
String str = obj.toString();
add(str);
}
/**
* Adds an empty item (spacer)
*/
public void addEmpty() {
items.add("");
}
/**
* Retrieves an iterator for items
*
* @return an <code>Iterator</code>
*/
public Iterator iterator() {
return items.iterator();
}
/**
* Retrieves the date using the specified pattern
* to parse the date. See <code>java.text.SimpleDateFormat</code>
* documentation valid date format patterns.
*
* @param location locationg of the item
* @param pattern date format pattern (i.e. "yyyy.MM.dd" for 2002.10.20")
* @return Date contained in specified location. If parsing fails
* using the specified pattern, returns NULL.
*/
public Date getDate(int location, String pattern) {
Date d = null;
String v = getString(location).trim();
try {
df.applyPattern(pattern);
d = df.parse(v);
}
catch (ParseException e) {
// do nothing and return null
}
return d;
}
/**
* Retrieve the date value at the specified
* <code>location</code> in specified <code>pattern</code>
* as an instance of <code>java.sql.Date</code>
* instead of <code>java.util.Date</code>.
* @param location location of date value
* @param pattern format of the date value in the data file
* @return <code>java.sql.Date</code> instance representing
* the date at <code>location</code>.
*/
public java.sql.Date getSqlDate(int location, String pattern) {
java.sql.Date d = null;
String v = getString(location).trim();
try {
df.applyPattern(pattern);
d = new java.sql.Date(df.parse(v).getTime());
}
catch (ParseException e) {
// do nothing
}
return d;
}
/**
* Retrieves the date corresponding to the specified
* column <code>label</code>.
*
* @param label column label
* @param pattern see {@link java.text.SimpleDateFormat} for
* further description on pattern syntax.
* @return <code>Date</code> value under specified column label.
*/
public Date getDate(String label, String pattern) {
Date d = null;
int idx = getIndex(label);
if (idx >= 0) {
d = getDate(idx, pattern);
}
return d;
}
/** Retrieves the double value of the datum contained
* in the specified location.
* @return a <code>double</code> value
* @param location location of the item
* @throws NumberFormatException if the item cannot be parsed using normal
* number parser.
*/
public double getDouble(int location) throws NumberFormatException {
double d = Double.NaN;
String val = getString(location).trim();
try {
d = nf.parse(val).doubleValue();
}
catch (ParseException e) {
try {
d = Double.valueOf(val).doubleValue();
}
catch (Exception l) {
throw new NumberFormatException(l.getMessage());
}
}
return d;
}
/**
* Retrieve the <code>double</code> value contained
* in data cell corresponding to the specified column
* <code>label</code>
*
* @param label column label
* @return a <code>double</code> value
* @exception NumberFormatException if the value cannot be parsed
* correctly.
*/
public double getDouble(String label) throws NumberFormatException {
double d = 0d;
int idx = getIndex(label);
if (idx >= 0) {
d = getDouble(idx);
}
else {
throw new NumberFormatException("cannot parse null - check label");
}
return d;
}
/**
* Retrieves the double value of the datum contained
* in the specified location. If the specified location does not
* contain a double value or empty, default value is returned.
*
* @param location location of the item.
* @param defaultVal default value to use when value does not
* exist or fails to parse correctly.
* @return a <code>double</code> value
*/
public double getDouble(int location, double defaultVal) {
String val = getString(location).trim();
try {
defaultVal = nf.parse(val).doubleValue();
}
catch (ParseException e) {
try {
defaultVal = Double.valueOf(val).doubleValue();
}
catch (NumberFormatException l) {
// do nothing and return defaultValue
}
}
return defaultVal;
}
/** Retrieves the <code>double</code> value at specified
* <code>location</code> parsed using <code>format</code>.
* If the value does not exist or fails to parse into
* <code>double</code>, <code>defaultVal</code> is returned.
* @param location location of <code>double</code> value
* @param format double value parser to be used in extracting
* item.
* @param defaultVal default value to use in case of missing data or
* parse error.
* @return a double value at specified <code>location</code>
* or <code>defaultVal</code>
*/
public double getDouble(int location, DecimalFormat format,
double defaultVal) {
String val = getString(location).trim();
try {
defaultVal = format.parse(val).doubleValue();
}
catch (ParseException e) {
try {
defaultVal = Double.valueOf(val).doubleValue();
}
catch (NumberFormatException nf) {
}
}
return defaultVal;
}
/**
* Retrieve the <code>double</code> value contained
* in data cell corresponding to the specified column
* <code>label</code>.
*
* @param label column label
* @param defaultVal default value to use when value does not
* exist or does not parse correctly.
* @return <code>double</code> value corresponding to the
* specified column <code>label</code>. If the
* specified column <code>label</code> does not
* exist or the value cannot parsed into a
* <code>double</code>, <code>defaultValu</code>.
*/
public double getDouble(String label, double defaultVal) {
int idx = getIndex(label);
if (idx >= 0) {
defaultVal = getDouble(idx, defaultVal);
}
return defaultVal;
}
/**
* Retrieves the int value of the datum contained
* in the specified location.
*
* @param location location of the item.
* @return an <code>int</code> at the specified <code>location</code>.
* @throws NumberFormatException if the value at specified location
* cannot parsed into an <code>int</code>
*/
public int getInt(int location) throws NumberFormatException {
int i = 0;
String val = getString(location).trim();
try {
i = nf.parse(val).intValue();
}
catch (Exception e) {
try {
i = Integer.parseInt(val);
}
catch (Exception l) {
new NumberFormatException(l.getMessage());
}
}
return i;
}
/**
* Retrieves the int value of the datum contained
* under specified column <code>label</code>.
*
* @param label column label
* @return a <code>int</code> value
* @throws NumberFormatException if specified column <code>label</code>
* does not exist or the value cannot parsed into an
* <code>int</code>
*/
public int getInt(String label) throws NumberFormatException {
int i = 0;
int idx = getIndex(label);
if (idx >= 0) {
i = getInt(idx);
}
else {
throw new NumberFormatException("cannot parse null - check label");
}
return i;
}
/**
* Retrieves the int value of the datum contained
* in the specified location. If the specified location does not
* contain a int value or empty, default value is returned.
*
* @param location location of the item.
* @param defaultVal default value to use when value does not exist.
* @return a <code>int</code> value
*/
public int getInt(int location, int defaultVal) {
String val = getString(location).trim();
try {
defaultVal = nf.parse(val).intValue();
}
catch(ParseException e) {
try {
defaultVal = Integer.parseInt(val);
}
catch (Exception l) {
// do nothing
}
}
return defaultVal;
}
/** Retrieves the <code>int</code> value at specified
* <code>location</code> parsed using <code>format</code>.
* If the value does not exist or fails to parse into
* <code>int</code>, <code>defaultVal</code> is returned.
* @param location location of <code>int</code> value
* @param format <code>int</code> value parser to be used in extracting
* item.
* @param defaultVal default value to use in case of missing data or
* parse error.
* @return an <code>int</code> value at specified <code>location</code>
* or the <code>defaultVal</code>
*/
public int getInt(int location, DecimalFormat format, int defaultVal) {
String val = getString(location).trim();
try {
defaultVal = format.parse(val).intValue();
}
catch (ParseException e) {
try {
defaultVal = Integer.parseInt(val);
}
catch (NumberFormatException ne) {
}
}
return defaultVal;
}
/**
* Retrieves the <code>int</code> value under the specified
* column <code>label</code>.
*
* @param label column label (header)
* @param defaultVal default value to use when value does not exist.
* @return <code>int</code> value corresponding to the
* specified column <code>label</code>.
* If the specified column <code>label</code>
* does not exist or cannot be convert into an
* <code>int</code> default value is returned.
*/
public int getInt(String label, int defaultVal) {
int idx = getIndex(label);
if (idx >= 0) {
defaultVal = getInt(idx, defaultVal);
}
return defaultVal;
}
/**
* Retrieves the String value contained in the
* specified location.
*
* @param location an <code>int</code> value
* @return a <code>String</code> value or emty String
* if specified location does not exist. (never
* returns null)
*/
public String getString(int location) {
String s = "";
try {
s = (String)items.get(location);
}
catch (IndexOutOfBoundsException e) {
// do nothing.
}
return s;
}
/**
* Retrieves the <code>String</code> value located
* under specified column <code>label</code>.
*
* @param label column label
* @return a <code>String</code> value corresponding
* to specified column <code>label</code>. If the column
* does not exist, empty <code>String</code> is returned.
*/
public String getString(String label) {
String s = "";
int idx = getIndex(label);
if (idx >= 0) {
s = getString(idx);
}
return s;
}
/**
* Retrieves the String value contained in the
* specified location or <code>defaultVal</code> if it
* does not.
*
* @param location location of the item (starts at zero)
* @param defaultVal default value to use when the
* does not contain a value.
* @return a <code>String</code> value at specified
* <code>location</code>. If the value does not
* exist, <code>defaultVal</code> is returned.
*/
public String getString(int location, String defaultVal) {
try {
String tmp = (String)items.get(location);
if (tmp.length() != 0) {
defaultVal = tmp;
}
}
catch (IndexOutOfBoundsException e) {
// do nothing
}
return defaultVal;
}
/**
* Retrieves the <code>String</code> value contained
* under the specified column <code>label</code>.
*
* @param label column label
* @param defaultVal default value to return when value does not
* exist or <code>label</code> fails to match
* any of the column names in header row.
* @return a <code>String</code> value corresponding to specified
* column <code>label</code>. If no such column exists
* or the value is empty, <code>devaultVal</code> is
* returned.
*/
public String getString(String label, String defaultVal) {
int idx = getIndex(label);
if (idx >= 0) {
defaultVal = getString(idx, defaultVal);
}
return defaultVal;
}
/**
* Method for <code>DataFile</code> to set the shared
* instance of a <code>Hashtable</code> that contains
* column label to index reference.
*
* @param index column label to index reference table.
*/
void setHeaderIndex(Hashtable index) {
this.index = index;
}
/**
* Retrieves the number of location in row.
*
* @return number of items contined in <code>DataRow</code>
*/
public int size() {
return items.size();
}
/**
* Helper method to retrieve column index for the specified
* column label.
*
* @param label column label
* @return column index corresponding to column label
*/
private int getIndex(String label) {
int loc = -1;
if (index != null) {
Integer idx = (Integer)index.get(label);
if (idx != null) {
loc = idx.intValue();
}
}
return loc;
}
/**
* <b>For debugging purpose</b>.
* Converts the row of data into String
* @return String representation of data row.
*/
public String toString() {
StringBuffer o = new StringBuffer("[DataRow]");
for (Iterator i = items.iterator(); i.hasNext();) {
o.append("|'").append((String)i.next()).append("'");
}
return o.toString();
}
/**
* Retrieves an immutable list of values contained within
* the instance of DataRow.
* @return immutable list of values in DataRow.
*/
public List getValues()
{
return Collections.unmodifiableList(items);
}
/**
* Remove the content of DataRow.
*/
public void clear() {
items.clear();
}
}