/*
* This software and supporting documentation were developed by
*
* Siemens Corporate Technology
* Competence Center Knowledge Management and Business Transformation
* D-81730 Munich, Germany
*
* Authors (representing a really great team ;-) )
* Stefan B. Augustin, Thorbj�rn Hansen, Manfred Langen
*
* This software is Open Source under GNU General Public License (GPL).
* Read the text of this license in LICENSE.TXT
* or look at www.opensource.org/licenses/
*
* Once more we emphasize, that:
* THIS SOFTWARE IS MADE AVAILABLE, AS IS, WITHOUT ANY WARRANTY
* REGARDING THE SOFTWARE, ITS PERFORMANCE OR
* FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR
* ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
* PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
*
*/
// KfmTransientDBTable
package KFM.DB;
// KFM packages
import KFM.Exceptions.ProgrammerException;
import KFM.log.*;
// java packages
import java.lang.Integer;
import java.sql.*;
import java.util.*;
/** A better `TransientDBTable� with support for iterators
* and with access by column name rather than by column position.
*
* <P>`KfmTransientDBTable� improves `TransientDBTable� in two ways. Firstly, it supports
* iterators, which are objects of the class `DBTagValueIterator� (yes, the naming is unfortunate).
* Secondly, it has access by column name rather than by column position.</P>
*
* Added a method to set values.
*
* @author ThH, 04.03.99
*/
public class KfmTransientDBTable /*extends TransientDBTable*/
{
//
// Variables
//
/** For internal fetching of data from db. */
private TransientDBTable mTable = new TransientDBTable();
/** Set of DbTagIterators which currently scan this table. */
private Hashtable mCurrentIterators = new Hashtable();
/** This id is needed for creating the next unique iterator id. */
long mNextIteratorId = 0;
/** Connection to communicate with the database - also needed for creating new iterators. */
private KFM_Database mDB;
/** Needed for creating new iterators. */
private String[] colNames;
/** Map column names to column numbers. */
protected Hashtable colNameToNumber; // String -> Integer // You cannot put an `int� into a `Hashtable�.
//
// Methoden
//
public KfmTransientDBTable (String[] ccolNames, KFM_Database aDB)
{
colNames = ccolNames;
mDB = aDB;
colNameToNumber = new Hashtable();
for(int i = 0; i < colNames.length; ++i) {
// Note: Array indices are 0-based, column numbers are 1-based.
colNameToNumber.put(colNames[i], new Integer(i+1));
}
}
public void finalize()
throws Throwable
{
invalidateAllIterators();
}
/** L�dt eine Datenbank-Tabelle in den Speicher dieses Objektes.
*
* @param sql Eine g�ltige sql-Anweisung
*/
public void loadTable(String sql)
{
//X long tTime = System.currentTimeMillis();
mTable = new TransientDBTable();
try {
mTable.loadTable(sql, mDB.getConnection());
}
catch(ProgrammerException e){
throw new ProgrammerException(
"KfmTransientDBTable::loadTable: getConnection() produced exception " + e.getMessage());
}
invalidateAllIterators();
//X tTime = System.currentTimeMillis() - tTime;
//X KFMSystem.log.info("loaded " + sql + " in " + tTime + " msec. (size: " + mTable.size() + ")");
}
/** Appends a database table to the memory of this object.
*
* @param sql Eine g�ltige sql-Anweisung
*/
public void appendTable(String sql)
{
//X long tTime = System.currentTimeMillis();
if (mTable == null)
mTable = new TransientDBTable();
try {
mTable.appendTable(sql, mDB.getConnection());
}
catch(ProgrammerException e){
throw new ProgrammerException(
"KfmTransientDBTable::appendTable: getConnection() produced exception " + e.getMessage());
}
invalidateAllIterators();
//X tTime = System.currentTimeMillis() - tTime;
//X KFMSystem.log.info("loaded " + sql + " in " + tTime + " msec. (size: " + mTable.size() + ")");
}
/*
public boolean loadTable(String sql, String[] colNames, Connection con)
{
colNameToNumber = new Hashtable();
for(int i = 0; i < colNames.length; ++i) {
// Note: Array indices are 0-based, column numbers are 1-based.
colNameToNumber.put(colNames[i], new Integer(i+1));
}
long tTime = System.currentTimeMillis();
boolean ret = mTable.loadTable(sql, con);
tTime = System.currentTimeMillis() - tTime;
KFMSystem.log.info("loaded " + sql + " in " + tTime + " msec.");
return ret;
}
*/
/**
* Get from table by row number and column name, returning a String or null.
* If the column name is invalid, a ProgrammerException is thrown.
*
* @return String oder null
*
* @see getString
*/
public String get (int rowNr, String colName)
{
final Object obj = colNameToNumber.get(colName);
if(obj == null) {
throw new ProgrammerException("KfmTransientDBTable: colName '" + colName + "' does not exist.");
}
final int colNr = ((Integer) obj).intValue();
return mTable.get(rowNr, colNr);
}
/**
* Get from table by row number and column name, always returning a string ("" if DB value is NULL).
* If the column name is invalid, a ProgrammerException is thrown.
*
* @return Always return a String.
* @see get
*/
public String getString(int rowNr, String colName)
{
String ret = get(rowNr, colName);
if (null == ret)
ret = "";
return ret;
}
/**
* Set a value in the table by row number and column name.
*
* If the column name is invalid, a ProgrammerException is thrown.
* If the row number is greater than the actual size, new (empty) rows are added.
*
* @param rowNr the row number for the new value, first row has index 0
* @param colName the name of the column for the new value
* @param value the value (as a String) to be set
*/
public void set (int rowNr, String colName, String value)
{
final Object obj = colNameToNumber.get(colName);
if(obj == null) {
throw new ProgrammerException("KfmTransientDBTable: colName '" + colName + "' does not exist.");
}
final int colNr = ((Integer) obj).intValue();
mTable.set (rowNr, colNr, value);
}
/**
* @return number of rows which are currently loaded
*/
public int size()
{
return mTable.size();
}
/**
* This is needed for identifying it again while disconnecting
* @return id for this iterator
*/
synchronized String connectIterator(DbTagValueIterator aIterator)
{
// increase the id
mNextIteratorId++;
// TODO: later the ids may not be enough. In this case use the date and
// time as prefix
// insert here
String tIteratorIdString = Long.toString(mNextIteratorId);
mCurrentIterators.put(tIteratorIdString, aIterator);
// tell iterator its id
return tIteratorIdString;
}
/**
* This is needed for identifying it again while disconnecting
* @return id for this iterator
*/
synchronized void disconnectIterator(String id)
{
if ( ! mCurrentIterators.containsKey(id))
throw new ProgrammerException("KfmTransientDBTaBLE.disconnect() - wrong iterator id");
mCurrentIterators.remove(id);
}
public synchronized void invalidateAllIterators()
{
//X String tStr = "";
for (Enumeration tEnum = mCurrentIterators.elements(); tEnum.hasMoreElements();)
{
((DbTagValueIterator) tEnum.nextElement()).invalidate();
//X tStr += ".";
}
//X KFMSystem.log.info("Invalidating all Iterators" + tStr);
}
/** Sorts the table after a column.
*
* Note by ThH: This method was added by HS on 1999-06-24.
* He did not know that KfmTransientDBTable should use *names* (Strings) instead of position (ints)
* to access the columns, so he just copied the signature of `TransientDBTable.sort�.
*
* See also `TransientDBTable.sort�.
*
* @param aColumnToSort
* Column to be sorted, starting with 1.
* E.g. if you want to access the first column, use aColumnToSort=1.
* New: Now a name!
* @param aTypeToSort
* Type of the column which should be sorted. Use <br>
* aTypeToSort=1 for int <br>
* aTypeToSort=2 for String
* @param aSortDirection
* Chooses sort direction: ascending or descending. Use<br>
* direction=1 for ascending<br>
* direction=2 for descending
*
* @see TransientDBTable#sort(int, int, int)
*/
public synchronized boolean sort (
String aColumnToSort,
int aTypeToSort,
int aSortDirection)
{
final Object obj = colNameToNumber.get(aColumnToSort);
if(obj == null) {
throw new ProgrammerException("KfmTransientDBTable: colName '" + aColumnToSort+ "' does not exist.");
}
final int colNr = ((Integer) obj).intValue();
// Call sort methode from TransientDBTable.
return mTable.sort(colNr, aTypeToSort, aSortDirection );
}
}