package org.h2.value;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import org.h2.engine.SysProperties;
import org.h2.store.DataHandler;
import org.h2.util.Bits;
import org.h2.util.JdbcUtils;
import org.h2.util.Utils;
public class ValueJavaObject extends ValueBytes {
private static final ValueJavaObject EMPTY =
new ValueJavaObject(Utils.EMPTY_BYTES, null);
private final DataHandler dataHandler;
protected ValueJavaObject(byte[] v, DataHandler dataHandler) {
super(v);
this.dataHandler = dataHandler;
}
public static ValueJavaObject getNoCopy(Object javaObject, byte[] b,
DataHandler dataHandler) {
if (b != null && b.length == 0) {
return EMPTY;
}
ValueJavaObject obj;
if (SysProperties.serializeJavaObject) {
if (b == null) {
b = JdbcUtils.serialize(javaObject, dataHandler);
}
obj = new ValueJavaObject(b, dataHandler);
} else {
obj = new NotSerialized(javaObject, b, dataHandler);
}
if (b == null || b.length > SysProperties.OBJECT_CACHE_MAX_PER_ELEMENT_SIZE) {
return obj;
}
return (ValueJavaObject) Value.cache(obj);
}
@Override
public TypeInfo getType() {
return TypeInfo.TYPE_JAVA_OBJECT;
}
@Override
public int getValueType() {
return JAVA_OBJECT;
}
@Override
public void set(PreparedStatement prep, int parameterIndex)
throws SQLException {
Object obj = JdbcUtils.deserialize(getBytesNoCopy(), getDataHandler());
prep.setObject(parameterIndex, obj, Types.JAVA_OBJECT);
}
private static class NotSerialized extends ValueJavaObject {
private Object javaObject;
NotSerialized(Object javaObject, byte[] v, DataHandler dataHandler) {
super(v, dataHandler);
this.javaObject = javaObject;
}
@Override
public void set(PreparedStatement prep, int parameterIndex)
throws SQLException {
prep.setObject(parameterIndex, getObject(), Types.JAVA_OBJECT);
}
@Override
public byte[] getBytesNoCopy() {
if (value == null) {
value = JdbcUtils.serialize(javaObject, null);
}
return value;
}
@Override
public int compareTypeSafe(Value v, CompareMode mode) {
Object o1 = getObject();
Object o2 = v.getObject();
boolean o1Comparable = o1 instanceof Comparable;
boolean o2Comparable = o2 instanceof Comparable;
if (o1Comparable && o2Comparable &&
Utils.haveCommonComparableSuperclass(o1.getClass(), o2.getClass())) {
@SuppressWarnings("unchecked")
Comparable<Object> c1 = (Comparable<Object>) o1;
return c1.compareTo(o2);
}
if (o1.getClass() != o2.getClass()) {
if (o1Comparable != o2Comparable) {
return o1Comparable ? -1 : 1;
}
return o1.getClass().getName().compareTo(o2.getClass().getName());
}
int h1 = hashCode();
int h2 = v.hashCode();
if (h1 == h2) {
if (o1.equals(o2)) {
return 0;
}
return Bits.compareNotNullSigned(getBytesNoCopy(), v.getBytesNoCopy());
}
return h1 > h2 ? 1 : -1;
}
@Override
public TypeInfo getType() {
TypeInfo type = this.type;
if (type == null) {
String string = getString();
this.type = type = createType(string);
}
return type;
}
private static TypeInfo createType(String string) {
return new TypeInfo(JAVA_OBJECT, 0, 0, string.length(), null);
}
@Override
public String getString() {
String str = getObject().toString();
if (type == null) {
type = createType(str);
}
return str;
}
@Override
public int hashCode() {
if (hash == 0) {
hash = getObject().hashCode();
}
return hash;
}
@Override
public Object getObject() {
if (javaObject == null) {
javaObject = JdbcUtils.deserialize(value, getDataHandler());
}
return javaObject;
}
@Override
public int getMemory() {
if (value == null) {
return 40;
}
int mem = 40;
if (javaObject != null) {
mem *= 2;
}
return mem;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof NotSerialized)) {
return false;
}
return getObject().equals(((NotSerialized) other).getObject());
}
@Override
public Value convertPrecision(long precision, boolean force) {
return this;
}
}
@Override
protected DataHandler getDataHandler() {
return dataHandler;
}
}