package railo.runtime.type.query;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Iterator;
import java.util.Map.Entry;
import railo.commons.sql.SQLUtil;
import railo.runtime.PageContext;
import railo.runtime.db.CFTypes;
import railo.runtime.dump.DumpData;
import railo.runtime.dump.DumpProperties;
import railo.runtime.engine.ThreadLocalPageContext;
import railo.runtime.exp.DatabaseException;
import railo.runtime.exp.PageException;
import railo.runtime.op.Caster;
import railo.runtime.query.caster.Cast;
import railo.runtime.type.Collection;
import railo.runtime.type.KeyImpl;
import railo.runtime.type.QueryColumn;
import railo.runtime.type.QueryImpl;
import railo.runtime.type.dt.DateTime;
import railo.runtime.type.it.EntryIterator;
import railo.runtime.type.scope.Undefined;
public class SimpleQueryColumn implements QueryColumn {
private static final long serialVersionUID = 288731277532671308L;
private SimpleQuery qry;
private Key key;
private int type;
private ResultSet res;
private Cast cast;
private int index;
private Object[] data;
public SimpleQueryColumn(SimpleQuery qry, ResultSet res, Collection.Key key, int type, int index) {
this.qry=qry;
this.res=res;
this.key=key;
this.index=index;
try {
switch(type){
case Types.TIMESTAMP:
cast=Cast.TIMESTAMP;
break;
case Types.TIME:
cast=Cast.TIME;
break;
case Types.DATE:
cast=Cast.DATE;
break;
case Types.CLOB:
cast=Cast.CLOB;
break;
case Types.BLOB:
cast=Cast.BLOB;
break;
case Types.BIT:
cast=Cast.BIT;
break;
case Types.ARRAY:
cast=Cast.ARRAY;
break;
case Types.BIGINT:
cast=Cast.BIGINT;
break;
case CFTypes.OPAQUE:
if(SQLUtil.isOracle(res.getStatement().getConnection()))
cast=Cast.ORACLE_OPAQUE;
else
cast=Cast.OTHER;
break;
default:
cast=Cast.OTHER;
break;
}
}
catch (Exception e) {
throw SimpleQuery.toRuntimeExc(e);
}
}
public Object get(Key key, Object defaultValue) {
int row=Caster.toIntValue(key,Integer.MIN_VALUE);
if(row==Integer.MIN_VALUE) {
Object child=getChildElement(key,null);
if(child!=null) return child;
return defaultValue;
}
return get(row,defaultValue);
}
public Object get(Key key) throws PageException {
int row=Caster.toIntValue(key,Integer.MIN_VALUE);
if(row==Integer.MIN_VALUE) {
Object child=getChildElement(key,null);
if(child!=null) return child;
throw new DatabaseException("key ["+key+"] not found",null,null,null);
}
return get(row);
}
private Object getChildElement(Key key, Object defaultValue) {
PageContext pc = ThreadLocalPageContext.get();
// column and query has same name
if(key.equals(this.key)) {
return get(qry.getCurrentrow(pc.getId()),defaultValue);
}
// get it from undefined scope
if(pc!=null){
Undefined undefined = pc.undefinedScope();
boolean old = undefined.setAllowImplicidQueryCall(false);
Object sister = undefined.get(this.key,null);
undefined.setAllowImplicidQueryCall(old);
if(sister!=null){
try {
return pc.get(sister, key);
} catch (PageException e) {
return defaultValue;
}
}
}
return defaultValue;
}
public int size() {
throw SimpleQuery.notSupported();
}
public Key[] keys() {
throw SimpleQuery.notSupported();
}
public Object remove(Key key) throws PageException {
throw SimpleQuery.notSupported();
}
public Object removeEL(Key key) {
throw SimpleQuery.notSupported();
}
public void clear() {
throw SimpleQuery.notSupported();
}
public Object get(String key) throws PageException {
return get(KeyImpl.init(key));
}
public Object get(String key, Object defaultValue) {
return get(KeyImpl.init(key),defaultValue);
}
public Object set(String key, Object value) throws PageException {
throw SimpleQuery.notSupported();
}
public Object set(Key key, Object value) throws PageException {
throw SimpleQuery.notSupported();
}
public Object setEL(String key, Object value) {
throw SimpleQuery.notSupported();
}
public Object setEL(Key key, Object value) {
throw SimpleQuery.notSupported();
}
public Collection duplicate(boolean deepCopy) {
throw SimpleQuery.notSupported();
}
public boolean containsKey(String key) {
throw SimpleQuery.notSupported();
}
public boolean containsKey(Key key) {
throw SimpleQuery.notSupported();
}
@Override
public DumpData toDumpData(PageContext pageContext, int maxlevel,
DumpProperties properties) {
throw SimpleQuery.notSupported();
}
@Override
public Iterator<Collection.Key> keyIterator() {
throw SimpleQuery.notSupported();
}
@Override
public Iterator<String> keysAsStringIterator() {
throw SimpleQuery.notSupported();
}
@Override
public Iterator<Entry<Key, Object>> entryIterator() {
return new EntryIterator(this,keys());
}
public Iterator<Object> valueIterator() {
throw SimpleQuery.notSupported();
}
public String castToString() throws PageException {
// TODO Auto-generated method stub
return Caster.toString(get(key));
}
public String castToString(String defaultValue) {
return Caster.toString(get(key,defaultValue),defaultValue);
}
public boolean castToBooleanValue() throws PageException {
return Caster.toBoolean(get(key));
}
public Boolean castToBoolean(Boolean defaultValue) {
return Caster.toBoolean(get(key,defaultValue),defaultValue);
}
public double castToDoubleValue() throws PageException {
return Caster.toDoubleValue(get(key));
}
public double castToDoubleValue(double defaultValue) {
return Caster.toDoubleValue(get(key,defaultValue),defaultValue);
}
public DateTime castToDateTime() throws PageException {
return Caster.toDate(get(key), false, null);
}
public DateTime castToDateTime(DateTime defaultValue) {
return Caster.toDate(get(key,defaultValue), false, null, defaultValue);
}
public int compareTo(String str) throws PageException {
throw SimpleQuery.notSupported();
}
public int compareTo(boolean b) throws PageException {
throw SimpleQuery.notSupported();
}
public int compareTo(double d) throws PageException {
throw SimpleQuery.notSupported();
}
public int compareTo(DateTime dt) throws PageException {
throw SimpleQuery.notSupported();
}
public String getKeyAsString() {
return key.getString();
}
public Key getKey() {
return key;
}
public Object get(PageContext pc) throws PageException {
return get(key);
}
public Object get(PageContext pc, Object defaultValue) {
return get(key,defaultValue);
}
public Object set(PageContext pc, Object value) throws PageException {
throw SimpleQuery.notSupported();
}
public Object setEL(PageContext pc, Object value) {
throw SimpleQuery.notSupported();
}
public Object remove(PageContext pc) throws PageException {
throw SimpleQuery.notSupported();
}
public Object removeEL(PageContext pc) {
throw SimpleQuery.notSupported();
}
public Object touch(PageContext pc) throws PageException {
throw SimpleQuery.notSupported();
}
public Object touchEL(PageContext pc) {
throw SimpleQuery.notSupported();
}
public Object getParent() {
return qry;
}
public Object remove(int row) throws PageException {
throw SimpleQuery.notSupported();
}
public Object removeRow(int row) throws PageException {
throw SimpleQuery.notSupported();
}
public Object removeEL(int row) {
throw SimpleQuery.notSupported();
}
@Override
public synchronized Object get(int row) throws PageException {
Object sv = getStoredValue(row);
if(sv!=SimpleQuery.DEFAULT_VALUE) return sv;
try {
if(row!=res.getRow()) {
res.absolute(row);
}
return _get(row);
}
catch (Throwable t) {
throw Caster.toPageException(t);
}
}
@Override
public synchronized Object get(int row, Object defaultValue) {
Object sv = getStoredValue(row);
if(sv!=SimpleQuery.DEFAULT_VALUE) return sv;
try {
if(row!=res.getRow()) {
res.absolute(row);
}
return _get(row);
}
catch (Throwable t) {
return defaultValue;
}
}
private synchronized Object getStoredValue(int row) {
if(data==null) return SimpleQuery.DEFAULT_VALUE;
return data[row-1];
}
private synchronized Object _get(int row) throws SQLException, IOException {
if(data==null) {
data=new Object[qry.getRecordcount()];
for(int i=0;i<data.length;i++){
data[i]=SimpleQuery.DEFAULT_VALUE;
}
}
return data[row-1]=cast.toCFType(null, type, res, index);
}
public Object set(int row, Object value) throws PageException {
throw SimpleQuery.notSupported();
}
public void add(Object value) {
throw SimpleQuery.notSupported();
}
public Object setEL(int row, Object value) {
throw SimpleQuery.notSupported();
}
public void addRow(int count) {
throw SimpleQuery.notSupported();
}
public int getType() {
return type;
}
public String getTypeAsString() {
return QueryImpl.getColumTypeName(type);
}
public void cutRowsTo(int maxrows) {
throw SimpleQuery.notSupported();
}
public Object clone() {
throw SimpleQuery.notSupported();
}
public int getIndex() {
return index;
}
@Override
public java.util.Iterator<String> getIterator() {
return keysAsStringIterator();
}
}