/*
* Copyright 2014-2015 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wplatform.ddal.value;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import com.wplatform.ddal.engine.SysProperties;
import com.wplatform.ddal.util.JdbcUtils;
import com.wplatform.ddal.util.Utils;
/**
* Implementation of the OBJECT data type.
*/
public class ValueJavaObject extends ValueBytes {
private static final ValueJavaObject EMPTY =
new ValueJavaObject(Utils.EMPTY_BYTES);
protected ValueJavaObject(byte[] v) {
super(v);
}
/**
* Get or create a java object value for the given byte array.
* Do not clone the data.
*
* @param javaObject the object
* @param b the byte array
* @param dataHandler provides the object serializer
* @return the value
*/
public static ValueJavaObject getNoCopy(Object javaObject, byte[] b) {
if (b != null && b.length == 0) {
return EMPTY;
}
ValueJavaObject obj;
if (SysProperties.serializeJavaObject) {
if (b == null) {
b = JdbcUtils.serialize(javaObject);
}
obj = new ValueJavaObject(b);
} else {
obj = new NotSerialized(javaObject, b);
}
if (b == null || b.length > SysProperties.OBJECT_CACHE_MAX_PER_ELEMENT_SIZE) {
return obj;
}
return (ValueJavaObject) Value.cache(obj);
}
@Override
public int getType() {
return Value.JAVA_OBJECT;
}
@Override
public void set(PreparedStatement prep, int parameterIndex)
throws SQLException {
Object obj = JdbcUtils.deserialize(getBytesNoCopy());
prep.setObject(parameterIndex, obj, Types.JAVA_OBJECT);
}
/**
* Value which serializes java object only for I/O operations.
* Used when property {@link SysProperties#serializeJavaObject} is disabled.
*
* @author Sergi Vladykin
*/
private static class NotSerialized extends ValueJavaObject {
private Object javaObject;
private int displaySize = -1;
NotSerialized(Object javaObject, byte[] v) {
super(v);
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);
}
return value;
}
@Override
protected int compareSecure(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);
}
// group by types
if (o1.getClass() != o2.getClass()) {
if (o1Comparable != o2Comparable) {
return o1Comparable ? -1 : 1;
}
return o1.getClass().getName().compareTo(o2.getClass().getName());
}
// compare hash codes
int h1 = hashCode();
int h2 = v.hashCode();
if (h1 == h2) {
if (o1.equals(o2)) {
return 0;
}
return Utils.compareNotNullSigned(getBytesNoCopy(), v.getBytesNoCopy());
}
return h1 > h2 ? 1 : -1;
}
@Override
public String getString() {
String str = getObject().toString();
if (displaySize == -1) {
displaySize = str.length();
}
return str;
}
@Override
public long getPrecision() {
return 0;
}
@Override
public int hashCode() {
if (hash == 0) {
hash = getObject().hashCode();
}
return hash;
}
@Override
public Object getObject() {
if (javaObject == null) {
javaObject = JdbcUtils.deserialize(value);
}
return javaObject;
}
@Override
public int getDisplaySize() {
if (displaySize == -1) {
displaySize = getString().length();
}
return displaySize;
}
@Override
public int getMemory() {
if (value == null) {
return DataType.getDataType(getType()).memory;
}
int mem = super.getMemory();
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;
}
}
}