package er.extensions.eof;
import java.math.BigDecimal;
import com.webobjects.eoaccess.EOAttribute;
import com.webobjects.eoaccess.EOSQLExpression;
import com.webobjects.foundation.NSData;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSTimestamp;
/**
* This class models an SQL binding based on a Java object.
* <p>
* When using this class to model a binding, the EOF SQL generation layer will not
* be able to inspect the model and obtain the correct value types and conversions.
* A best guess will be made based on the class of the wrapped object. This class
* supports the five basic types EOF supports (String, BigDecimal, Number, NSData and
* NSTimestamp). Also, boolean values true and false are converted to "true" and "false"
* strings. If boolean representation is different on the database you are using (like
* integers) you have to handle it yourself by wrapping an object of the appropriate
* class.
* </p>
* <p>
* A note about SQL generation: due to the internal architecture of database plugins,
* this class will not be able to ask the plugin for an appropriate placeholder string
* for the binding values. This won't matter for databases where the placeholder string
* is "?". However, some databases, like PostgreSQL 7.4 and older, require the placeholder
* string to contain the value type, like "?::varchar(1000)". Using this class may cause
* problems and unexpected results on such databases. If that's the case, consider using
* {@link ERXKeyValueBinding}.
* </p>
*/
public class ERXObjectBinding implements ERXSQLBinding {
/**
* Wrapped object.
*/
private Object _value;
/**
* Helper EOAttributed used for SQL generation.
*/
private EOAttribute _attribute;
/**
* Creates a new object binding wrapper for the given object.
* <p>
* value must be an instance of the following classes (or any subsclass of these): String,
* BigDecimal, Number, NSData, NSTimestamp.
* </p>
* @param value
* Object to be wrapped
*/
public ERXObjectBinding( Object value ) {
super();
initForValue( value );
}
/**
* Initializes instance based on the wrapped object class.
*
* @param originalValue
* Object to be wrapped
*/
private void initForValue(Object originalValue) {
Object value = originalValue;
if( originalValue instanceof Boolean ) {
value = originalValue.toString();
}
EOAttribute attribute = new EOAttribute();
attribute.setName(""); // Must have a name, or EOSQLExpression will scream
if( value instanceof String ) {
attribute.setClassName( String.class.getName() );
} else if( value instanceof BigDecimal ) {
attribute.setClassName( BigDecimal.class.getName() );
} else if( value instanceof Number ) {
attribute.setClassName( Number.class.getName() );
} else if( value instanceof NSData ) {
attribute.setClassName( NSData.class.getName() );
} else if( value instanceof NSTimestamp ) {
attribute.setClassName( NSTimestamp.class.getName() );
} else {
throw new RuntimeException("Unsupported object class: " + value.getClass().getName() );
}
_value = value;
_attribute = attribute;
}
public String sqlStringForBindingOnExpression(EOSQLExpression expression) {
NSDictionary binding = expression.bindVariableDictionaryForAttribute( _attribute, _value );
expression.addBindVariableDictionary(binding);
return (String) binding.objectForKey(EOSQLExpression.BindVariablePlaceHolderKey);
}
}