package serializers.xml;
import static data.media.FieldMapping.FULL_FIELD_NAME_BITRATE;
import static data.media.FieldMapping.FULL_FIELD_NAME_COPYRIGHT;
import static data.media.FieldMapping.FULL_FIELD_NAME_DURATION;
import static data.media.FieldMapping.FULL_FIELD_NAME_FORMAT;
import static data.media.FieldMapping.FULL_FIELD_NAME_HEIGHT;
import static data.media.FieldMapping.FULL_FIELD_NAME_IMAGES;
import static data.media.FieldMapping.FULL_FIELD_NAME_MEDIA;
import static data.media.FieldMapping.FULL_FIELD_NAME_PERSONS;
import static data.media.FieldMapping.FULL_FIELD_NAME_PLAYER;
import static data.media.FieldMapping.FULL_FIELD_NAME_SIZE;
import static data.media.FieldMapping.FULL_FIELD_NAME_TITLE;
import static data.media.FieldMapping.FULL_FIELD_NAME_URI;
import static data.media.FieldMapping.FULL_FIELD_NAME_WIDTH;
import java.util.ArrayList;
import java.util.List;
import javax.xml.stream.*;
import data.media.Image;
import data.media.Media;
import data.media.MediaContent;
public class StaxDeserializer
{
protected final boolean _workingGetElementText;
public StaxDeserializer(boolean workingGetElementText)
{
_workingGetElementText = workingGetElementText;
}
public final MediaContent readDocument(XMLStreamReader parser) throws XMLStreamException
{
return readMediaContent(parser);
}
public final MediaContent[] readDocument(XMLStreamReader parser, int items) throws XMLStreamException
{
MediaContent[] result = new MediaContent[items];
searchTag(parser, XmlStax.STREAM_ROOT);
for (int i = 0; i < items; ++i) {
result[i] = readMediaContent(parser);
}
// and should have closing tag at this point
if (parser.nextTag() != XMLStreamConstants.END_ELEMENT) {
throw new IllegalStateException("Expected closing tag, got: "+parser.getEventType());
}
if (!XmlStax.STREAM_ROOT.equals(parser.getLocalName())) {
throw new IllegalStateException("Expected closing </"+XmlStax.STREAM_ROOT+">, got </"+parser.getLocalName()+">");
}
return result;
}
private MediaContent readMediaContent(XMLStreamReader parser) throws XMLStreamException
{
searchTag(parser, "mc");
Media media = readMedia(parser);
List<Image> images = new ArrayList<Image>();
if (parser.nextTag() != XMLStreamConstants.START_ELEMENT) {
throw new IllegalStateException("Expected <im>, no START_ELEMENT encountered but "+parser.getEventType());
}
do {
if (!FULL_FIELD_NAME_IMAGES.equals(parser.getLocalName())) {
throw new IllegalStateException("Expected <"+FULL_FIELD_NAME_IMAGES+">, got <"+parser.getLocalName()+">");
}
images.add(readImage(parser));
} while (parser.nextTag() == XMLStreamConstants.START_ELEMENT);
// and should have closing </mc> at this point
if (!"mc".equals(parser.getLocalName())) {
throw new IllegalStateException("Expected closing </mc>, got </"+parser.getLocalName()+">");
}
return new MediaContent(media, images);
}
private Image readImage (XMLStreamReader parser) throws XMLStreamException
{
Image image = new Image();
image.uri = readElement(parser, FULL_FIELD_NAME_URI);
image.title = readElement(parser, FULL_FIELD_NAME_TITLE);
image.width = Integer.parseInt(readElement(parser, FULL_FIELD_NAME_WIDTH));
image.height = Integer.parseInt(readElement(parser, FULL_FIELD_NAME_HEIGHT));
image.size = imageSize(readElement(parser, FULL_FIELD_NAME_SIZE));
// need to match close tag
if (parser.nextTag() != XMLStreamConstants.END_ELEMENT) {
throw new IllegalStateException("Expected closing </"+FULL_FIELD_NAME_IMAGES+">");
}
return image;
}
private Image.Size imageSize(String value) {
if (value == null) {
throw new IllegalStateException("Missing 'size' value for Image (null)");
}
return Image.Size.valueOf(value);
}
private Media readMedia (XMLStreamReader parser) throws XMLStreamException
{
Media media = new Media();
media.player = Media.Player.valueOf(readElement(parser, FULL_FIELD_NAME_PLAYER));
media.uri = readElement(parser, FULL_FIELD_NAME_URI);
media.title = readElementMaybe(parser, FULL_FIELD_NAME_TITLE);
media.width = Integer.parseInt(readElement(parser, FULL_FIELD_NAME_WIDTH));
media.height = Integer.parseInt(readElement(parser, FULL_FIELD_NAME_HEIGHT));
media.format = readElement(parser, FULL_FIELD_NAME_FORMAT);
media.duration = Long.parseLong(readElement(parser, FULL_FIELD_NAME_DURATION));
media.size = Long.parseLong(readElement(parser, FULL_FIELD_NAME_SIZE));
String bitrateString = readElement(parser, FULL_FIELD_NAME_BITRATE);
if (bitrateString != null) {
media.hasBitrate = true;
media.bitrate = Integer.parseInt(bitrateString);
}
media.copyright = readElementMaybe(parser, FULL_FIELD_NAME_COPYRIGHT);
searchTag(parser, FULL_FIELD_NAME_PERSONS);
List<String> persons = new ArrayList<String>();
do {
persons.add(_getElementText(parser));
} while (parser.nextTag() == XMLStreamConstants.START_ELEMENT
&& FULL_FIELD_NAME_PERSONS.equals(parser.getLocalName()));
if (!FULL_FIELD_NAME_MEDIA.equals(parser.getLocalName())) {
throw new IllegalStateException("Expected closing </"+FULL_FIELD_NAME_MEDIA+">, got </"+parser.getLocalName()+">");
}
media.persons = persons;
return media;
}
private String readElementMaybe(XMLStreamReader parser, String string) throws XMLStreamException
{
if (parser.getEventType() != XMLStreamConstants.START_ELEMENT) {
while (parser.next() != XMLStreamConstants.START_ELEMENT) { }
}
return (parser.getLocalName().equals(string)) ? _getElementText(parser) : null;
}
private String readElement(XMLStreamReader parser, String string) throws XMLStreamException
{
// If not at START_ELEMENT, find one (usually called when at END_ELEMENT)
if (parser.getEventType() != XMLStreamConstants.START_ELEMENT) {
while (parser.next() != XMLStreamConstants.START_ELEMENT) { }
}
while (true) {
if (parser.getLocalName().equals(string)) {
return _getElementText(parser);
}
while (parser.next() != XMLStreamConstants.START_ELEMENT) { }
}
}
protected void searchTag(XMLStreamReader parser, String string) throws XMLStreamException
{
// may already be located at the start element
if (parser.getEventType() == XMLStreamConstants.START_ELEMENT
&& parser.getLocalName().equals(string)) {
return;
}
while (true) {
if (parser.nextTag() == XMLStreamConstants.START_ELEMENT
&& parser.getLocalName().equals(string)) {
return;
}
}
}
private final String _getElementText(XMLStreamReader parser) throws XMLStreamException
{
if (_workingGetElementText) {
return parser.getElementText();
}
/* This is not optimal if there are more than two segments; but really
* it should not matter -- impls SHOULD implement getElementText() properly
* so this is just a fallback. Also, unlikely we'll get more than one segment
* in most cases.
*/
String text = null;
int t;
while (parser.hasNext()) {
t = parser.next();
if (t == XMLStreamConstants.END_ELEMENT) {
break;
}
if (t == XMLStreamConstants.CHARACTERS || t == XMLStreamConstants.CDATA) {
if (text == null) {
text = parser.getText();
} else {
text += parser.getText();
}
}
}
return (text == null) ? "" : text;
}
}