package serializers.xml;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import com.thoughtworks.xstream.io.xml.XppDriver;
import data.media.Image;
import data.media.Media;
import data.media.MediaContent;
import data.media.Media.Player;
import data.media.Image.Size;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import serializers.*;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import com.thoughtworks.xstream.io.xml.CompactWriter;
@SuppressWarnings("rawtypes")
public class XmlXStream
{
public static void register(TestGroups groups)
{
// The default XStream serializer.
// commented-out by dyu: the perf of the default sux.
/*groups.media.add(JavaBuiltIn.MediaTransformer, new ConverterSerializer<MediaContent>("xml/xstream",
new com.thoughtworks.xstream.XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
//return new PrettyPrintWriter(out, xmlFriendlyReplacer());
return new CompactWriter(out, xmlFriendlyReplacer());
}
}), EmptyConfiguration));*/
groups.media.add(JavaBuiltIn.mediaTransformer, new ConverterSerializer<MediaContent>("xml/xstream+c",
new com.thoughtworks.xstream.XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
//return new PrettyPrintWriter(out, xmlFriendlyReplacer());
return new CompactWriter(out, xmlFriendlyReplacer());
}
}), MediaConfiguration),
new SerFeatures(
SerFormat.XML,
SerGraph.FLAT_TREE,
SerClass.ZERO_KNOWLEDGE,
""
)
);
// commented-out by dyu: use the non-abbreviated version
/*groups.media.add(JavaBuiltIn.MediaTransformer, new ConverterSerializer<MediaContent>("xml/xstream+c-abbrev",
new com.thoughtworks.xstream.XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
//return new PrettyPrintWriter(out, xmlFriendlyReplacer());
return new CompactWriter(out, xmlFriendlyReplacer());
}
}), MediaConfigurationAbbreviated));*/
// Adapt each of the STAX handlers to use XStream
for (XmlStax.Handler h : XmlStax.HANDLERS) {
// TODO: This doesn't work yet. Need to properly handle optional fields in readMedia/readImage.
// commented-out by dyu: use the non-abbreviated version (+c) because the perf of the default sux.
//groups.media.add(JavaBuiltIn.MediaTransformer, XStream.<MediaContent>mkStaxSerializer(h, "", EmptyConfiguration));
groups.media.add(JavaBuiltIn.mediaTransformer, XmlXStream.<MediaContent>mkStaxSerializer(h, "+c", MediaConfiguration),
new SerFeatures(
SerFormat.XML,
SerGraph.FLAT_TREE,
SerClass.MANUAL_OPT,
""
)
);
//groups.media.add(JavaBuiltIn.MediaTransformer, XStream.<MediaContent>mkStaxSerializer(h, "+c-abbrev", MediaConfigurationAbbreviated));
}
}
private static <T> ConverterSerializer<T> mkStaxSerializer(final XmlStax.Handler handler, String suffix, Configuration config)
{
return new ConverterSerializer<T>("xml/xstream" + suffix + "-" + handler.name,
new com.thoughtworks.xstream.XStream(new StaxDriver() {
public XMLInputFactory getInputFactory() { return handler.inFactory; }
public XMLOutputFactory getOutputFactory() { return handler.outFactory; }
}), config);
}
public static final class ConverterSerializer<T> extends Serializer<T>
{
private String name;
private com.thoughtworks.xstream.XStream xstream;
public ConverterSerializer(String name, com.thoughtworks.xstream.XStream xstream, Configuration config)
{
this.name = name;
this.xstream = xstream;
config.run(xstream);
}
public String getName() { return name; }
public T deserialize(byte[] array) throws Exception
{
@SuppressWarnings("unchecked")
T value = (T) xstream.fromXML(new ByteArrayInputStream(array));
return value;
}
public byte[] serialize(T content) throws IOException
{
ByteArrayOutputStream baos = outputStream(content);
xstream.toXML(content, baos);
return baos.toByteArray();
}
}
public static abstract class Configuration
{
public abstract void run(com.thoughtworks.xstream.XStream xstream);
}
// -----------------------------------------------------------------------
// Serializer: Media
public static final Configuration EmptyConfiguration = new Configuration()
{
public void run(com.thoughtworks.xstream.XStream xstream) {}
};
public static final Configuration MediaConfiguration = new MediaConfiguration();
public static class MediaConfiguration extends Configuration
{
public void run(com.thoughtworks.xstream.XStream xstream)
{
xstream.alias("Image", Image.class);
xstream.registerConverter(new ImageConverter());
xstream.alias("Media", Media.class);
xstream.registerConverter(new MediaConverter());
xstream.alias("MediaContent", MediaContent.class);
xstream.registerConverter(new MediaContentConverter());
}
private static class MediaContentConverter implements Converter
{
public void marshal(Object obj, HierarchicalStreamWriter writer, MarshallingContext context)
{
MediaContent content = (MediaContent) obj;
writer.startNode("Media");
context.convertAnother(content.media);
writer.endNode();
for (Image image : content.images) {
writer.startNode("Image");
context.convertAnother(image);
writer.endNode();
}
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context)
{
reader.moveDown();
Media media = (Media) context.convertAnother(null, Media.class);
reader.moveUp();
List<Image> images = new ArrayList<Image>();
while (reader.hasMoreChildren()) {
reader.moveDown();
images.add((Image) context.convertAnother(images, Image.class));
reader.moveUp();
}
return new MediaContent(media, images);
}
@Override
public boolean canConvert(Class arg0)
{
return MediaContent.class.equals(arg0);
}
}
private static class ImageConverter implements Converter
{
public void marshal(Object obj, HierarchicalStreamWriter writer, MarshallingContext context)
{
Image image = (Image) obj;
writer.addAttribute("uri", image.uri);
if (image.title != null) writer.addAttribute("title", image.title);
writer.addAttribute("width", String.valueOf(image.width));
writer.addAttribute("height", String.valueOf(image.height));
writer.addAttribute("size", String.valueOf(image.size.ordinal()));
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context)
{
Image image = new Image();
image.uri = reader.getAttribute("uri");
image.title = reader.getAttribute("title");
image.width = Integer.valueOf(reader.getAttribute("width"));
image.height = Integer.valueOf(reader.getAttribute("height"));
image.size = Size.values()[Integer.valueOf(reader.getAttribute("size"))];
return image;
}
@Override
public boolean canConvert(Class arg0)
{
return Image.class.equals(arg0);
}
}
private static class MediaConverter implements Converter
{
public void marshal(Object obj, HierarchicalStreamWriter writer, MarshallingContext context)
{
Media media = (Media) obj;
writer.addAttribute("player", String.valueOf(media.player.ordinal()));
writer.addAttribute("uri", media.uri);
if (media.title != null) writer.addAttribute("title", media.title);
writer.addAttribute("width", String.valueOf(media.width));
writer.addAttribute("height", String.valueOf(media.height));
writer.addAttribute("format", media.format);
writer.addAttribute("duration", String.valueOf(media.duration));
writer.addAttribute("size", String.valueOf(media.size));
if (media.hasBitrate) writer.addAttribute("bitrate", String.valueOf(media.bitrate));
if (media.copyright != null) writer.addAttribute("copyright", media.copyright);
for (String p : media.persons)
{
writer.startNode("person");
writer.setValue(p);
writer.endNode();
}
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context)
{
Media media = new Media();
media.player = Player.values()[Integer.valueOf(reader.getAttribute("player"))];
media.uri = reader.getAttribute("uri");
media.title = reader.getAttribute("title");
media.width = Integer.valueOf(reader.getAttribute("width"));
media.height = Integer.valueOf(reader.getAttribute("height"));
media.format = reader.getAttribute("format");
media.duration = Long.valueOf(reader.getAttribute("duration"));
media.size = Long.valueOf(reader.getAttribute("size"));
String stringBitrate = reader.getAttribute("bitrate");
if (stringBitrate != null) {
media.hasBitrate = true;
media.bitrate = Integer.valueOf(stringBitrate);
}
media.copyright = reader.getAttribute("copyright");
List<String> persons = new ArrayList<String>();
while (reader.hasMoreChildren())
{
reader.moveDown();
persons.add(reader.getValue());
reader.moveUp();
}
media.persons = persons;
return media;
}
@Override
public boolean canConvert(Class arg0)
{
return Media.class.equals(arg0);
}
}
};
public static final Configuration MediaConfigurationAbbreviated = new MediaConfigurationAbbreviated();
public static class MediaConfigurationAbbreviated extends Configuration
{
public void run(com.thoughtworks.xstream.XStream xstream)
{
xstream.alias("im", Image.class);
xstream.registerConverter(new ImageConverter());
xstream.alias("md", Media.class);
xstream.registerConverter(new MediaConverter());
xstream.alias("mc", MediaContent.class);
xstream.registerConverter(new MediaContentConverter());
}
private static class MediaContentConverter implements Converter
{
public void marshal(Object obj, HierarchicalStreamWriter writer, MarshallingContext context)
{
MediaContent content = (MediaContent) obj;
writer.startNode("md");
context.convertAnother(content.media);
writer.endNode();
for (Image image : content.images) {
writer.startNode("im");
context.convertAnother(image);
writer.endNode();
}
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context)
{
reader.moveDown();
Media media = (Media) context.convertAnother(null, Media.class);
reader.moveUp();
List<Image> images = new ArrayList<Image>();
while (reader.hasMoreChildren()) {
reader.moveDown();
images.add((Image) context.convertAnother(images, Image.class));
reader.moveUp();
}
return new MediaContent(media, images);
}
@Override
public boolean canConvert(Class arg0)
{
return MediaContent.class.equals(arg0);
}
}
private static class ImageConverter implements Converter
{
public void marshal(Object obj, HierarchicalStreamWriter writer, MarshallingContext context)
{
Image image = (Image) obj;
writer.addAttribute("ul", image.uri);
if (image.title != null) writer.addAttribute("tl", image.title);
writer.addAttribute("wd", String.valueOf(image.width));
writer.addAttribute("hg", String.valueOf(image.height));
writer.addAttribute("sz", String.valueOf(image.size.ordinal()));
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context)
{
Image image = new Image();
image.uri = reader.getAttribute("ul");
image.title = reader.getAttribute("tl");
image.width = Integer.valueOf(reader.getAttribute("wd"));
image.height = Integer.valueOf(reader.getAttribute("hg"));
image.size = Size.values()[Integer.valueOf(reader.getAttribute("sz"))];
return image;
}
@Override
public boolean canConvert(Class arg0)
{
return Image.class.equals(arg0);
}
}
private static class MediaConverter implements Converter
{
public void marshal(Object obj, HierarchicalStreamWriter writer, MarshallingContext context)
{
Media media = (Media) obj;
writer.addAttribute("pl", String.valueOf(media.player.ordinal()));
writer.addAttribute("ul", media.uri);
if (media.title != null) writer.addAttribute("tl", media.title);
writer.addAttribute("wd", String.valueOf(media.width));
writer.addAttribute("hg", String.valueOf(media.height));
writer.addAttribute("fr", media.format);
writer.addAttribute("dr", String.valueOf(media.duration));
writer.addAttribute("sz", String.valueOf(media.size));
if (media.hasBitrate) writer.addAttribute("br", String.valueOf(media.bitrate));
if (media.copyright != null) writer.addAttribute("cp", media.copyright);
for (String p : media.persons)
{
writer.startNode("pr");
writer.setValue(p);
writer.endNode();
}
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context)
{
Media media = new Media();
media.player = Player.values()[Integer.valueOf(reader.getAttribute("pl"))];
media.uri = reader.getAttribute("ul");
media.title = reader.getAttribute("tl");
media.width = Integer.valueOf(reader.getAttribute("wd"));
media.height = Integer.valueOf(reader.getAttribute("hg"));
media.format = reader.getAttribute("fr");
media.duration = Long.valueOf(reader.getAttribute("dr"));
media.size = Long.valueOf(reader.getAttribute("sz"));
String stringBitrate = reader.getAttribute("br");
if (stringBitrate != null) {
media.hasBitrate = true;
media.bitrate = Integer.valueOf(stringBitrate);
}
media.copyright = reader.getAttribute("cp");
List<String> persons = new ArrayList<String>();
while (reader.hasMoreChildren())
{
reader.moveDown();
persons.add(reader.getValue());
reader.moveUp();
}
media.persons = persons;
return media;
}
@Override
public boolean canConvert(Class arg0)
{
return Media.class.equals(arg0);
}
}
};
}