All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.threerings.nexus.io.AbstractSerializer Maven / Gradle / Ivy

The newest version!
//
// Nexus Core - a framework for developing distributed applications
// http://github.com/threerings/nexus/blob/master/LICENSE

package com.threerings.nexus.io;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.threerings.nexus.distrib.DService;
import com.threerings.nexus.distrib.NexusException;
import com.threerings.nexus.distrib.NexusService;

/**
 * A basic {@link Serializer} implementation that handles standard types. This is extended by
 * generated serializers to add support for project classes.
 */
public abstract class AbstractSerializer implements Serializer
{
    // from interface Serializer
    public Class getClass (short code) {
        return nonNull(_classes.get(code), "Unknown class code ", code);
    }

    // from interface Serializer
    public Streamer getStreamer (short code) {
        return nonNull(_streamers.get(code), "Unknown class code ", code);
    }

    // from interface Serializer
    public DService.Factory getServiceFactory (short code) {
        return nonNull(_services.get(code), "Unknown service code ", code);
    }

    // from interface Serializer
    public short getCode (Class clazz) {
        return nonNull(_codes.get(clazz), "Unknown streamable class ", clazz);
    }

    // from interface Serializer
    public short getServiceCode (Class clazz) {
        return nonNull(_serviceCodes.get(clazz), "Unknown service class ", clazz);
    }

    // from interface Serializer
    public  Streamer writeStreamer (Streamable.Output out, T value) {
        if (value == null) {
            return this.writeClass(out, (short)0); // null streamer has code 0
        }

        // if the class is known, just look up the code and write it
        Class vclass = value.getClass();
        Short code = _codes.get(vclass);
        if (code != null) {
            return this.writeClass(out, code);
        }

        // if the class is some more obscure subtype of list/set/map, use the stock
        // streamer and cache this type with the same code
        if (value instanceof List) {
            _codes.put(vclass, code = _codes.get(ArrayList.class));
            return this.writeClass(out, code);
        } else if (value instanceof Set) {
            _codes.put(vclass, code = _codes.get(HashSet.class));
            return this.writeClass(out, code);
        } else if (value instanceof Map) {
            _codes.put(vclass, code = _codes.get(HashMap.class));
            return this.writeClass(out, code);
        }

        // otherwise: houston, we have a problem
        throw new NexusException("Requested to stream unknown type " + vclass);
    }

    @SuppressWarnings("unchecked")
    protected final  Streamer writeClass (Streamable.Output out, Short code) {
        out.writeShort(code);
        return (Streamer)_streamers.get(code);
    }

    protected void mapStreamer (Streamer streamer) {
        short code = (short)++_nextCode;
        _classes.put(code, streamer.getObjectClass());
        _streamers.put(code, streamer);
        _codes.put(streamer.getObjectClass(), code);
    }

    protected > void mapEnumStreamer (Class eclass) {
        mapStreamer(Streamers.create(eclass));
    }

    protected void mapService (DService.Factory factory, Class clazz) {
        short code = (short)++_nextServiceCode;
        _services.put(code, factory);
        _serviceCodes.put(clazz, code);
    }

    @SuppressWarnings("rawtypes")
    protected AbstractSerializer () {
        // map the streamers for our basic types
        mapStreamer(new Streamers.Streamer_Null());
        mapStreamer(new Streamers.Streamer_Boolean());
        mapStreamer(new Streamers.Streamer_Byte());
        mapStreamer(new Streamers.Streamer_Character());
        mapStreamer(new Streamers.Streamer_Short());
        mapStreamer(new Streamers.Streamer_Integer());
        mapStreamer(new Streamers.Streamer_Long());
        mapStreamer(new Streamers.Streamer_Float());
        mapStreamer(new Streamers.Streamer_Double());
        mapStreamer(new Streamers.Streamer_String());
        // fast path for common implementations; a slow path will catch all other types with a
        // series of instanceof checks
        mapStreamer(new Streamers.Streamer_List());
        mapStreamer(new Streamers.Streamer_Set());
        mapStreamer(new Streamers.Streamer_Map());

        // TEMP: map the core streamables manually while we lack a code generator
        mapStreamer(new com.threerings.nexus.distrib.Streamer_Address.OfKeyed());
        mapStreamer(new com.threerings.nexus.distrib.Streamer_Address.OfSingleton());
        mapStreamer(new com.threerings.nexus.distrib.Streamer_Address.OfAnonymous());
        mapStreamer(new com.threerings.nexus.distrib.Streamer_DMap.PutEvent());
        mapStreamer(new com.threerings.nexus.distrib.Streamer_DMap.RemoveEvent());
        mapStreamer(new com.threerings.nexus.distrib.Streamer_DSet.AddEvent());
        mapStreamer(new com.threerings.nexus.distrib.Streamer_DSet.RemoveEvent());
        mapStreamer(new com.threerings.nexus.distrib.Streamer_DValue.ChangeEvent());
        mapStreamer(new com.threerings.nexus.distrib.Streamer_DSignal.EmitEvent());
        mapStreamer(new com.threerings.nexus.net.Streamer_Downstream.Subscribe());
        mapStreamer(new com.threerings.nexus.net.Streamer_Downstream.SubscribeFailure());
        mapStreamer(new com.threerings.nexus.net.Streamer_Downstream.DispatchEvent());
        mapStreamer(new com.threerings.nexus.net.Streamer_Downstream.ServiceResponse());
        mapStreamer(new com.threerings.nexus.net.Streamer_Downstream.ServiceFailure());
        mapStreamer(new com.threerings.nexus.net.Streamer_Downstream.ObjectCleared());
        mapStreamer(new com.threerings.nexus.net.Streamer_Upstream.Subscribe());
        mapStreamer(new com.threerings.nexus.net.Streamer_Upstream.Unsubscribe());
        mapStreamer(new com.threerings.nexus.net.Streamer_Upstream.PostEvent());
        mapStreamer(new com.threerings.nexus.net.Streamer_Upstream.ServiceCall());
        // END TEMP
    }

    protected static  T nonNull (T value, String errmsg, Object data) {
        if (value == null) throw new NexusException(errmsg + data);
        return value;
    }

    protected int _nextCode = -1; // so that null gets zero
    protected int _nextServiceCode = 0; // services start at one, there's no null service

    protected final Map,Short> _codes = new HashMap,Short>();
    protected final Map> _streamers = new HashMap>();
    protected final Map> _classes = new HashMap>();

    protected final Map,Short> _serviceCodes = new HashMap,Short>();
    protected final Map> _services =
        new HashMap>();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy