package com.odc.eva3.recordsets;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.StringTokenizer;
import com.odc.eva3.rt.dbx.ColumnDescriptor;
import com.odc.eva3.rt.dbx.HSRecordSet;
import com.odc.eva3.rt.dbx.HSRecordSetConstants;
import com.odc.eva3.rt.dbx.RecordSet;
import com.odc.eva3.rt.dbx.RecordSetDescriptor;
import com.odc.eva3.rt.dbx.HSRecordSet.RecordSetCondition;
import com.odc.eva3.rt.se.beans.PTableElement;
import com.odc.eva3.rt.se.beans.STableElement;
/**
* <code>CSVRecordSet</code> in an implementation of <code>RecordSet</code>
* which handle data from an CSV file. It will save the data at disposing the
* dataset.
*
*
*
* @author smandera
*
*/
public class CSVRecordSet extends RecordSet {
/**
* <code>FALSE</code>- String
*/
private static final String FALSE = "false"; //$NON-NLS-1$
/**
* <code>TRUE</code>- String
*/
private static final String TRUE = "true"; //$NON-NLS-1$
/**
* <code>Line</code> representant a data row. Its contains
* <code>Value</code> objects for column definition.
*
*/
private class Line implements Comparable {
/**
* Sort index for line
*/
private int sortIndex;
/**
* Values for line
*/
private ArrayList values;
public Line() {
values = new ArrayList();
}
/**
* Adds an value to value list. The added position is the column
* position in table
*
* @param value
* to add
*/
public void addValue(Value value) {
values.add(value);
}
/**
* Compare the sort index which will set in sort method. See sort() for
* more informations
*
* @param arg0
* @return 1 if sort index bigger then
*/
public int compareTo(Object arg0) {
Line line = (Line) arg0;
if (sortIndex > line.sortIndex) {
return 1;
} else if (sortIndex < line.sortIndex) {
return -1;
} else {
return 0;
}
}
/**
* Gets the value for given position
*
* @param position
* or column index
* @return <code>Value</code> for the position
*/
public Value getValue(int position) {
return (Value) values.get(position);
}
}
/**
* Representants a cell value. <code>Value</code> are added in
* <code>Line</code> for column position
*/
private class Value {
Object value;
public String toString() {
if (value != null) {
return value.toString();
} else {
return null;
}
}
}
/**
* Compares <code>Value</code> objects
*
*/
private class ValueComporator implements Comparator {
public int compare(Object arg0, Object arg1) {
Value value = (Value) arg0;
Value value2 = (Value) arg1;
if (value.value == null && value2.value == null) {
return 0;
} else if (value.value == null && value2.value != null) {
return 1;
} else if (value.value != null && value2.value == null) {
return -1;
} else {
return String.valueOf(value.value).compareTo(String.valueOf(value2.value));
}
}
}
private Hashtable columnIndecies;
private String[] columnNames;
// private RecordSetOrderCondition currentRecordSetOrderCondition;
private int currentRow = HSRecordSetConstants.BEFORE_FIRST;
boolean disposed = false;
private File file;
private ArrayList filteredLines;
private boolean inserted;
private ArrayList lines;
private RandomAccessFile randomAccessFile;
private Object[] updateCache;
private boolean updated;
public CSVRecordSet(RecordSetDescriptor recordSourceDescriptor) throws InvocationTargetException {
super(recordSourceDescriptor);
lines = new ArrayList();
columnIndecies = new Hashtable();
filteredLines = new ArrayList();
initialise(recordSourceDescriptor);
}
/**
* Sets the current row position and refresh update cache
*
* @param the
* current row position to set
*/
public boolean absolute(int row) throws SQLException {
if (row >= 0 && row <= filteredLines.size()) {
currentRow = row;
refreshUpdateCache();
}
return false;
}
/**
* Sets the current row to after last and refresh update cache
*/
public void afterLast() throws SQLException {
currentRow = HSRecordSetConstants.AFTER_LAST;
refreshUpdateCache();
}
/**
* Sets the current row to before first and refresh update cache
*/
public void beforeFirst() throws SQLException {
currentRow = HSRecordSetConstants.BEFORE_FIRST;
refreshUpdateCache();
}
/**
* Cancel the row update and will set the update cache to <code>null</code>
*/
public void cancelRowUpdates() throws SQLException {
updateCache = null;
if (inserted) {
inserted = false;
}
if (updated) {
updated = false;
}
}
/**
* Create empty update cache
*
* @throws SQLException
*/
private void createEmptyCache() throws SQLException {
updateCache = new Object[getColumnCount()];
}
/**
* Create <code>StringBuffer</code> for <code>Line</code> object
* representation
*
* @param line
* to parse
* @return <code>StringBuffer</code> representation of <code>Line</code>
*/
private StringBuffer createStringBuffer(Line line) {
StringBuffer buffer = new StringBuffer();
Iterator iterator = line.values.iterator();
while (iterator.hasNext()) {
Value value = (Value) iterator.next();
if (value.value != null) {
buffer.append(String.valueOf(value.value));
}
if (!iterator.hasNext()) {
buffer.append('\r');
buffer.append('\n');
} else {
buffer.append(';');
}
}
return buffer;
}
/**
* Deletes the current record and refreshes the recordset. Index of cursor
* remaines unchanged except for the last record. Therefore the index of the
* cursor is set to the new last record.
*
* @throws SQLException
* for an error from DBMS
*/
public void deleteRow() throws SQLException {
deleteRow(true);
}
/**
* Deletes the current record. Index of cursor remaines unchanged.
*
* @param update
* flag for refreshing the recordset after deleting the current
* row
*
* @throws SQLException
* for an error from DBMS
*/
public void deleteRow(boolean update) throws SQLException {
if (isRowInserted()) {
moveToCurrentRow();
} else {
updateCache = null;
Line line = (Line) filteredLines.get(currentRow - 1);
lines.remove(line);
filteredLines.remove(line);
if (update) {
if (getRowCount() == 0) {
currentRow = HSRecordSetConstants.AFTER_LAST;
} else if (getRowCount() == 1) {
currentRow = 1;
} else if (currentRow < getRowCount()) {
} else {
currentRow = getRowCount();
}
}
}
}
/**
* Applays delete flag to specified column. Therfore the record is logically
* deleted.
*
* @param columnName
* name of column
* @param delete
* boolean value for column
*
* @throws SQLException
* for an error from DBMS
*/
public void deleteRow(String columnName, boolean update) throws SQLException {
Line line = (Line) filteredLines.get(currentRow - 1);
int columnIndex = getColumnIndex(columnName);
line.getValue(columnIndex).value = null;
updateCache = null;
}
/**
* Dispose the data source and saves the csv file to file system
*/
public void dispose() {
try {
randomAccessFile.getChannel().close();
if (fileUpdated
&& (getRecordSourceDescriptor().getProperties().get("writable") == null || getRecordSourceDescriptor().getProperties().getProperty(
"writable").equalsIgnoreCase("true"))) {
FileWriter fileWriter = new FileWriter(file);
String firstRowColumnInformationsString = getRecordSourceDescriptor().getProperties().getProperty("firstRowContainsNames");
if (firstRowColumnInformationsString != null && firstRowColumnInformationsString.equalsIgnoreCase("true")) {
String columnString = "";
for (int i = 0; i < getColumnNames().length; i++) {
columnString += getColumnNames()[i];
if (i < getColumnNames().length - 1) {
columnString += ";";
}
}
fileWriter.write(columnString + "\r\n");
}
Iterator iterator = lines.iterator();
while (iterator.hasNext()) {
Line line = (Line) iterator.next();
fileWriter.write(createStringBuffer(line).toString());
}
fileWriter.close();
}
randomAccessFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
disposed = true;
}
/**
* Filters the values of given data <code>ArrayList</code>. This
* <code>ArrayList</code> must contains <code>Line</code> objects.
*
* @param data
* <code>ArrayList</code> which must contains <code>Line</code>
* objects. This <code>Lines</code> will be compared with given
* <code>RecordSetCondition[]</code> and matching data will be
* added in result<code>ArrayList</code>
* @param recordSetConditions
* <code>RecordSetCondition[]</code>
* @return matched <code>Line´s</code> in <code>ArrayList</code>
* @throws SQLException
*/
private ArrayList filterValue(ArrayList data, RecordSetCondition[] recordSetConditions) throws SQLException {
RecordSetCondition[] searchConditions = recordSetConditions;
ArrayList result = new ArrayList();
if (searchConditions != null && searchConditions.length > 0) {
Iterator iterator = data.iterator();
while (iterator.hasNext()) {
Line line = (Line) iterator.next();
boolean found = true;
for (int fieldCounter = 1; fieldCounter <= searchConditions.length; fieldCounter++) {
HSRecordSet.RecordSetCondition condition = searchConditions[fieldCounter - 1];
Object searchFieldObject = condition.value;
if ((searchFieldObject == null || searchFieldObject.equals("") || searchFieldObject.toString().equalsIgnoreCase("null")) //$NON-NLS-1$ //$NON-NLS-2$
&& (getTableElement() != null
&& (getTableElement() instanceof PTableElement && !((PTableElement) getTableElement()).isAllowNullFilterValues()) || (getTableElement() instanceof STableElement && !((STableElement) getTableElement())
.isAllowNullFilterValues()))) {
found = false;
break;
}
String searchFieldNames = condition.columnName;
StringTokenizer stringTokenizer = new StringTokenizer(searchFieldNames, ";");
Object searchValue = searchFieldObject;
String strSearchValue = searchValue.toString().trim();
boolean flag = false;
while (stringTokenizer.hasMoreTokens()) {
String filterName = stringTokenizer.nextToken();
int columnIndex = getColumnIndex(filterName);
Object object = line.getValue(columnIndex - 1).value;
String colValue = String.valueOf(object);
int compareResult;
if (searchValue == null && object == null) {
compareResult = 0;
} else {
compareResult = colValue.compareTo(strSearchValue);
}
boolean numFlag = false;
double dblSearchValue = 0;
double dblColValue = 0;
if (searchValue != null && object != null && searchValue instanceof Number) {
try {
dblSearchValue = ((Number) searchValue).doubleValue();
dblColValue = Double.parseDouble(colValue);
numFlag = true;
} catch (Exception ex) {
}
}
int searchOperator = condition.operator;
switch (searchOperator) {
case HSRecordSetConstants.SEARCH_BEGINS_WITH:
boolean startsWith = colValue.toLowerCase().startsWith(strSearchValue.toLowerCase());
if (startsWith) {
flag = true;
}
break;
case HSRecordSetConstants.SEARCH_BEGINS_ENDS_WITH:
boolean contains = colValue.toLowerCase().indexOf(strSearchValue.toLowerCase()) == -1 ? false : true;
if (contains) {
flag = true;
}
break;
case HSRecordSetConstants.SEARCH_ENDS_WITH:
boolean endsWith = colValue.toLowerCase().endsWith(strSearchValue.toLowerCase());
if (endsWith) {
flag = true;
}
break;
default:
case HSRecordSetConstants.SEARCH_LIKE:
if (numFlag && dblSearchValue == dblColValue) {
flag = true;
} else {
if (compareResult == 0) {
flag = true;
}
}
break;
case HSRecordSetConstants.SEARCH_BIGGER:
if (numFlag && dblColValue > dblSearchValue) {
flag = true;
} else {
if (compareResult < 0) {
flag = true;
}
}
break;
case HSRecordSetConstants.SEARCH_SMALLER:
if (numFlag && dblColValue < dblSearchValue) {
flag = true;
} else {
if (compareResult > 0) {
flag = true;
}
}
break;
case HSRecordSetConstants.SEARCH_BIGGER_OR_LIKE:
if (numFlag && dblColValue >= dblSearchValue) {
flag = true;
} else {
if (compareResult <= 0) {
flag = true;
}
}
break;
case HSRecordSetConstants.SEARCH_SMALLER_OR_LIKE:
if (numFlag && dblColValue <= dblSearchValue) {
flag = true;
} else {
if (compareResult >= 0) {
flag = true;
}
}
break;
case HSRecordSetConstants.SEARCH_UNLIKE:
if (compareResult != 0) {
flag = true;
}
break;
}
if (flag) {
break;
}
}
found = flag;
if (getUseOrOperator()) {
if (found) {
break;
} else {
continue;
}
} else if (!found) {
break;
}
}
if (found) {
result.add(line);
}
}
} else {
result.addAll(data);
}
return result;
}
/**
* Filters the <code>Line</code> objects with setted
* <code>RecordSetCondition[]</code>
*
* @throws SQLException
*/
private void filterValues() throws SQLException {
ArrayList result = filterValue(lines, getRecordSetConditions());
filteredLines.addAll(result);
}
/**
* Resets cursor to first record in set.
*
* @throws SQLException
* for an error from the DBMS
*/
public void first() throws SQLException {
currentRow = 1;
refreshCache();
}
/**
* Gets column value at specified index of type <code>boolean</code>.
*
* @param columnIndex
* Index of column
* @return the value for column at spezified index
* @throws SQLException
* for an error from the DBMS
*/
public boolean getBoolean(int columnIndex) throws SQLException {
Object value = getObject(columnIndex);
if (value == null) {
return false;
} else if (value instanceof String) {
String strValue = ((String) value).trim();
if (strValue.equalsIgnoreCase(TRUE)) {
return true;
} else if (strValue.equalsIgnoreCase(FALSE)) {
return false;
} else {
try {
int intValue = Integer.parseInt(strValue);
return intValue == 0 ? false : true;
} catch (NumberFormatException e) {
return false;
}
}
} else if (value instanceof Boolean) {
return ((Boolean) value).booleanValue();
} else {
try {
int intValue = Integer.parseInt(value.toString());
return intValue == 0 ? false : true;
} catch (NumberFormatException e) {
return false;
}
}
}
/**
* Gets column value spezified by column name for type <code>boolean</code>.
*
* @param columnName
* Name of column
* @return the value of specified column
* @throws SQLException
* for an error from the DBMS
*/
public boolean getBoolean(String columnName) throws SQLException {
return getBoolean(getColumnIndex(columnName));
}
/**
* Gets the number of columns.
*
* @return the number of columns
* @throws SQLException
* for an error from the DBMS
*/
public int getColumnCount() throws SQLException {
return getColumnDescriptors().length;
}
/**
* Gets the data type for column index. The <code>int</code> constant of
* <code>java.sql.Types</code>
*
* @return <code>int</code> constant
*/
public int getColumnDataType(int columnIndex) {
if (columnIndex >= 1 && columnIndex <= getColumnNames().length + 1) {
return getColumnDescriptors()[columnIndex - 1].getDataType();
}
return 0;
}
/**
* Gets the column index (1-n) for given column name, or <code>-1</code>
* if not found
*
* @return column index
*/
public int getColumnIndex(String columnName) throws SQLException {
if (getColumnNames() != null) {
Integer integer = (Integer) columnIndecies.get(columnName.toLowerCase());
if (integer != null) {
return integer.intValue() + 1;
}
}
return -1;
}
/**
* Gets the column name for given column index, or <code>null</code> if
* index does not exists
*
* @return column name
*/
public String getColumnName(int columnIndex) {
if (columnIndex >= 1 && columnIndex <= getColumnNames().length + 1) {
return getColumnNames()[columnIndex - 1];
}
return null;
}
/**
* Gets the column names as <code>String[]</code>
*
* @return column names
*/
public String[] getColumnNames() {
if (columnNames == null) {
columnNames = new String[getColumnDescriptors().length];
for (int i = 0; i < columnNames.length; i++) {
columnNames[i] = getColumnDescriptors()[i].getName();
columnIndecies.put(getColumnDescriptors()[i].getName().toLowerCase(), new Integer(i));
}
}
return columnNames;
}
/**
* Gets the column value at the specified index of type <code>double</code>.
* columns with a String type will be parsed to double.
*
* @param columnIndex
* index of column
* @return <code>double</code> value for column at spezified index. If the
* value is SQL NULL, the value returned is 0.
* @throws SQLException
* @throws NumberFormatException
* columns with a String type can cause a
* <code>NumberFormatException</code>
*/
public double getDouble(int columnIndex) throws SQLException, NumberFormatException {
Object value = getObject(columnIndex);
if (value == null) {
return 0d;
} else if (value instanceof String) {
String strValue = ((String) value).trim();
return Double.parseDouble(strValue);
} else if (value instanceof Number) {
Number numValue = (Number) value;
return numValue.doubleValue();
}
throw new NumberFormatException(MessageFormat.format(
Messages.getString("CSVRecordSet.valueCannotParsedToDouble"), new String[] { Integer.toString(columnIndex) })); //$NON-NLS-1$
}
/**
* Retrieves the column value specified by column name for type
* <code>double</code>. columns with a String type will be parsed to
* double.
*
* @param columnIndex
* index of column
* @return <code>double</code> value for column at spezified index. If the
* value is SQL NULL, the value returned is 0.
* @throws SQLException
* @throws NumberFormatException
* columns with a String type can cause a
* <code>NumberFormatException</code>
*/
public double getDouble(String columnName) throws SQLException, NumberFormatException {
return getDouble(getColumnIndex(columnName));
}
/**
* Gets column value at specified index of type <code>Object</code>.
*
* @param columnIndex
* index of column
* @return <code>Object</code> value for column at spezified index
* @throws SQLException
* for an error from DBMS
*/
public Object getObject(int columnIndex) throws SQLException {
if (columnIndex > 0 && columnIndex <= getColumnCount()) {
return updateCache[columnIndex -= 1];
} else {
throw new SQLException(Messages.getString("CSVRecordSet.columnIsOutOfRange")); //$NON-NLS-1$
}
}
/**
* Gets value object for resultset at specified row and column index.
*
* @param rowIndex
* index of Row
*
* @param columnIndex
* index of column
*
* @return <code>Object</code> value at specified row and column index
*
* @throws SQLException
* for an error from DBMS
*/
public Object getObject(int rowIndex, int columnIndex) throws SQLException {
if (rowIndex == currentRow) {
return updateCache[(columnIndex -= 1)];
} else {
if (rowIndex != HSRecordSet.AFTER_LAST && rowIndex != HSRecordSet.BEFORE_FIRST && rowIndex <= getRowCount() && rowIndex > 0) {
if (columnIndex > 0 && columnIndex <= getColumnCount()) {
return ((Line) filteredLines.get((rowIndex -= 1))).getValue((columnIndex -= 1));
} else {
throw new SQLException(Messages.getString("CSVRecordSet.columnIsOutOfRange")); //$NON-NLS-1$
}
} else {
throw new SQLException(Messages.getString("CSVRecordSet.rowIsOutOfRange")); //$NON-NLS-1$
}
}
}
/**
* Gets value of type <code>Object</code> from column specified by its
* name.
*
* @param columnName
* name of column
*
* @return <code>Object</code> value for column at spezified index
*
* @throws SQLException
* for an error from DBMS
*/
public Object getObject(String columnName) throws SQLException {
return getObject(getColumnIndex(columnName));
}
/**
* Gets the index of the current data record.
*
* @return cursor position
* @throws SQLException
* for an error from the DBMS
*/
public int getRow() throws SQLException {
return currentRow;
}
/**
* Gets the number of data records of the result set. It is basic principle
* to not call this methode <code>getRowCount()</code>, because it can
* lead to speed losses.
*
* @return the number of rows
* @throws SQLException
* for an error from the DBMS
*/
public int getRowCount() throws SQLException {
return filteredLines.size() + ((inserted) ? 1 : 0);
}
/**
* In the ArrayList are the <code>Value[]</code> for all rows, this method
* search an internal search index for given line. The values in the line
* for <code>RecordSetOrderConditions</code> is searched in sorted
* <code>Value[]</code> and representant the line position for sort.
*
* @param results
* which must containts sorted <code>Value[]</code> for each
* column
* @param line
* for get the internal search index
* @return the internal search index
* @throws SQLException
*/
private int getSearchIndex(ArrayList results, Line line) throws SQLException {
String searchIndex = ""; //$NON-NLS-1$
for (int i = 0; i < getRecordSetOrderConditions().length; i++) {
Value[] values = (Value[]) results.get(i);
int index = getColumnIndex(getRecordSetOrderConditions()[i].columnName);
index--;
Value value = (Value) line.values.get(index);
for (int j = 0; j < values.length; j++) {
if (String.valueOf(values[j].value).equalsIgnoreCase(String.valueOf(value.value))) {
if (getRecordSetOrderConditions()[i].order == HSRecordSetConstants.DESC) {
searchIndex += (values.length - j);
} else if (getRecordSetOrderConditions()[i].order == HSRecordSetConstants.NO_SORT) {
searchIndex = "0"; //$NON-NLS-1$
} else {
searchIndex += String.valueOf(j);
}
break;
}
}
}
return Integer.parseInt(searchIndex);
}
/**
* Retrieves the value of the designated column in the current row of this
* ResultSet object as a <code>java.sql.Timestamp</code> object.
*
* @param columnIndex
* name of the column
* @return the column value; if the value is SQL NULL, the value returned is
* null
* @throws SQLException
*/
public Timestamp getTimestamp(int columnIndex) throws SQLException {
Object value = getObject(columnIndex);
if (value == null) {
return null;
} else if (value instanceof Timestamp) {
return (Timestamp) value;
}
try {
return (Timestamp) new SimpleDateFormat().parse(value.toString());
} catch (Throwable e) {
return null;
}
}
/**
* Retrieves the value of the designated column in the current row of this
* ResultSet object as a <code>java.sql.Timestamp</code> object.
*
* @param columnName
* name of the column
* @return the column value; if the value is SQL NULL, the value returned is
* null
* @throws SQLException
*/
public Timestamp getTimestamp(String columnName) throws SQLException {
return getTimestamp(getColumnIndex(columnName));
}
/**
* Gets the type of <code>HSRecordSet</code>(
* <code>HSResultSet.TYPE_TABLE</code> or
* <code>HSResultSet.TYPE_QUERY</code>)
*
* @return the type of <code>HSRecordSet</code>(
* <code>HSResultSet.TYPE_TABLE</code> or
* <code>HSResultSet.TYPE_QUERY</code>)
*/
public int getType() {
return 0;
}
public String[] getUpdatedColumnNames() throws SQLException {
// TODO Auto-generated method stub
return null;
}
/**
* Indicates is file data was updated
*/
private boolean fileUpdated = false;
/**
* Initialises CSVRecordSource data
*
* @param recordSourceDescriptor
*/
private void initialise(RecordSetDescriptor recordSourceDescriptor) {
String fullPath = recordSourceDescriptor.getProperties().getProperty("fullpath"); //$NON-NLS-1$
String firstRowColumnInformationsString = recordSourceDescriptor.getProperties().getProperty("firstRowContainsNames");
String writable = recordSourceDescriptor.getProperties().getProperty("writable");
try {
file = new File(fullPath);
if (!file.exists()) {
file.createNewFile();
}
if (writable != null && writable.equalsIgnoreCase("false")) {
randomAccessFile = new RandomAccessFile(file, "r");
} else {
randomAccessFile = new RandomAccessFile(file, "rws"); //$NON-NLS-1$
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
String line;
int currentPosition = 0;
while ((line = randomAccessFile.readLine()) != null) {
String[] values = line.split(";"); //$NON-NLS-1$
if (currentPosition == 0 && firstRowColumnInformationsString != null && firstRowColumnInformationsString.equalsIgnoreCase("true")) {
ColumnDescriptor[] columnDescriptors = new ColumnDescriptor[values.length];
for (int i = 0; i < values.length; i++) {
columnDescriptors[i] = new ColumnDescriptor();
columnDescriptors[i].setName(values[i]);
columnDescriptors[i].setDataType(Types.VARCHAR);
columnDescriptors[i].setTypeName("VARCHAR");
}
recordSourceDescriptor.setColumnDescriptors(columnDescriptors);
} else {
Line newLine = new Line();
// newLine.position = currentPosition;
for (int i = 0; i < values.length; i++) {
Value newValue = new Value();
newValue.value = values[i];
newLine.addValue(newValue);
}
lines.add(newLine);
}
currentPosition++;
}
refreshCache();
if (writable == null || (writable != null && writable.equalsIgnoreCase("true"))) {
randomAccessFile.getChannel().tryLock();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Inserts a new record into the set. First call
* <code>moveToInsertRow()</code> for moving the cursor to the place where
* the new row should be inserted and then call for example
* <code>hrset.updateObject(columnIndex, "content")</code> to specify the
* column content of the new row.
*
* @throws SQLException
* for an error from the DBMS
* @see HSRecordSet#moveToInsertRow()
* @see HSRecordSet#updateObject(int, Object)
* @see HSRecordSet#updateObject(String, Object)
*/
public void insertRow() throws SQLException {
updateRow();
}
/**
* Method to analyse invalid cursor state for position after last row.
*
* @return <code>true</code> if cursor has position after last row
* @throws SQLException
* for an error from DBMS
*/
public boolean isAfterLast() throws SQLException {
return currentRow == HSRecordSetConstants.AFTER_LAST;
}
/**
* Method to analyse invalid cursor state for position before first row.
*
* @return <code>true</code> if and only if cursor has position before
* first row
*
* @throws SQLException
* for an error from DBMS
*/
public boolean isBeforeFirst() throws SQLException {
return currentRow == HSRecordSetConstants.BEFORE_FIRST;
}
/**
* Method to analyse invalid state of recordset is disposed.
*
* @return <code>true</code>, if recordset is disposed
*/
public boolean isDisposed() {
return disposed;
}
/**
* Method to analyse the cursor state for new row has been inserted.
*
* @return <code>true</code>, if a new row has been inserted
*/
public boolean isRowInserted() {
return inserted;
}
/**
* Method to analyse the cursor state for current row has been updated.
*
* @return <code>true</code>, if current row has been updated
*/
public boolean isRowUpdated() {
return updated;
}
/**
* Sets the cursor position to the last record.
*
* @throws SQLException
* for an error from the DBMS
*/
public void last() throws SQLException {
currentRow = filteredLines.size();
refreshCache();
}
/**
* Resets the cursor position to the last current cursor index before
* <code>moveToInsertRow</code> is invoked. Unsaved changes get lost.
*
* @throws SQLException
* for an error from the DBMS
*/
public void moveToCurrentRow() throws SQLException {
System.out.println("moveToCurrentRow"); //$NON-NLS-1$
refreshCache();
}
/**
* Sets the cursor to the index out of the recordset to insert a new row.
* Changes can only be saved by <code>insertRow</code>.
*
* @throws SQLException
* for an error from the DBMS
*/
public void moveToInsertRow() throws SQLException {
System.out.println("moveToInsertRow"); //$NON-NLS-1$
if (filteredLines.size() == 0) {
currentRow = 0;
} else {
currentRow = filteredLines.size() + 1;
}
refreshCache();
inserted = true;
}
/**
* Sets the cursor position to the next index.
*
* @return <code>true</code> if the cursor has a valid index
* @throws SQLException
* for an error from the DBMS
*/
public boolean next() throws SQLException {
if (currentRow < getRowCount() - 1) {
currentRow++;
refreshCache();
return true;
}
return false;
}
/**
* Sets the cursor position to the previous index.
*
* @return <code>true</code> if the cursor has a valid index
* @throws SQLException
* for an error from the DBMS
*/
public boolean previous() throws SQLException {
if (currentRow > 0) {
currentRow--;
refreshCache();
return true;
}
return false;
}
/**
* Clears the cache and reloads Data.
*
* @throws SQLException
* for an error from the DBMS
*/
public void refresh() throws SQLException {
refreshCache();
}
/**
* Filters and sort the lines for representation
*
* @throws SQLException
*/
private void refreshCache() throws SQLException {
filteredLines.clear();
filterValues();
sort();
if (currentRow > 0 && currentRow <= filteredLines.size()) {
refreshUpdateCache();
} else {
createEmptyCache();
}
}
/**
* Clears the update cache and copies current row values in cache
*/
private void refreshUpdateCache() {
Line line = (Line) filteredLines.get((currentRow - 1));
Value[] values = (Value[]) line.values.toArray(new Value[0]);
updateCache = new Object[values.length];
for (int i = 0; i < values.length; i++) {
updateCache[i] = values[i].value;
}
}
/**
* Looks up for records according the serach conditions.
*
* @param searchConditions
* the search conditions
* @return <code>true</code> if a record according to search creteria
* could be found. Therefore the current cursor position is set to
* the first found record.
* @throws SQLException
* for an error from the DBMS
*/
public boolean search(RecordSetCondition[] searchConditions) throws SQLException {
ArrayList arrayList = filterValue(filteredLines, searchConditions);
if (arrayList.size() > 0) {
Line line = (Line) arrayList.get(0);
int index = filteredLines.indexOf(line) + 1;
currentRow = index;
refreshUpdateCache();
return true;
}
return false;
}
/**
* Searchs for the column with the index "<code>indexValue</code>" in
* the row "<code>boundColumnName</code>". If find: the method returns
* the corresponding value of the column "<code>showColumnName
* </code>"
* as an object.
*
* @param boundColumnName
* column name to specify the lookup row
* @param showColumnName
* column name to get result of looked up row
* @param indexValue
* value to specify lookup row
* @return value of the column <code>showColumnName</code> in the row
* looked up
* @throws SQLException
* for an error from the DBMS
*/
public Object search(String boundColumnName, String showColumnName, Object indexValue) throws SQLException {
int boundColumnIndex = getColumnIndex(boundColumnName);
int showColumnIndex = getColumnIndex(showColumnName);
int max = filteredLines.size();
for (int i = 1; i <= max; i++) {
if ((indexValue == null && getObject(i, boundColumnIndex) == null)
|| String.valueOf(indexValue).equals(String.valueOf(getObject(i, boundColumnIndex)))) {
Object viewValue = ((Line) filteredLines.get(i - 1)).getValue(showColumnIndex - 1);
// viewValues.put(boundColumnName + showColumnName + indexValue,
// viewValue);
return viewValue;
}
}
return null;
}
/**
* Sets the update state of the current row.
*
* @param b
* the update state value
*/
public void setRowUpdated(boolean updated) {
this.updated = updated;
}
/**
* Sorts the lines with setted <code>RecordSetOrderConditions</code>
*
* @throws SQLException
*/
private void sort() throws SQLException {
if (getRecordSetOrderConditions() != null && getRecordSetOrderConditions().length > 0) {
ArrayList results = new ArrayList();
for (int i = 0; i < getRecordSetOrderConditions().length; i++) {
int columnIndex = getColumnIndex(getRecordSetOrderConditions()[i].columnName);
columnIndex--;
Value[] values = new Value[filteredLines.size()];
for (int j = 0; j < values.length; j++) {
values[j] = ((Line) filteredLines.get(j)).getValue(columnIndex);
}
Arrays.sort(values, new ValueComporator());
results.add(values);
}
Iterator iterator = filteredLines.iterator();
while (iterator.hasNext()) {
Line line = (Line) iterator.next();
line.sortIndex = getSearchIndex(results, line);
}
Collections.sort(filteredLines);
}
}
/**
* Updates the <code>boolean</code> column at <code>columnIndex</code>
* to the value <code>b</code> at the column in the current row.
*
* @param columnIndex
* the index of the column to update
* @param b
* <code>boolean</code> value to set
* @throws SQLException
* for an error from the DBMS
*/
public void updateBoolean(int columnIndex, boolean b) throws SQLException {
updateObject(columnIndex, new Boolean(b));
updated = true;
}
/**
* Updates the <code>boolean</code> column specified by the name to the
* value <code>b</code> in the current row.
*
* @param columnName
* the name of the column to update
* @param b
* the <code>boolean</code> value to set
* @throws SQLException
* for an error from the DBMS
*/
public void updateBoolean(String columnName, boolean b) throws SQLException {
updateBoolean(getColumnIndex(columnName), b);
updated = true;
}
/**
* Updates the column at the <code>columnIndex</code> by the value
* <code>x</code> in the current record.
*
* @param columnIndex
* the index of the column
* @param x
* the value to set
* @throws SQLException
* for an error from the DBMS
*/
public void updateObject(int columnIndex, Object object) throws SQLException {
int index = columnIndex -= 1;
if (object != null && updateCache[index] == null || object == null && updateCache[index] != null || !String.valueOf(object).equals(updateCache[index])) {
System.out.println("updateObject(columnIndex,object)"); //$NON-NLS-1$
updateCache[index] = object;
updated = true;
}
}
/**
* Updates the column specified by <code>columnName</code> with the value
* <code>x</code> in the current record.
*
* @param columnName
* the name of the column
* @param x
* the value to set
* @throws SQLException
* for an error from the DBMS
*/
public void updateObject(String columnName, Object object) throws SQLException {
updateObject(getColumnIndex(columnName), object);
updated = true;
}
/**
* Saves the changes of the current recordset in the database. If one
* recordset is added, the method function is like <code>insertRow</code>
* and returns <code>1</code>.
*
* @return the number of updated rows
*
* @throws SQLException
* for an error from DBMS
*/
public int updateRow() throws SQLException {
int result = 0;
System.out.println("updateRow updated=" + updated + " inserted=" + inserted); //$NON-NLS-1$ //$NON-NLS-2$
if (inserted && updated) {
Line line = new Line();
for (int i = 0; i < updateCache.length; i++) {
Value value = new Value();
value.value = updateCache[i];
line.addValue(value);
}
lines.add(line);
filteredLines.add(line);
result = 1;
fileUpdated = true;
} else if (updated) {
Line line = (Line) filteredLines.get(currentRow - 1);
line.values.removeAll(line.values);
for (int i = 0; i < updateCache.length; i++) {
Value value = new Value();
value.value = updateCache[i];
line.addValue(value);
}
result = 1;
fileUpdated = true;
// refreshRowData(length, line);
}
updateCache = null;
updated = false;
inserted = false;
return result;
}
/**
* Gets value object for resultset at specified row index and column
* specified by name.
*
* @param rowIndex
* the index of the row
* @param columnName
* the name of the column
* @return the value at the specified row and column
* @throws SQLException
* for an error from the DBMS
*/
public Object getObject(int rowIndex, String columnName) throws SQLException {
return getObject(rowIndex, getColumnIndex(columnName));
}
}
|