/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.juniform;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.core.MessageUnpacker;
import org.msgpack.value.ArrayValue;
import org.msgpack.value.IntegerValue;
import org.msgpack.value.MapValue;
import org.msgpack.value.Value;
import org.msgpack.value.impl.ImmutableDoubleValueImpl;
/**
*
* @author acherkashin
*/
public class JUniformPackerMessagePack implements IJUniformPacker
{
private final static MessagePack _msgpack = new MessagePack();
// ---------------------------------------------------------------------- //
// PUBLIC
// ---------------------------------------------------------------------- //
@Override
public JUniformObject toUniformObjectFromStream(InputStream stream) {
MessageUnpacker unpacker = _msgpack.newUnpacker(stream);
return this.toUniformObjectFromUnpacker(unpacker);
}
public JUniformObject toUniformObjectFromUnpacker(MessageUnpacker unpacker) {
if (unpacker == null) {
return JUniformObject.OBJECT_NIL;
}
Value value;
try {
value = unpacker.unpackValue();
} catch (IOException ex) {
return JUniformObject.OBJECT_NIL;
}
return this.toUniformObjectFromObject(value);
}
@Override
public JUniformObject toUniformObjectFromString(String string) {
return this.toUniformObjectFromBytes(string.getBytes());
}
@Override
public JUniformObject toUniformObjectFromBytes(byte[] bytes) {
MessageUnpacker unpacker = _msgpack.newUnpacker(bytes);
return this.toUniformObjectFromUnpacker(unpacker);
}
@Override
public JUniformObject toUniformObjectFromObject(Object object) {
Object result = _toSimpleObjectFromValue(object);
if (result == null) {
return JUniformObject.OBJECT_NIL;
}
return new JUniformObject(result);
}
private Object _toSimpleObjectFromValue(Object object) {
if (object == null || !(object instanceof Value)) {
return null;
}
Value value = (Value)object;
if (value.isNilValue()) {
return null;
}
else if (value.isBooleanValue()) {
return value.asBooleanValue().getBoolean();
}
else if (value.isStringValue()) {
return value.asStringValue().toString();
}
else if (value.isIntegerValue()) {
IntegerValue innerValue = value.asIntegerValue();
if (innerValue.isInLongRange()) {
return innerValue.asLong();
} else if (innerValue.isInIntRange()) {
return innerValue.asInt();
} else if (innerValue.isInShortRange()) {
return innerValue.asShort();
} else if (innerValue.isInByteRange()) {
return innerValue.asByte();
}
return null;
}
else if (value.isNumberValue()) {
// shame on you, MessagePack
if (ImmutableDoubleValueImpl.class.equals(value.getClass())) {
ImmutableDoubleValueImpl innerValue = (ImmutableDoubleValueImpl)value;
return innerValue.toDouble();
}
return value.asNumberValue().toLong();
}
else if (value.isArrayValue()) {
ArrayList<Object> array = new ArrayList<>();
ArrayValue msgpackArray = value.asArrayValue();
Iterator<Value> it = msgpackArray.iterator();
while(it.hasNext()) {
Value inner = it.next();
array.add(this.toUniformObjectFromObject(inner));
}
return array;
}
else if (value.isMapValue()) {
Map<Object,Object> map = new HashMap<>();
MapValue msgpackMap = value.asMapValue();
Iterator<Map.Entry<Value,Value>> it = msgpackMap.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<Value,Value> entry = it.next();
map.put(
this._toSimpleObjectFromValue(entry.getKey()),
this.toUniformObjectFromObject(entry.getValue())
);
}
return map;
}
return JUniformObject.OBJECT_NIL;
}
@Override
public Object fromUniformObject(JUniformObject object) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
MessagePacker packer = _msgpack.newPacker(out);
try {
this._writeJUniformObjectToPacker(object, packer);
packer.close();
} catch (IOException ex) {
return null;
}
return out.toByteArray();
}
@Override
public byte[] fromUniformObjectToByteArray(JUniformObject object) {
Object result = this.fromUniformObject(object);
if (result == null) {
return null;
}
return (byte[])result;
}
@Override
public String fromUniformObjectToString(JUniformObject object) {
Object result = this.fromUniformObject(object);
if (result == null) {
return null;
}
byte[] bytes = (byte[])result;
return new String(bytes);
}
private void _writeJUniformObjectToPacker(JUniformObject object, MessagePacker packer) throws IOException {
if (object == null) {
packer.packNil();
}
else if (object.isMapValue()) {
packer.packMapHeader(object.getPropertiesCount());
Iterator<Map.Entry<Object,JUniformObject>> it = object.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Object,JUniformObject> pair = it.next();
this._writeSimpleObjectToPacker(pair.getKey(), packer);
this._writeJUniformObjectToPacker(pair.getValue(), packer);
}
} else if (object.isArrayValue()) {
packer.packArrayHeader(object.getElementsCount());
Iterator<JUniformObject> it = object.iterator();
while(it.hasNext()) {
this._writeJUniformObjectToPacker(it.next(), packer);
}
} else {
this._writeSimpleObjectToPacker(object.getValue(), packer);
}
}
private void _writeSimpleObjectToPacker(Object object, MessagePacker packer) throws IOException {
if (object == null) {
packer.packNil();
} else if (object instanceof Byte) {
packer.packByte((Byte)object);
} else if (object instanceof Boolean) {
packer.packBoolean((Boolean)object);
} else if (object instanceof Double) {
packer.packDouble((Double)object);
} else if (object instanceof Float) {
packer.packFloat((Float)object);
} else if (object instanceof Integer) {
packer.packInt((Integer)object);
} else if (object instanceof Long) {
packer.packLong((Long)object);
} else if (object instanceof Short) {
packer.packShort((Short)object);
} else if (object instanceof String) {
packer.packString((String)object);
} else {
packer.packNil();
}
}
}