package serializers.avro;
import data.media.*;
import org.apache.avro.Schema;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.io.DecoderFactory;
import org.apache.avro.io.BinaryEncoder;
import org.apache.avro.io.BinaryDecoder;
import serializers.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AvroGeneric
{
public static void register(TestGroups groups)
{
groups.media.add(MediaTransformer, new GenericSerializer(Avro.Media.sMediaContent),
new SerFeatures(
SerFormat.BIN_CROSSLANG,
SerGraph.FLAT_TREE,
SerClass.MANUAL_OPT,
""
)
);
}
// ------------------------------------------------------------
// Serializer (just one class)
private static final DecoderFactory DECODER_FACTORY
= DecoderFactory.get();
private static final EncoderFactory ENCODER_FACTORY
= EncoderFactory.get();
public static class GenericSerializer extends Serializer<GenericRecord>
{
public String getName() { return "avro-generic"; }
private final GenericDatumWriter<GenericRecord> WRITER;
private final GenericDatumReader<GenericRecord> READER;
private BinaryEncoder encoder;
private BinaryDecoder decoder;
public GenericSerializer(Schema schema)
{
WRITER = new GenericDatumWriter<GenericRecord>(schema);
READER = new GenericDatumReader<GenericRecord>(schema);
}
public GenericRecord deserialize(byte[] array) throws Exception
{
decoder = DECODER_FACTORY.binaryDecoder(array, decoder);
return READER.read(null, decoder);
}
public byte[] serialize(GenericRecord data) throws IOException
{
ByteArrayOutputStream out = outputStream(data);
encoder = ENCODER_FACTORY.binaryEncoder(out, encoder);
WRITER.write(data, encoder);
encoder.flush();
return out.toByteArray();
}
}
// ------------------------------------------------------------
// MediaTransformer
public static final Schema sMediaContent = serializers.avro.media.MediaContent.SCHEMA$;
public static final Transformer<MediaContent,GenericRecord> MediaTransformer = new MediaTransformer<GenericRecord>()
{
@SuppressWarnings("unused")
private final Schema sImage = serializers.avro.media.Image.SCHEMA$;
private final Schema sMedia = serializers.avro.media.Media.SCHEMA$;
@SuppressWarnings("unused")
private final Schema sImages = sMediaContent.getField("images").schema();
@SuppressWarnings("unused")
private final Schema sPersons = sMedia.getField("persons").schema();
public GenericRecord[] resultArray(int size) {
return new GenericRecord[size];
}
// ----------------------------------------------------------
// Forward
public GenericRecord forward(MediaContent mc)
{
GenericRecord content = new GenericData.Record(Avro.Media.sMediaContent);
content.put("media", forwardMedia(mc.media));
GenericData.Array<GenericRecord> images = new GenericData.Array<GenericRecord>(mc.images.size(), Avro.Media.sImages);
for (Image image : mc.images) {
images.add(forwardImage(image));
}
content.put("images", images);
return content;
}
private GenericRecord forwardMedia(Media media)
{
GenericRecord m = new GenericData.Record(Avro.Media.sMedia);
m.put("uri", media.uri);
m.put("format", media.format);
if (media.title != null) {
m.put("title", media.title);
}
m.put("duration", media.duration);
if (media.hasBitrate) {
m.put("bitrate", media.bitrate);
}
GenericData.Array<CharSequence> persons = new GenericData.Array<CharSequence>(media.persons.size(), Avro.Media.sPersons);
for (String p : media.persons) {
persons.add(p);
}
m.put("persons", persons);
m.put("player", forwardPlayer(media.player));
m.put("height", media.height);
m.put("width", media.width);
m.put("size", media.size);
if (media.copyright != null) {
m.put("copyright", media.copyright);
}
return m;
}
public int forwardPlayer(Media.Player p)
{
switch (p) {
case JAVA: return 1;
case FLASH: return 2;
default:
throw new AssertionError("invalid case: " + p);
}
}
private GenericRecord forwardImage(Image image)
{
GenericRecord i = new GenericData.Record(Avro.Media.sImage);
i.put("uri", image.uri);
i.put("width", image.width);
i.put("height", image.height);
i.put("size", forwardSize(image.size));
if (image.title != null) {
i.put("title", image.title);
}
return i;
}
public int forwardSize(Image.Size s)
{
switch (s) {
case SMALL: return 1;
case LARGE: return 2;
default:
throw new AssertionError("invalid case: " + s);
}
}
// ----------------------------------------------------------
// Reverse
public MediaContent reverse(GenericRecord mc)
{
@SuppressWarnings("unchecked")
GenericData.Array<GenericRecord> gimages = (GenericData.Array<GenericRecord>) mc.get("images");
List<Image> images = new ArrayList<Image>((int) gimages.size());
for (GenericRecord image : gimages) {
images.add(reverseImage(image));
}
return new MediaContent(reverseMedia((GenericRecord) mc.get("media")), images);
}
private Media reverseMedia(GenericRecord media)
{
// Media
@SuppressWarnings("unchecked")
GenericData.Array<CharSequence> gpersons = (GenericData.Array<CharSequence>) media.get("persons");
List<String> persons = new ArrayList<String>((int) gpersons.size());
for (CharSequence person : gpersons) {
persons.add(person.toString());
}
// Optional fields.
CharSequence title = (CharSequence) media.get("title");
Integer bitrate = (Integer) media.get("bitrate");
CharSequence copyright = (CharSequence) media.get("copyright");
return new Media(
((CharSequence) media.get("uri")).toString(),
title != null ? title.toString() : null,
(Integer) media.get("width"),
(Integer) media.get("height"),
((CharSequence) media.get("format")).toString(),
(Long) media.get("duration"),
(Long) media.get("size"),
bitrate != null ? bitrate : 0,
bitrate != null,
persons,
reversePlayer((Integer) media.get("player")),
copyright != null ? copyright.toString() : null
);
}
public Media.Player reversePlayer(int p)
{
switch (p) {
case 1: return Media.Player.JAVA;
case 2: return Media.Player.FLASH;
default: throw new AssertionError("invalid case: " + p);
}
}
private Image reverseImage(GenericRecord image)
{
CharSequence title = (CharSequence) image.get("title");
return new Image(
((CharSequence) image.get("uri")).toString(),
title == null ? null : title.toString(),
(Integer) image.get("width"),
(Integer) image.get("height"),
reverseSize((Integer) image.get("size")));
}
public Image.Size reverseSize(int s)
{
switch (s) {
case 1: return Image.Size.SMALL;
case 2: return Image.Size.LARGE;
default: throw new AssertionError("invalid case: " + s);
}
}
public MediaContent shallowReverse(GenericRecord mc)
{
return new MediaContent(reverseMedia((GenericRecord) mc.get("media")), Collections.<Image>emptyList());
}
};
}