eva/3 Application BuilderDeveloping Additional eva/3 ComponentsDevelopment of own data origins 

CSVRecordSource reference implementation

With the CSVRecordSet the data management of the data and the data view occur in two collections of the type ArrayList. By the call of the method refresh() firstly the second ArrayList is filled with the data which conforms the filter criteria. Afterwards the data of the filtered list is sorted.

CSVRecordSource example class

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 = (Linearg0;
      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 (Valuevalues.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 = (Valuearg0;
      Value value2 = (Valuearg1;

      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 recordSourceDescriptorthrows 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 rowthrows SQLException {
    if (row >= && 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 = (Valueiterator.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 updatethrows SQLException {
    if (isRowInserted()) {
      moveToCurrentRow();
    else {
      updateCache = null;

      Line line = (LinefilteredLines.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 updatethrows SQLException {
    Line line = (LinefilteredLines.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 = (Lineiterator.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[] recordSetConditionsthrows SQLException {
    RecordSetCondition[] searchConditions = recordSetConditions;
    ArrayList result = new ArrayList();
    if (searchConditions != null && searchConditions.length > 0) {
      Iterator iterator = data.iterator();
      while (iterator.hasNext()) {

        Line line = (Lineiterator.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 && !((PTableElementgetTableElement()).isAllowNullFilterValues()) || (getTableElement() instanceof STableElement && !((STableElementgetTableElement())
                  .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 = ((NumbersearchValue).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()) == -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 columnIndexthrows SQLException {
    Object value = getObject(columnIndex);
    if (value == null) {
      return false;
    else if (value instanceof String) {
      String strValue = ((Stringvalue).trim();
      if (strValue.equalsIgnoreCase(TRUE)) {
        return true;
      else if (strValue.equalsIgnoreCase(FALSE)) {
        return false;
      else {
        try {
          int intValue = Integer.parseInt(strValue);
          return intValue == false true;
        catch (NumberFormatException e) {
          return false;
        }
      }
    else if (value instanceof Boolean) {
      return ((Booleanvalue).booleanValue();
    else {
      try {
        int intValue = Integer.parseInt(value.toString());
        return intValue == 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 columnNamethrows 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 >= && 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 columnNamethrows SQLException {
    if (getColumnNames() != null) {
      Integer integer = (IntegercolumnIndecies.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 >= && 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 columnIndexthrows SQLException, NumberFormatException {
    Object value = getObject(columnIndex);
    if (value == null) {
      return 0d;
    else if (value instanceof String) {
      String strValue = ((Stringvalue).trim();
      return Double.parseDouble(strValue);
    else if (value instanceof Number) {
      Number numValue = (Numbervalue;
      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 columnNamethrows 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 columnIndexthrows SQLException {
    if (columnIndex > && 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 columnIndexthrows SQLException {
    if (rowIndex == currentRow) {
      return updateCache[(columnIndex -= 1)];
    else {
      if (rowIndex != HSRecordSet.AFTER_LAST && rowIndex != HSRecordSet.BEFORE_FIRST && rowIndex <= getRowCount() && rowIndex > 0) {
        if (columnIndex > && columnIndex <= getColumnCount()) {
          return ((LinefilteredLines.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 columnNamethrows 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() ((inserted0);
  }

  /**
   * 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 linethrows 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 = (Valueline.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 columnIndexthrows SQLException {
    Object value = getObject(columnIndex);
    if (value == null) {
      return null;
    else if (value instanceof Timestamp) {
      return (Timestampvalue;
    }
    try {
      return (Timestampnew 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 columnNamethrows 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 == && firstRowColumnInformationsString != null && firstRowColumnInformationsString.equalsIgnoreCase("true")) {
          ColumnDescriptor[] columnDescriptors = new ColumnDescriptor[values.length];
          for (int i = 0; i < values.length; i++) {
            columnDescriptors[inew 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 > && currentRow <= filteredLines.size()) {
      refreshUpdateCache();
    else {
      createEmptyCache();
    }
  }

  /**
   * Clears the update cache and copies current row values in cache
   */
  private void refreshUpdateCache() {
    Line line = (LinefilteredLines.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[] searchConditionsthrows SQLException {
    ArrayList arrayList = filterValue(filteredLines, searchConditions);
    if (arrayList.size() 0) {
      Line line = (LinearrayList.get(0);
      int index = filteredLines.indexOf(line1;

      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 indexValuethrows 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 = ((LinefilteredLines.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((LinefilteredLines.get(j)).getValue(columnIndex);
        }
        Arrays.sort(values, new ValueComporator());
        results.add(values);
      }

      Iterator iterator = filteredLines.iterator();
      while (iterator.hasNext()) {
        Line line = (Lineiterator.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 bthrows 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 bthrows 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 objectthrows 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 objectthrows 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 = (LinefilteredLines.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 columnNamethrows SQLException {
    return getObject(rowIndex, getColumnIndex(columnName));
  }

}