Package com.tinkerpop.rexster.protocol.serializer.msgpack.templates

Source Code of com.tinkerpop.rexster.protocol.serializer.msgpack.templates.ResultsConverter

package com.tinkerpop.rexster.protocol.serializer.msgpack.templates;

import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.pipes.util.structures.Row;
import com.tinkerpop.pipes.util.structures.Table;
import com.tinkerpop.rexster.Tokens;
import org.msgpack.packer.Packer;
import org.msgpack.type.ArrayValue;
import org.msgpack.type.MapValue;
import org.msgpack.type.NilValue;
import org.msgpack.type.Value;
import org.msgpack.type.ValueFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* Universally useful msgpack object serialization and deserialization functions
*
* @author Blake Eggleston (bdeggleston.github.com)
*/
public class ResultsConverter {

    static Object serializeElementId(final Element element) {
        final Object id = element.getId();
        if (id.getClass().isPrimitive()) {
            return id;
        } else {
            return id.toString();
        }
    }

    static public void serializeObject(final Object object, final Packer packer) throws Exception {
        if (object == null) {
            packer.write(ValueFactory.createNilValue());
        } else if (object instanceof String || object instanceof Number || object instanceof Boolean) {
            packer.write(object);
        } else if (object instanceof Element) {
            try {
                final Element element = (Element) object;
                final Set<String> propertyKeys = element.getPropertyKeys();
                final int propertySize = propertyKeys.size();
                final boolean isVertex = !(element instanceof Edge);
                final int elementSize = (isVertex ? 2 : 5) + ((propertySize > 0) ? 1 : 0);

                packer.writeMapBegin(elementSize);
                packer.write(Tokens._ID);
                packer.write(serializeElementId(element));

                if (isVertex) {
                    packer.write(Tokens._TYPE);
                    packer.write(Tokens.VERTEX);
                } else {
                    final Edge edge = (Edge) element;
                    packer.write(Tokens._TYPE);
                    packer.write(Tokens.EDGE);
                    packer.write(Tokens._IN_V);
                    packer.write(serializeElementId(edge.getVertex(Direction.IN)));
                    packer.write(Tokens._OUT_V);
                    packer.write(serializeElementId(edge.getVertex(Direction.OUT)));
                    packer.write(Tokens._LABEL);
                    packer.write(edge.getLabel());
                }

                if (propertyKeys.size() > 0) {
                    packer.write(Tokens._PROPERTIES);
                    packer.writeMapBegin(propertySize);

                    final Iterator<String> itty = propertyKeys.iterator();
                    while (itty.hasNext()) {
                        final String propertyKey = itty.next();
                        packer.write(propertyKey);
                        serializeObject(element.getProperty(propertyKey), packer);
                    }

                    packer.writeMapEnd(false);
                }
                packer.writeMapEnd(false);
            } catch (Exception e) {
                // if a transaction gets closed and the element goes out of scope it may not serialize.  in these
                // cases the vertex will just be written as null.  this can happen during binding serialization.
                // specific case is doing this:
                // v = g.addVertex()
                // g.rollback()
                // in some graphs v will go out of scope, yet it is still on the bindings as a Vertex object.
                packer.writeNil();
            }
        } else if (object instanceof Map) {
            final Map map = (Map) object;
            packer.writeMapBegin(map.size());
            for (Object key : map.keySet()) {
                if(key instanceof Element) {
                    // restructure element -> x maps
                    // this is typical in Tree and Map returns where the key is an object value instead of a
                    // primitive.  MsgPack can't process keys that way so the data needs to be restructured
                    // so that it doesn't end up simply being toString'd
                    final Element element = (Element) key;
                    writeMapKey(element.getId(), packer);
                    final HashMap<String, Object> m = new HashMap<String, Object>();
                    m.put(Tokens._KEY, element);
                    m.put(Tokens._VALUE, map.get(key));
                    serializeObject(m, packer);
                } else {
                    writeMapKey(key, packer);
                    serializeObject(map.get(key), packer);
                }
            }
            packer.writeMapEnd();
        } else if (object instanceof Table) {
            final Table table = (Table) object;
            final Iterator<Row> rows = table.iterator();

            packer.writeArrayBegin(table.size());
            while (rows.hasNext()) {
                serializeObject(rows.next(), packer);
            }
            packer.writeArrayEnd();

        } else if (object instanceof Row) {
            final Row row = (Row) object;
            final List<String> columnNames = row.getColumnNames();

            packer.writeMapBegin(columnNames.size());
            for (String columnName : columnNames) {
                packer.write(columnName);
                serializeObject(row.getColumn(columnName), packer);
            }
            packer.writeMapEnd(false);

        } else if (object instanceof Iterable) {
            Collection contents;
            if (object instanceof Collection) {
                contents = (Collection) object;
            } else {
                contents = iterateToList(((Iterable) object).iterator());
            }

            packer.writeArrayBegin(contents.size());
            for (Object o : contents) {
                serializeObject(o, packer);
            }
            packer.writeArrayEnd();

        } else if (object instanceof Iterator) {
            //we need to know the array size before beginning serialization
            final Collection contents = iterateToList((Iterator) object);

            packer.writeArrayBegin(contents.size());
            for (Object o : contents) {
                serializeObject(o, packer);
            }
            packer.writeArrayEnd();

        } else if (object instanceof NilValue) {
            packer.write((NilValue) object);
        } else {
            packer.write(object.toString());
        }

    }

    private static void writeMapKey(final Object key, final Packer packer) throws IOException {
        // map keys must be something serializable by MsgPack.  don't get too fancy
        if (key instanceof String || key instanceof Number) {
            packer.write(key);
        } else {
            packer.write(key.toString());
        }
    }

    private static ArrayList<Object> iterateToList(final Iterator itty) {
        final ArrayList<Object> contents = new ArrayList<Object>();

        while (itty.hasNext()) {
            contents.add(itty.next());
        }
        return contents;
    }

    public static Object deserializeObject(final Value v) {
        Object o;

        //check for null first to avoid NullPointerException
        if (v == null) {
            o = null;
        } else if (v.isBooleanValue()) {
            o = v.asBooleanValue().getBoolean();
        } else if (v.isFloatValue()) {
            o = v.asFloatValue().getDouble();
        } else if (v.isIntegerValue()) {
            o = v.asIntegerValue().getLong();
        } else if (v.isArrayValue()) {
            final ArrayValue src = v.asArrayValue();
            final ArrayList<Object> dst = new ArrayList<Object>(src.size());
            for (int i = 0; i < src.size(); i++) {
                final Object val = deserializeObject(src.get(i));
                dst.add(i, val);
            }
            o = dst;
        } else if (v.isMapValue()) {
            final MapValue src = v.asMapValue();
            final HashMap<Object, Object> dst = new HashMap<Object, Object>(src.size());
            for (Map.Entry<Value, Value> entry : src.entrySet()) {
                final Object key = deserializeObject(entry.getKey());
                final Object val = deserializeObject(entry.getValue());
                dst.put(key, val);
            }
            o = dst;
        } else if (v.isNilValue()) {
            o = null;
        } else {
            // includes raw value
            o = v.asRawValue().getString();
        }
        return o;
    }
}
TOP

Related Classes of com.tinkerpop.rexster.protocol.serializer.msgpack.templates.ResultsConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.