package Express.services;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
import DisplayProject.binding.beans.ExtendedPropertyChangeSupport;
import DisplayProject.binding.beans.Observable;
import Framework.Constants;
import Framework.HashTable;
import Framework.RuntimeProperties;
import Framework.TextData;
import GenericDBMS.DBConnectionManager;
/**
* Defines a cache that holds SQL statements in a hash table for quick lookup.
* <p>
* @author ITerative Consulting
* @since 26-Feb-2008
*/
@RuntimeProperties(isDistributed=false, isAnchored=false, isShared=true, isTransactional=false)
@SuppressWarnings("serial")
public class SqlStatementCache
implements Serializable, Observable
{
// ----------
// Attributes
// ----------
public PropertyChangeSupport qq_Listeners = new ExtendedPropertyChangeSupport(this, true);
private HashTable cache;
private DBConnectionManager dB;
private SqlStatement head;
private int maxStatements;
private boolean on;
private int statements;
private SqlStatement tail;
// ------------
// Constructors
// ------------
public SqlStatementCache() {
// Explicitly call the superclass constructor to prevent the implicit call
super();
this.maxStatements = 50;
this.head = new SqlStatement();
this.tail = new SqlStatement();
this.head.setNext(this.tail);
this.tail.setPrev(this.head);
this.setup(0);
this.setOn(true);
}
public SqlStatementCache(DBConnectionManager pDB) {
this();
this.setDB( pDB );
}
// ----------------------
// Accessors and Mutators
// ----------------------
public synchronized void setDB(DBConnectionManager dB) {
DBConnectionManager oldValue = this.dB;
this.dB = dB;
this.qq_Listeners.firePropertyChange("DB", oldValue, this.dB);
}
public synchronized DBConnectionManager getDB() {
return this.dB;
}
public synchronized void setOn(boolean on) {
boolean oldValue = this.on;
this.on = on;
this.qq_Listeners.firePropertyChange("on", oldValue, this.on);
}
public synchronized boolean getOn() {
// AD:Aug 15, 2008 - the statement cache always needs to be off in the java environment
// when using pooling
return false;
// return this.on;
}
private synchronized SqlStatement getTail() {
return this.tail;
}
// -------
// Methods
// -------
public void addPropertyChangeListener(String property, PropertyChangeListener listener) {
qq_Listeners.addPropertyChangeListener(property, listener);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
qq_Listeners.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(String property, PropertyChangeListener listener) {
qq_Listeners.removePropertyChangeListener(property, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
qq_Listeners.removePropertyChangeListener(listener);
}
/**
* enter<p>
* <p>
* @param element Type: Object
* @param key Type: TextData
*/
public synchronized void enter(Object element, TextData key) {
if (this.getOn()) {
this.cache.enter(element, key);
//
// Add statement to LRU chain.
//
SqlStatement s = (SqlStatement)element;
s.setKey(key);
s.setNext(this.head.getNext());
s.setPrev(this.head);
this.head.getNext().setPrev(s);
this.head.setNext(s);
this.statements = this.statements+1;
if (this.statements > this.maxStatements) {
//
// too many elements take one out
//
s = this.tail.getPrev();
this.tail.setPrev(this.tail.getPrev().getPrev());
this.tail.getPrev().setNext(this.tail);
this.statements = this.statements-1;
s.setNext(null);
s.setPrev(null);
this.cache.remove(s.getKey());
try {
s.getHandle().close();
} catch (java.sql.SQLException qq_SQLEx) {
throw new SQLErrorCodeSQLExceptionTranslator().translate("SQL tasks", "", qq_SQLEx );
}
}
}
}
/**
* find<p>
* <p>
* @param key Type: TextData
* @return Object
*/
public synchronized Object find(TextData key) {
SqlStatement s = null;
if (this.getOn()) {
s = (SqlStatement)this.cache.find(key);
if (s != null && this.head.getNext() != s) {
//
// Move it to the front of the LRU chain.
//
s.getNext().setPrev(s.getPrev());
s.getPrev().setNext(s.getNext());
s.setNext(this.head.getNext());
s.setPrev(this.head);
this.head.getNext().setPrev(s);
this.head.setNext(s);
}
}
return s;
}
/**
* setup<p>
* <p>
* @param maxStatements Type: int (Input) (default in Forte: 0)
*/
public synchronized void setup(int maxStatements) {
if (this.head.getNext() != this.getTail()) {
throw new Error(Error.SS_CACHE_IN_USE, "Setup", this).getException();
}
if (maxStatements > 0) {
this.maxStatements = maxStatements;
}
this.cache = new HashTable();
this.cache.setup(this.maxStatements*2, new SqlStatementHash(Constants.SP_KT_OBJECT));
}
} // end class SqlStatementCache
// c Pass 2 Conversion Time: 703 milliseconds