package serializers.javaxjson; import static data.media.FieldMapping.*; import java.io.*; import java.util.*; import javax.json.spi.*; import javax.json.stream.*; import javax.json.stream.JsonParser.Event; import org.apache.activemq.util.buffer.ByteArrayInputStream; import serializers.*; import data.media.*; /** * Base class for benchmark using the streaming capabilities of javax.json. * <p> * Code is based of JacksonJsonManual; first copy/pasted then modified to fit * javax.json classes. There was a "fast" path version, but given that there's * no optimization possible with the API (no nextFieldName like there is in * Jackson), the only overhead we have here is the mapping between field name * and index. */ public abstract class JavaxJsonStream extends Serializer<MediaContent> { private final JsonProvider json; public JavaxJsonStream(JsonProvider json) { this.json = json; } @Override public final byte[] serialize(MediaContent content) throws IOException { ByteArrayOutputStream baos = outputStream(content); JsonGenerator generator = constructGenerator(baos); writeMediaContent(generator, content); generator.close(); return baos.toByteArray(); } @Override public final MediaContent deserialize(byte[] array) throws IOException { JsonParser parser = constructParser(array); MediaContent mc = readMediaContent(parser); parser.close(); return mc; } private JsonGenerator constructGenerator(ByteArrayOutputStream baos) { return json.createGenerator(baos); } private JsonParser constructParser(byte[] array) { return json.createParser(new ByteArrayInputStream(array)); } ////////////////////////////////////////////////// // Serialization ////////////////////////////////////////////////// protected void writeMediaContent(JsonGenerator generator, MediaContent content) throws IOException { generator.writeStartObject(); generator.writeStartObject(FULL_FIELD_NAME_MEDIA); writeMedia(generator, content.media); generator.writeStartArray(FULL_FIELD_NAME_IMAGES); for (Image i : content.images) { writeImage(generator, i); } generator.writeEnd(); generator.writeEnd(); } private void writeMedia(JsonGenerator generator, Media media) throws IOException { generator.write(FULL_FIELD_NAME_PLAYER, media.player.name()); generator.write(FULL_FIELD_NAME_URI, media.uri); if (media.title != null) { generator.write(FULL_FIELD_NAME_TITLE, media.title); } generator.write(FULL_FIELD_NAME_WIDTH, media.width); generator.write(FULL_FIELD_NAME_HEIGHT, media.height); generator.write(FULL_FIELD_NAME_FORMAT, media.format); generator.write(FULL_FIELD_NAME_DURATION, media.duration); generator.write(FULL_FIELD_NAME_SIZE, media.size); if (media.hasBitrate) { generator.write(FULL_FIELD_NAME_BITRATE, media.bitrate); } if (media.copyright != null) { generator.write(FULL_FIELD_NAME_COPYRIGHT, media.copyright); } generator.writeStartArray(FULL_FIELD_NAME_PERSONS); for (String person : media.persons) { generator.write(person); } generator.writeEnd(); generator.writeEnd(); } private void writeImage(JsonGenerator generator, Image image) throws IOException { generator.writeStartObject(); generator.write(FULL_FIELD_NAME_URI, image.uri); if (image.title != null) { generator.write(FULL_FIELD_NAME_TITLE, image.title); } generator.write(FULL_FIELD_NAME_WIDTH, image.width); generator.write(FULL_FIELD_NAME_HEIGHT, image.height); generator.write(FULL_FIELD_NAME_SIZE, image.size.name()); generator.writeEnd(); } ////////////////////////////////////////////////// // Deserialization ////////////////////////////////////////////////// protected MediaContent readMediaContent(JsonParser parser) throws IOException { MediaContent mc = new MediaContent(); Event current; if ((current = parser.next()) != Event.START_OBJECT) { reportIllegal(parser, current, Event.START_OBJECT); } while ((current = parser.next()) == Event.KEY_NAME) { String field = parser.getString(); Integer I = fullFieldToIndex.get(field); if (I != null) { switch (I) { case FIELD_IX_MEDIA: mc.media = readMedia(parser); continue; case FIELD_IX_IMAGES: mc.images = readImages(parser); continue; } } throw new IllegalStateException("Unexpected field '" + field + "'"); } verifyCurrent(parser, current, Event.END_OBJECT); if (mc.media == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_MEDIA); if (mc.images == null) mc.images = new ArrayList<Image>(); return mc; } private Media readMedia(JsonParser parser) throws IOException { Event current; if ((current = parser.next()) != Event.START_OBJECT) { reportIllegal(parser, current, Event.START_OBJECT); } Media media = new Media(); boolean haveWidth = false; boolean haveHeight = false; boolean haveDuration = false; boolean haveSize = false; while ((current = parser.next()) == Event.KEY_NAME) { String field = parser.getString(); Integer I = fullFieldToIndex.get(field); if (I != null) { switch (I) { case FIELD_IX_PLAYER: current = parser.next(); media.player = Media.Player.find(parser.getString()); continue; case FIELD_IX_URI: current = parser.next(); media.uri = parser.getString(); continue; case FIELD_IX_TITLE: current = parser.next(); media.title = parser.getString(); continue; case FIELD_IX_WIDTH: current = parser.next(); media.width = parser.getInt(); haveWidth = true; continue; case FIELD_IX_HEIGHT: current = parser.next(); media.height = parser.getInt(); haveHeight = true; continue; case FIELD_IX_FORMAT: current = parser.next(); media.format = parser.getString(); continue; case FIELD_IX_DURATION: current = parser.next(); media.duration = parser.getInt(); haveDuration = true; continue; case FIELD_IX_SIZE: current = parser.next(); media.size = parser.getInt(); haveSize = true; continue; case FIELD_IX_BITRATE: current = parser.next(); media.bitrate = parser.getInt(); media.hasBitrate = true; continue; case FIELD_IX_PERSONS: media.persons = readPersons(parser); continue; case FIELD_IX_COPYRIGHT: current = parser.next(); media.copyright = parser.getString(); continue; } } throw new IllegalStateException("Unexpected field '" + field + "'"); } verifyCurrent(parser, current, Event.END_OBJECT); if (media.uri == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_URI); if (!haveWidth) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_WIDTH); if (!haveHeight) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_HEIGHT); if (media.format == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_FORMAT); if (!haveDuration) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_DURATION); if (!haveSize) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_SIZE); if (media.persons == null) media.persons = new ArrayList<String>(); if (media.player == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_PLAYER); return media; } private List<Image> readImages(JsonParser parser) throws IOException { Event current; if ((current = parser.next()) != Event.START_ARRAY) { reportIllegal(parser, current, Event.START_ARRAY); } List<Image> images = new ArrayList<Image>(); while ((current = parser.next()) == Event.START_OBJECT) { images.add(readImage(parser)); } verifyCurrent(parser, current, Event.END_ARRAY); return images; } private List<String> readPersons(JsonParser parser) throws IOException { Event current; if ((current = parser.next()) != Event.START_ARRAY) { reportIllegal(parser, current, Event.START_ARRAY); } List<String> persons = new ArrayList<String>(); while ((current = parser.next()) == Event.VALUE_STRING) { persons.add(parser.getString()); } verifyCurrent(parser, current, Event.END_ARRAY); return persons; } private Image readImage(JsonParser parser) throws IOException { Event current; boolean haveWidth = false; boolean haveHeight = false; Image image = new Image(); while ((current = parser.next()) == Event.KEY_NAME) { String field = parser.getString(); // read value token (or START_ARRAY) current = parser.next(); Integer I = fullFieldToIndex.get(field); if (I != null) { switch (I) { case FIELD_IX_URI: image.uri = parser.getString(); continue; case FIELD_IX_TITLE: image.title = parser.getString(); continue; case FIELD_IX_WIDTH: image.width = parser.getInt(); haveWidth = true; continue; case FIELD_IX_HEIGHT: image.height = parser.getInt(); haveHeight = true; continue; case FIELD_IX_SIZE: image.size = Image.Size.valueOf(parser.getString()); continue; } } throw new IllegalStateException("Unexpected field '" + field + "'"); } if (image.uri == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_URI); if (!haveWidth) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_WIDTH); if (!haveHeight) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_HEIGHT); if (image.size == null) throw new IllegalStateException("Missing field: " + FULL_FIELD_NAME_SIZE); verifyCurrent(parser, current, Event.END_OBJECT); return image; } private final void verifyCurrent(JsonParser parser, Event current, Event expToken) throws IOException { if (current != expToken) { reportIllegal(parser, current, expToken); } } private void reportIllegal(JsonParser parser, Event current, Event expToken) throws IOException { String msg = "Expected token " + expToken + "; got " + current; if (current == Event.KEY_NAME) { msg += " (current field name '" + parser.getString() + "')"; } msg += ", location: " + parser.getLocation(); throw new IllegalStateException(msg); } }