package serializers.kryo;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import serializers.JavaBuiltIn;
import serializers.SerClass;
import serializers.SerFeatures;
import serializers.SerFormat;
import serializers.SerGraph;
import serializers.Serializer;
import serializers.TestGroup;
import serializers.TestGroups;
import serializers.Transformer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.CollectionSerializer;
import com.esotericsoftware.kryo.serializers.FieldSerializer;
import com.esotericsoftware.kryo.serializers.FieldSerializer.CachedField;
import data.media.Image;
import data.media.Image.Size;
import data.media.Media;
import data.media.MediaContent;
public class Kryo {
public static void register (TestGroups groups) {
register(groups.media, JavaBuiltIn.mediaTransformer, MediaTypeHandler);
}
private static <T, S> void register (TestGroup<T> group, Transformer<T, S> transformer, TypeHandler<S> handler) {
group.add(transformer, new DefaultSerializer<S>(handler, true, "kryo-serializer"),
new SerFeatures(SerFormat.BINARY,
SerGraph.FULL_GRAPH,
SerClass.ZERO_KNOWLEDGE,
"default") );
group.add(transformer, new DefaultSerializer<S>(handler, false, "kryo-flat"),
new SerFeatures(
SerFormat.BINARY,
SerGraph.FLAT_TREE,
SerClass.ZERO_KNOWLEDGE,
"default, no shared refs"));
group.add(transformer, new BasicSerializer<S>(handler, "kryo-flat-pre"),
new SerFeatures(SerFormat.BINARY,
SerGraph.FLAT_TREE,
SerClass.CLASSES_KNOWN,
"no shared refs, preregistered classes"));
group.add(transformer, new OptimizedSerializer<S>(handler),
new SerFeatures(SerFormat.BINARY,
SerGraph.FLAT_TREE,
SerClass.MANUAL_OPT,
"manually optimized"));
group.add(transformer, new CustomSerializer<S>(handler),
new SerFeatures( SerFormat.BINARY,
SerGraph.FLAT_TREE,
SerClass.MANUAL_OPT,
"manually optimized"));
}
// ------------------------------------------------------------
// Serializers
/** This is the most basic Kryo usage. Don't register anything go. */
public static class DefaultSerializer<T> extends Serializer<T> {
final com.esotericsoftware.kryo.Kryo kryo;
private final String name;
private final byte[] buffer = new byte[BUFFER_SIZE];
private final Output output = new Output(buffer, -1);
private final Input input = new Input(buffer);
private final Class<T> type;
boolean shared;
public DefaultSerializer (TypeHandler<T> handler,boolean shared, String name) {
this.name = name;
this.type = handler.type;
this.shared = shared;
this.kryo = new com.esotericsoftware.kryo.Kryo();
kryo.setReferences(shared);
kryo.setRegistrationRequired(false);
}
@SuppressWarnings("unchecked")
public T deserialize (byte[] array) {
input.setBuffer(array);
return (T) kryo.readObject(input, type);
}
public byte[] serialize (T content) {
output.setBuffer(buffer, -1);
kryo.writeObject(output, content);
return output.toBytes();
}
public void serializeItems (T[] items, OutputStream outStream) throws Exception {
output.setOutputStream(outStream);
for (int i = 0, n = items.length; i < n; ++i) {
kryo.writeClassAndObject(output, items[i]);
}
output.flush();
}
@SuppressWarnings("unchecked")
public T[] deserializeItems (InputStream inStream, int numberOfItems) throws IOException {
input.setInputStream(inStream);
MediaContent[] result = new MediaContent[numberOfItems];
for (int i = 0; i < numberOfItems; ++i) {
result[i] = (MediaContent) kryo.readClassAndObject(input);
}
return (T[])result;
}
public final String getName () {
return name;
}
}
/** This is slightly advanced Kryo usage. Just register the classes and go. */
public static class BasicSerializer<T> extends Serializer<T> {
private final Class<T> type;
final com.esotericsoftware.kryo.Kryo kryo;
private final String name;
private final byte[] buffer = new byte[BUFFER_SIZE];
private final Output output = new Output(buffer, -1);
private final Input input = new Input(buffer);
public BasicSerializer (TypeHandler<T> handler, String name) {
this.type = handler.type;
this.kryo = new com.esotericsoftware.kryo.Kryo();
kryo.setReferences(false);
kryo.setRegistrationRequired(true);
this.name = name;
handler.register(this.kryo);
}
public T deserialize (byte[] array) {
input.setBuffer(array);
return kryo.readObject(input, type);
}
public byte[] serialize (T content) {
output.setBuffer(buffer, -1);
kryo.writeObject(output, content);
return output.toBytes();
}
public void serializeItems (T[] items, OutputStream outStream) throws Exception {
output.setOutputStream(outStream);
for (int i = 0, n = items.length; i < n; ++i) {
kryo.writeObject(output, items[i]);
}
output.flush();
}
@SuppressWarnings("unchecked")
public T[] deserializeItems (InputStream inStream, int numberOfItems) throws IOException {
input.setInputStream(inStream);
MediaContent[] result = new MediaContent[numberOfItems];
for (int i = 0; i < numberOfItems; ++i) {
result[i] = kryo.readObject(input, MediaContent.class);
}
return (T[])result;
}
@Override
public final String getName () {
return name;
}
}
/** This shows how to configure individual Kryo serializersto reduce the serialized bytes. */
public static class OptimizedSerializer<T> extends BasicSerializer<T> {
public OptimizedSerializer (TypeHandler<T> handler) {
super(handler, "kryo-opt");
handler.optimize(this.kryo);
}
}
/** This shows how to use hand written serialization code with Kryo, while still leveraging Kryo for most of the work. A
* serializer for each class can be implemented, as it is here, or the classes to be serialized can implement an interface and
* host their own serialization code (similar to java.io.Externalizable). */
public static class CustomSerializer<T> extends BasicSerializer<T> {
public CustomSerializer (TypeHandler<T> handler) {
super(handler, "kryo-manual");
handler.registerCustom(this.kryo);
}
}
// ------------------------------------------------------------
public static abstract class TypeHandler<T> {
public final Class<T> type;
protected TypeHandler (Class<T> type) {
this.type = type;
}
public abstract void register (com.esotericsoftware.kryo.Kryo kryo);
public abstract void optimize (com.esotericsoftware.kryo.Kryo kryo);
public abstract void registerCustom (com.esotericsoftware.kryo.Kryo kryo);
}
// ------------------------------------------------------------
// Media
public static final TypeHandler<MediaContent> MediaTypeHandler = new TypeHandler<MediaContent>(MediaContent.class) {
public void register (com.esotericsoftware.kryo.Kryo kryo) {
kryo.register(ArrayList.class);
kryo.register(MediaContent.class);
kryo.register(Media.Player.class);
kryo.register(Media.class);
kryo.register(Image.Size.class);
kryo.register(Image.class);
}
@SuppressWarnings("rawtypes")
public void optimize (com.esotericsoftware.kryo.Kryo kryo) {
FieldSerializer imageSerializer = (FieldSerializer)kryo.getSerializer(Image.class);
imageSerializer.setFieldsCanBeNull(false);
imageSerializer.getField("title").setCanBeNull(true);
FieldSerializer mediaContentSerializer = (FieldSerializer)kryo.getSerializer(MediaContent.class);
mediaContentSerializer.setFieldsCanBeNull(false);
CachedField imagesField = mediaContentSerializer.getField("images");
CollectionSerializer imagesSerializer = new CollectionSerializer();
imagesSerializer.setElementsCanBeNull(false);
imagesField.setClass(ArrayList.class, imagesSerializer);
FieldSerializer mediaSerializer = new FieldSerializer(kryo, Media.class);
mediaSerializer.setFieldsCanBeNull(false);
mediaSerializer.getField("title").setCanBeNull(true);
mediaSerializer.getField("copyright").setCanBeNull(true);
CachedField mediaField = mediaContentSerializer.getField("media");
mediaField.setClass(Media.class, mediaSerializer);
CachedField personsField = mediaSerializer.getField("persons");
CollectionSerializer personsSerializer = new CollectionSerializer();
personsSerializer.setElementsCanBeNull(false);
personsField.setClass(ArrayList.class, personsSerializer);
}
public void registerCustom (com.esotericsoftware.kryo.Kryo kryo) {
kryo.register(Image.class, new ImageSerializer());
kryo.register(MediaContent.class, new MediaContentSerializer(kryo));
kryo.register(Media.class, new MediaSerializer(kryo));
}
};
static class MediaContentSerializer extends com.esotericsoftware.kryo.Serializer<MediaContent> {
private CollectionSerializer _imagesSerializer;
public MediaContentSerializer (com.esotericsoftware.kryo.Kryo kryo) {
_imagesSerializer = new CollectionSerializer();
_imagesSerializer.setElementsCanBeNull(false);
}
public MediaContent read (com.esotericsoftware.kryo.Kryo kryo, Input input, Class<MediaContent> type) {
final Media media = kryo.readObject(input, Media.class);
@SuppressWarnings("unchecked")
final List<Image> images = (List<Image>)kryo.readObject(input, ArrayList.class, _imagesSerializer);
return new MediaContent(media, images);
}
public void write (com.esotericsoftware.kryo.Kryo kryo, Output output, MediaContent obj) {
kryo.writeObject(output, obj.media);
kryo.writeObject(output, obj.images, _imagesSerializer);
}
}
static class MediaSerializer extends com.esotericsoftware.kryo.Serializer<Media> {
private final CollectionSerializer _personsSerializer;
public MediaSerializer (final com.esotericsoftware.kryo.Kryo kryo) {
_personsSerializer = new CollectionSerializer();
_personsSerializer.setElementsCanBeNull(false);
}
@SuppressWarnings("unchecked")
public Media read (com.esotericsoftware.kryo.Kryo kryo, Input input, Class<Media> type) {
return new Media(input.readString(), input.readString(), input.readInt(true), input.readInt(true), input.readString(),
input.readLong(true), input.readLong(true), input.readInt(true), input.readBoolean(), (List<String>)kryo.readObject(
input, ArrayList.class, _personsSerializer), kryo.readObject(input, Media.Player.class), input.readString());
}
public void write (com.esotericsoftware.kryo.Kryo kryo, Output output, Media obj) {
output.writeString(obj.uri);
output.writeString(obj.title);
output.writeInt(obj.width, true);
output.writeInt(obj.height, true);
output.writeString(obj.format);
output.writeLong(obj.duration, true);
output.writeLong(obj.size, true);
output.writeInt(obj.bitrate, true);
output.writeBoolean(obj.hasBitrate);
kryo.writeObject(output, obj.persons, _personsSerializer);
kryo.writeObject(output, obj.player);
output.writeString(obj.copyright);
}
}
static class ImageSerializer extends com.esotericsoftware.kryo.Serializer<Image> {
public Image read (com.esotericsoftware.kryo.Kryo kryo, Input input, Class<Image> type) {
return new Image(input.readString(), input.readString(), input.readInt(true), input.readInt(true), kryo.readObject(
input, Size.class));
}
public void write (com.esotericsoftware.kryo.Kryo kryo, Output output, Image obj) {
output.writeString(obj.uri);
output.writeString(obj.title);
output.writeInt(obj.width, true);
output.writeInt(obj.height, true);
kryo.writeObject(output, obj.size);
}
}
}