de.timroes.axmlrpc.serializer.SerializerHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aXMLRPC Show documentation
Show all versions of aXMLRPC Show documentation
Lightweight Java XML-RPC working also on Android.
package de.timroes.axmlrpc.serializer;
import de.timroes.axmlrpc.XMLRPCClient;
import de.timroes.axmlrpc.XMLRPCException;
import de.timroes.axmlrpc.XMLUtil;
import de.timroes.axmlrpc.xmlcreator.XmlElement;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import org.w3c.dom.Element;
/**
* The serializer handler serializes and deserializes objects.
* It takes an object, determine its type and let the responsible handler serialize it.
* For deserialization it looks at the xml tag around the element.
*
* @author Tim Roes
*/
public class SerializerHandler {
public static final String TYPE_STRING = "string";
public static final String TYPE_BOOLEAN = "boolean";
public static final String TYPE_INT = "int";
public static final String TYPE_INT2 = "i4";
public static final String TYPE_LONG = "i8";
public static final String TYPE_DOUBLE = "double";
public static final String TYPE_DATETIME = "dateTime.iso8601";
public static final String TYPE_STRUCT = "struct";
public static final String TYPE_ARRAY = "array";
public static final String TYPE_BASE64 = "base64";
public static final String TYPE_NULL = "nil";
private StringSerializer string;
private BooleanSerializer bool = new BooleanSerializer();
private IntSerializer integer = new IntSerializer();
private LongSerializer long8 = new LongSerializer();
private StructSerializer struct;
private DoubleSerializer floating = new DoubleSerializer();
private DateTimeSerializer datetime;
private ArraySerializer array;
private Base64Serializer base64 = new Base64Serializer();
private NullSerializer nil = new NullSerializer();
private int flags;
public SerializerHandler(){
this(XMLRPCClient.FLAGS_DEBUG);
}
public SerializerHandler(int flags) {
this.flags = flags;
string = new StringSerializer(
(flags & XMLRPCClient.FLAGS_NO_STRING_ENCODE) == 0,
(flags & XMLRPCClient.FLAGS_NO_STRING_DECODE) == 0
);
struct = new StructSerializer(this);
array = new ArraySerializer(this);
datetime = new DateTimeSerializer((flags & XMLRPCClient.FLAGS_ACCEPT_NULL_DATES) != 0);
}
/**
* Deserializes an incoming xml element to an java object.
* The xml element must be the value element around the type element.
* The type of the returning object depends on the type tag.
*
* @param element An type element from within a value tag.
* @return The deserialized object.
* @throws XMLRPCException Will be thrown whenever an error occurs.
*/
public Object deserialize(Element element) throws XMLRPCException {
if(!XMLRPCClient.VALUE.equals(element.getNodeName())) {
throw new XMLRPCException("Value tag is missing around value.");
}
if(!XMLUtil.hasChildElement(element.getChildNodes())) {
// Value element doesn't contain a child element
if((flags & XMLRPCClient.FLAGS_DEFAULT_TYPE_STRING) != 0) {
return string.deserialize(element);
} else {
throw new XMLRPCException("Missing type element inside of value element.");
}
}
// Grep type element from inside value element
Element childElement = XMLUtil.getOnlyChildElement(element.getChildNodes());
Serializer s;
String type;
// If FLAGS_IGNORE_NAMESPACE has been set, only use local name.
if((flags & XMLRPCClient.FLAGS_IGNORE_NAMESPACES) != 0) {
type = childElement.getLocalName() == null ? childElement.getNodeName() : childElement.getLocalName();
} else {
type = childElement.getNodeName();
}
if((flags & XMLRPCClient.FLAGS_NIL) != 0 && TYPE_NULL.equals(type)) {
s = nil;
} else if(TYPE_STRING.equals(type)) {
s = string;
} else if(TYPE_BOOLEAN.equals(type)) {
s = bool;
} else if(TYPE_DOUBLE.equals(type)) {
s = floating;
} else if (TYPE_INT.equals(type) || TYPE_INT2.equals(type)) {
s = integer;
} else if(TYPE_DATETIME.equals(type)) {
s = datetime;
} else if (TYPE_LONG.equals(type)) {
if((flags & XMLRPCClient.FLAGS_8BYTE_INT) != 0) {
s = long8;
} else {
throw new XMLRPCException("8 byte integer is not in the specification. "
+ "You must use FLAGS_8BYTE_INT to enable the i8 tag.");
}
} else if(TYPE_STRUCT.equals(type)) {
s = struct;
} else if(TYPE_ARRAY.equals(type)) {
s = array;
} else if(TYPE_BASE64.equals(type)) {
s = base64;
} else {
throw new XMLRPCException("No deserializer found for type '" + type + "'.");
}
return s.deserialize(childElement);
}
/**
* Serialize an object to its representation as an xml element.
* The xml element will be the type element for the use within a value tag.
*
* @param object The object that should be serialized.
* @return The xml representation of this object.
* @throws XMLRPCException Will be thrown, if an error occurs (e.g. the object
* cannot be serialized to an xml element.
*/
public XmlElement serialize(Object object) throws XMLRPCException {
Serializer s;
if((flags & XMLRPCClient.FLAGS_NIL) != 0 && object == null) {
s = nil;
} else if(object instanceof String) {
s = string;
} else if(object instanceof Boolean) {
s = bool;
} else if(object instanceof Double || object instanceof Float
|| object instanceof BigDecimal) {
s = floating;
} else if (object instanceof Integer || object instanceof Short
|| object instanceof Byte) {
s = integer;
} else if(object instanceof Long) {
// Check whether the 8 byte integer flag was set.
if((flags & XMLRPCClient.FLAGS_8BYTE_INT) != 0) {
s = long8;
} else {
// Allow long values as long as their fit within the 4 byte integer range.
long l = (Long)object;
if(l > Integer.MAX_VALUE || l < Integer.MIN_VALUE) {
throw new XMLRPCException("FLAGS_8BYTE_INT must be set, if values "
+ "outside the 4 byte integer range should be transfered.");
} else {
s = integer;
}
}
} else if(object instanceof Date) {
s = datetime;
} else if(object instanceof Calendar) {
object = ((Calendar)object).getTime();
s = datetime;
} else if (object instanceof Map) {
s = struct;
} else if(object instanceof byte[]) {
byte[] old = (byte[])object;
Byte[] boxed = new Byte[old.length];
for(int i = 0; i < boxed.length; i++) {
boxed[i] = new Byte(old[i]);
}
object = boxed;
s = base64;
} else if(object instanceof Byte[]) {
s = base64;
} else if(object instanceof Iterable> || object instanceof Object[]) {
s = array;
} else {
throw new XMLRPCException("No serializer found for type '"
+ object.getClass().getName() + "'.");
}
return s.serialize(object);
}
}