package dbfit.util;
import dbfit.fixture.StatementExecution;
import static dbfit.util.Direction.*;
import static dbfit.util.ValueNormaliser.normaliseValue;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
public class DbParameterAccessor {
private int index; // index in effective sql statement (not necessarily the same as position below)
private Direction direction;
private String name;
private int sqlType;
private String userDefinedTypeName;
private Class<?> javaType;
private int position; // zero-based index of parameter in procedure (-1 for ret value) or column in table
protected StatementExecution cs;
private TypeTransformerFactory dbfitToJdbcTransformerFactory;
/*
* Create an exact copy of this object. Normally this should be
* overridden in favour of the clone template method
*/
protected DbParameterAccessor copy() {
return new DbParameterAccessor(name, direction,
sqlType, javaType, position, dbfitToJdbcTransformerFactory);
}
@Override
public DbParameterAccessor clone() {
DbParameterAccessor copy = copy();
copy.cs = null;
return copy;
}
@SuppressWarnings("unchecked")
public DbParameterAccessor(String name, Direction direction, int sqlType, Class javaType, int position,
TypeTransformerFactory dbfitToJdbcTransformerFactory) {
this(name, direction, sqlType, null, javaType, position, dbfitToJdbcTransformerFactory);
}
public DbParameterAccessor(String name, Direction direction, int sqlType, String userDefinedTypeName, Class javaType, int position,
TypeTransformerFactory dbfitToJdbcTransformerFactory) {
if (direction == RETURN_VALUE && position != -1) {
throw new IllegalArgumentException("Position of return value should be -1");
}
if ((name == null) || (direction != RETURN_VALUE && name.isEmpty())) {
throw new IllegalArgumentException("Missing column or procedure parameter name");
}
this.name = name;
this.direction = direction;
this.sqlType = sqlType;
this.userDefinedTypeName = userDefinedTypeName;
this.javaType = javaType;
this.position = position;
this.dbfitToJdbcTransformerFactory = dbfitToJdbcTransformerFactory;
}
protected int getSqlType() {
return sqlType;
}
public String getUserDefinedTypeName() {
return userDefinedTypeName;
}
public Direction getDirection() {
return direction;
}
public String getName() {
return name;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public void bindTo(StatementExecution cs, int ind) throws SQLException {
this.cs = cs;
this.index = ind;
if (direction != INPUT) {
cs.registerOutParameter(ind, getSqlType(), direction == RETURN_VALUE);
}
}
private Object toJdbcCompatibleValue(Object value) throws SQLException {
TypeTransformer dbfitToJdbcTransformer = null;
Object transformedValue;
if (value != null) {
dbfitToJdbcTransformer = dbfitToJdbcTransformerFactory.getTransformer(value.getClass());
}
if (dbfitToJdbcTransformer != null) {
transformedValue = dbfitToJdbcTransformer.transform(value);
} else {
transformedValue = value;
}
return transformedValue;
}
public void set(Object value) throws Exception {
if (direction == OUTPUT || direction == RETURN_VALUE) {
throw new UnsupportedOperationException("Trying to set value of output parameter " + name);
}
cs.setObject(index, toJdbcCompatibleValue(value), sqlType, userDefinedTypeName);
}
public Object get() throws IllegalAccessException, InvocationTargetException {
try {
if (direction.equals(INPUT)) {
throw new UnsupportedOperationException("Trying to get value of input parameter " + name);
}
return normaliseValue(cs.getObject(index));
}
catch (SQLException sqle) {
throw new InvocationTargetException(sqle);
}
}
/**
* Zero-based column or parameter position in a query, table or stored proc
*/
public int getPosition() {
return position;
}
public Class<?> getJavaType() {
return javaType;
}
protected TypeTransformerFactory getDbfitToJdbcTransformerFactory() {
return dbfitToJdbcTransformerFactory;
}
public boolean isReturnValueAccessor() {
return direction.isReturnValue();
}
public boolean hasDirection(Direction expectedDirection) {
return getDirection() == expectedDirection;
}
public boolean doesNotHaveDirection(Direction expectedDirection) {
return !hasDirection(expectedDirection);
}
}