package com.completex.objective.components.persistency.type;
import com.completex.objective.components.persistency.ColumnType;
import com.completex.objective.components.persistency.xml.XmlRuntimeException;
import com.completex.objective.util.XmlDomHelper;
import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author Gennady Krizhevsky
*/
public class ValueStreamHelper {
public static final Map NUMERIC = new HashMap();
public static final LongFactory LONG_FACTORY = new LongFactory();
public static final IntegerFactory INTEGER_FACTORY = new IntegerFactory();
public static final ShortFactory SHORT_FACTORY = new ShortFactory();
public static final FloatFactory FLOAT_FACTORY = new FloatFactory();
public static final DoubleFactory DOUBLE_FACTORY = new DoubleFactory();
public static final ByteFactory BYTE_FACTORY = new ByteFactory();
static {
NUMERIC.put(Long.class.getName(), LONG_FACTORY);
NUMERIC.put(Integer.class.getName(), INTEGER_FACTORY);
NUMERIC.put(Short.class.getName(), SHORT_FACTORY);
NUMERIC.put(Float.class.getName(), FLOAT_FACTORY);
NUMERIC.put(Double.class.getName(), DOUBLE_FACTORY);
NUMERIC.put(Byte.class.getName(), BYTE_FACTORY);
NUMERIC.put(BigDecimal.class.getName(), new BigDecimalFactory());
NUMERIC.put(BigInteger.class.getName(), new BigIntegerFactory());
//
// Primitives:
//
NUMERIC.put(long.class.getName(), LONG_FACTORY);
NUMERIC.put(int.class.getName(), INTEGER_FACTORY);
NUMERIC.put(short.class.getName(), SHORT_FACTORY);
NUMERIC.put(float.class.getName(), FLOAT_FACTORY);
NUMERIC.put(double.class.getName(), DOUBLE_FACTORY);
NUMERIC.put(byte.class.getName(), BYTE_FACTORY);
}
public static final Map DATE = new HashMap();
static {
DATE.put(Date.class.getName(), new DateFactory());
DATE.put(java.sql.Date.class.getName(), new SqlDateFactory());
DATE.put(Time.class.getName(), new SqlTimeFactory());
DATE.put(Timestamp.class.getName(), new SqlTimestampFactory());
}
public static final Map BOOLEAN = new HashMap();
public static final BooleanFactory BOOLEAN_FACTORY = new BooleanFactory();
static {
BOOLEAN.put(Boolean.class.getName(), BOOLEAN_FACTORY);
//
// Primitives:
//
BOOLEAN.put(boolean.class.getName(), BOOLEAN_FACTORY);
}
public static final Map VALUE_FACTORIES = new HashMap();
public static final ByteArrayInputStream NULL_BYTE_ARRAY_INPUT_STREAM = new ByteArrayInputStream(new byte [0]);
static {
VALUE_FACTORIES.putAll(NUMERIC);
VALUE_FACTORIES.putAll(DATE);
VALUE_FACTORIES.putAll(BOOLEAN);
}
public static ValueStringResult value2string(ColumnType type, Object value) {
ValueStringResult result = new ValueStringResult();
if (value == null) {
return result;
}
try {
if (ColumnType.isBinary(type)) {
if (value == ColumnType.NULL_BINARY_OBJECT) {
value = null;
}
BASE64Encoder encoder = new BASE64Encoder();
if (value instanceof Blob) {
Blob blob = (Blob) value;
long len = blob.length();
validateIntLen(len);
result.setValueString(encoder.encode(blob.getBytes(1, (int) len)));
} else if (value instanceof Clob) {
Clob clob = (Clob) value;
long len = clob.length();
validateIntLen(len);
result.setValueString(clob.getSubString(1, (int) len));
} else if (value instanceof ByteArrayInputStream) {
ByteArrayInputStream bin = (ByteArrayInputStream) value;
ByteArrayOutputStream bout = new ByteArrayOutputStream(bin.available());
BlobImpl.writeBlob(bin, bout);
result.setValueString(encoder.encode(bout.toByteArray()));
} else {
result = value2string(value);
}
} else if (ColumnType.isDate(type)) {
Date date = (Date) value;
result.setValueString(XmlDomHelper.D2S(date));
} else if (ColumnType.isBoolean(type)) {
Boolean date = (Boolean) value;
result.setValueString(XmlDomHelper.B2S(date));
} else if (ColumnType.isObject(type)) {
result = value2string(value);
} else {
result.setValueString(String.valueOf(value));
}
} catch (Exception e) {
throw new XmlRuntimeException("Cannot convert value " +
"of type [" + type + "] to String", e);
}
return result;
}
public static ValueStringResult value2string(Object value) throws IOException {
ValueStringResult result = new ValueStringResult();
String valueString = null;
if (value instanceof String) {
valueString = ((String) value);
} else if (isNumericValue(value)) {
valueString = String.valueOf(value);
} else if (isDate(value)) {
valueString = XmlDomHelper.D2S(((Date) value));
} else if (isBoolean(value)) {
valueString = XmlDomHelper.B2S(((Boolean) value));
} else if (value != null) {
valueString = unknownBinary2string(value);
result.setBinary(true);
}
result.setValueString(valueString);
return result;
}
protected static String unknownBinary2string(Object value) throws IOException {
BASE64Encoder encoder = new BASE64Encoder();
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(os);
out.writeObject(value);
out.flush();
out.close();
byte[] bytes = os.toByteArray();
return encoder.encode(bytes);
}
protected static boolean isNumericValue(Object value) {
if (value == null) {
return false;
}
return isNumericClass(value.getClass().getName());
}
protected static boolean isNumericClass(String className) {
return NUMERIC.containsKey(className);
}
protected static boolean isDate(Object value) {
if (value == null) {
return false;
}
return isDateClass(value);
}
protected static boolean isDateClass(Object className) {
return DATE.containsKey(className);
}
protected static boolean isBoolean(Object value) {
if (value == null) {
return false;
}
return isBooleanClass(value.getClass().getName());
}
protected static boolean isBooleanClass(String className) {
return BOOLEAN.containsKey(className);
}
protected static void validateIntLen(long len) {
if (len > Integer.MAX_VALUE) {
throw new XmlRuntimeException("len > Integer.MAX_VALUE");
}
}
/**
* Value factory
*/
protected static interface ValueFactory {
Object newValueInstance(String valueString);
}
/**
* Numeric:
*/
protected static class LongFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
return Long.valueOf(valueString);
}
}
protected static class IntegerFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
return Integer.valueOf(valueString);
}
}
protected static class ShortFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
return Short.valueOf(valueString);
}
}
protected static class FloatFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
return Float.valueOf(valueString);
}
}
protected static class DoubleFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
return Double.valueOf(valueString);
}
}
protected static class ByteFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
return Byte.valueOf(valueString);
}
}
protected static class BigDecimalFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
return new BigDecimal(valueString);
}
}
protected static class BigIntegerFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
return new BigInteger(valueString);
}
}
/**
* Date
*/
protected static class DateFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
return XmlDomHelper.S2D(valueString);
}
}
protected static class SqlDateFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
Date date = XmlDomHelper.S2D(valueString);
return new java.sql.Date(date.getTime());
}
}
protected static class SqlTimeFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
Date date = XmlDomHelper.S2D(valueString);
return new java.sql.Time(date.getTime());
}
}
protected static class SqlTimestampFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
Date date = XmlDomHelper.S2D(valueString);
return new java.sql.Timestamp(date.getTime());
}
}
/**
* Boolean
*/
protected static class BooleanFactory implements ValueFactory {
public Object newValueInstance(String valueString) {
return XmlDomHelper.S2B(valueString);
}
}
//
// Back:
//
public static Object string2value(boolean binary, String valueString, boolean origValue, ColumnType type, String columnName) {
Object value = null;
try {
if (binary) {
value = readUnknownBinary(valueString, origValue);
} else if (type.isString()) {
value = valueString;
} else if (type.isBoolean()) {
value = XmlDomHelper.S2B(valueString);
} else if (type.getValueClass() == Long.class) {
value = XmlDomHelper.S2L(valueString);
} else if (type.isNumeric()) {
value = XmlDomHelper.S2BigDecimal(valueString);
} else if (type.isBinary()) {
if (Blob.class.isAssignableFrom(type.getValueClass())) {
if (!origValue) {
BASE64Decoder decoder = new BASE64Decoder();
byte [] bytes = decoder.decodeBuffer(valueString);
value = new DetachedBlobImpl(bytes);
} else {
value = DetachedBlobImpl.NULL_BLOB;
}
} else if (Clob.class.isAssignableFrom(type.getValueClass())) {
if (!origValue) {
value = new DetachedClobImpl(valueString);
} else {
value = DetachedClobImpl.NULL_CLOB;
}
} else if (InputStream.class.isAssignableFrom(type.getValueClass())) {
if (!origValue) {
BASE64Decoder decoder = new BASE64Decoder();
byte [] bytes = decoder.decodeBuffer(valueString);
value = new ByteArrayInputStream(bytes);
} else {
value = NULL_BYTE_ARRAY_INPUT_STREAM;
}
} else {
value = readUnknownBinary(valueString, origValue);
}
} else if (type.isDate()) {
value = XmlDomHelper.S2D(valueString);
} else if (type.isBoolean()) {
value = XmlDomHelper.S2B(valueString);
} else if (type.isObject()) {
value = readUnknownBinary(valueString, origValue);
} else {
System.err.println("ERROR: XmlPersistentObjectInputStream::strings2values: Cannot handle type " + type);
}
} catch (Exception e) {
throw new XmlRuntimeException("Cannot convert string of type [" + type +
"], column [" + columnName + "] to value", e);
}
return value;
}
public static Object string2value(String className, String valueString, boolean binary) throws IOException, ClassNotFoundException {
Object value = null;
if (valueString != null) {
if (binary) {
value = string2unknownBinary(valueString);
} else if (String.class.getName().equals(className)) {
value = valueString;
} else if (isNumericClass(className)
|| isDateClass(className)
|| isBooleanClass(className)) {
value = string2value0(className, valueString);
} else {
value = string2unknownBinary(valueString);
}
}
return value;
}
protected static Object string2value0(String className, String valueString) {
if (valueString == null) {
return null;
}
ValueFactory valueFactory = (ValueFactory) VALUE_FACTORIES.get(className);
if (valueFactory == null) {
throw new XmlRuntimeException("Cannot find valueFactory for className " + className);
}
return valueFactory.newValueInstance(valueString);
}
protected static Object readUnknownBinary(String valueString, boolean origValue) throws IOException, ClassNotFoundException {
Object value;
if (!origValue) {
value = string2unknownBinary(valueString);
} else {
value = ColumnType.NULL_BINARY_OBJECT;
}
return value;
}
protected static Object string2unknownBinary(String valueString) throws IOException, ClassNotFoundException {
BASE64Decoder decoder = new BASE64Decoder();
byte [] bytes = decoder.decodeBuffer(valueString);
ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
ObjectInputStream in = new ObjectInputStream(bin);
return in.readObject();
}
}
|