/**
*
*/
package meetup.beeno.util;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Date;
import org.apache.log4j.Logger;
/**
* Support methods for implementing {@link java.io.Externalizable} interface.
*
* @author garyh
*
*/
public class IOUtil {
public static enum VALUE_TYPE {STRING, INT, LONG, FLOAT, DOUBLE, DATE, ENUM, OBJECT};
private static Logger log = Logger.getLogger(IOUtil.class);
public static void writeNullable( ObjectOutput out, Object value ) throws IOException {
if (value == null) {
out.writeBoolean(true);
}
else {
out.writeBoolean(false);
if (value instanceof String)
out.writeUTF((String)value);
else if (value instanceof Integer)
out.writeInt(((Integer)value).intValue());
else if (value instanceof Float)
out.writeFloat(((Float)value).floatValue());
else if (value instanceof Double)
out.writeDouble(((Double)value).doubleValue());
else if (value instanceof Long)
out.writeLong(((Long)value).longValue());
else if (value instanceof Date)
out.writeLong(((Date)value).getTime());
else if (value instanceof Enum)
out.writeUTF(((Enum)value).name());
else
out.writeObject(value);
}
}
public static void writeNullableWithType( ObjectOutput out, Object value ) throws IOException {
if (value == null) {
out.writeBoolean(true);
}
else {
out.writeBoolean(false);
if (value instanceof String) {
out.writeUTF(VALUE_TYPE.STRING.name());
out.writeUTF((String)value);
}
else if (value instanceof Integer) {
out.writeUTF(VALUE_TYPE.INT.name());
out.writeInt(((Integer)value).intValue());
}
else if (value instanceof Float) {
out.writeUTF(VALUE_TYPE.FLOAT.name());
out.writeFloat(((Float)value).floatValue());
}
else if (value instanceof Double) {
out.writeUTF(VALUE_TYPE.DOUBLE.name());
out.writeDouble(((Double)value).doubleValue());
}
else if (value instanceof Long) {
out.writeUTF(VALUE_TYPE.LONG.name());
out.writeLong(((Long)value).longValue());
}
else if (value instanceof Date) {
out.writeUTF(VALUE_TYPE.DATE.name());
out.writeLong(((Date)value).getTime());
}
else if (value instanceof Enum) {
out.writeUTF(VALUE_TYPE.ENUM.name());
out.writeUTF(value.getClass().getName());
out.writeUTF(((Enum)value).name());
}
else {
out.writeUTF(VALUE_TYPE.OBJECT.name());
out.writeObject(value);
}
}
}
public static Integer readInteger( ObjectInput in ) throws IOException {
return (in.readBoolean() ? null : new Integer(in.readInt()));
}
public static Long readLong( ObjectInput in ) throws IOException {
return (in.readBoolean() ? null : new Long(in.readLong()));
}
public static Float readFloat( ObjectInput in ) throws IOException {
return (in.readBoolean() ? null : new Float(in.readFloat()));
}
public static Double readDouble( ObjectInput in ) throws IOException {
return (in.readBoolean() ? null : new Double(in.readDouble()));
}
public static String readString( ObjectInput in ) throws IOException {
return (in.readBoolean() ? null : in.readUTF());
}
public static Date readDate( ObjectInput in ) throws IOException {
return (in.readBoolean() ? null : new Date(in.readLong()));
}
public static <T extends Enum<T>> T readEnum( ObjectInput in, Class<T> enumType ) throws IOException {
String enumName = readString(in);
if (enumName == null)
return null;
return Enum.valueOf(enumType, enumName);
}
/**
* Reads back a generic object (if not null) with no guarantee as to the
* returned type.
*/
public static Object readObject( ObjectInput in ) throws IOException, ClassNotFoundException {
if (in.readBoolean())
return null;
return in.readObject();
}
/**
* Reads an object from the input stream that has been serialized by
* calling {@link #writeNullableWithType(ObjectOutput, Object)}.
*
* Note: If called on a serialized object value that has not been written
* with the type, this will fail!
* @param in
* @return
* @throws IOException
*/
public static Object readWithType( ObjectInput in ) throws IOException, ClassNotFoundException {
if (in.readBoolean())
return null;
try {
VALUE_TYPE type = VALUE_TYPE.valueOf( in.readUTF() );
switch (type) {
case STRING:
return in.readUTF();
case INT:
return in.readInt();
case LONG:
return in.readLong();
case FLOAT:
return in.readFloat();
case DOUBLE:
return in.readDouble();
case DATE:
return new Date(in.readLong());
case ENUM:
try {
Class enumClass = Class.forName(in.readUTF());
return Enum.valueOf(enumClass, in.readUTF());
}
catch (Exception e) {
log.error("Error reading enum value from object input", e);
return null;
}
case OBJECT:
return in.readObject();
default:
log.warn("Invalid serialized value type!");
}
}
catch (IllegalArgumentException iae) {
log.error("Invalid serialized type reading from object input stream", iae);
}
return null;
}
}