/*
* Copyright Ericsson AB 2011-2014. All Rights Reserved.
*
* The contents of this file are subject to the Lesser GNU Public License,
* (the "License"), either version 2.1 of the License, or
* (at your option) any later version.; you may not use this file except in
* compliance with the License. You should have received a copy of the
* License along with this software. If not, it can be
* retrieved online at https://www.gnu.org/licenses/lgpl.html. Moreover
* it could also be requested from Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
* WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
* EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
* OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
* LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
*
* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
* WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
* REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
* DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
* DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY
* (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
* INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE
* OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH
* HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
*/
package com.ericsson.deviceaccess.upnp;
import com.ericsson.common.util.function.QuadConsumer;
import com.ericsson.deviceaccess.upnp.media.MediaContainer;
import com.ericsson.deviceaccess.upnp.media.MediaItem;
import com.ericsson.deviceaccess.upnp.media.MediaObject;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
public class DidlXmlPullParser {
private static final String NS_URI_DC = "http://purl.org/dc/elements/1.1/";
private static final String NS_URI_UPNP = "urn:schemas-upnp-org:metadata-1-0/upnp/";
private static final String NS_URI_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
private static final String ID = "id";
private static final String TITLE = "title";
private static final String URL = "url";
private static final String ARTIST = "artist";
private static final String ALBUMART_URI = "albumart";
private static final String RESOLUTION = "resolution";
private static final String DURATION = "duration";
private static final String PROTOCOL_INFO = "protocolInfo";
private static final String MIME_TYPE = "mimeType";
private static final String UPNP_CLASS = "class";
private static final String SIZE = "size";
private static final String TAG_ATTRIBUTES = "tagAttributes";
private static final Map<Integer, QuadConsumer<XmlPullParser, Stack<String>, Map<String, String>, List<MediaObject>>> eventTypes = new HashMap<>();
private static QuadConsumer<XmlPullParser, Stack<String>, Map<String, String>, List<MediaObject>> EMPTY = (a, b, c, d) -> {
};
static {
eventTypes.put(XmlPullParser.START_TAG, (xpp, tagStack, properties, results) -> {
String tag = xpp.getName();
tagStack.push(tag);
switch (tag) {
case "container":
case "item":
properties.put(ID, xpp.getAttributeValue(null, ID));
break;
case "res":
properties.put("protocolInfo", xpp.getAttributeValue(null, "protocolInfo"));
int nAttr = xpp.getAttributeCount();
Map<String, String> attributes = new HashMap<>();
for (int i = 0; i < nAttr; i++) {
attributes.put(xpp.getAttributeName(i), xpp.getAttributeValue(i));
}
break;
}
});
eventTypes.put(XmlPullParser.END_TAG, (xpp, tagStack, properties, results) -> {
switch (tagStack.pop()) {
case "container":
MediaContainer container = new MediaContainer();
container.setId(properties.get(ID));
container.setName(properties.get(TITLE));
properties.clear();
results.add(container);
break;
case "item":
MediaItem item = new MediaItem();
item.setId(properties.get(ID));
item.setName(properties.get(TITLE));
item.setUrl(properties.get(URL));
item.setType(getTypeFromUpnpClass(properties.get(UPNP_CLASS)));
properties.clear();
results.add(item);
break;
}
});
eventTypes.put(XmlPullParser.TEXT, (xpp, tagStack, properties, results) -> {
String tag = tagStack.peek();
if (tag.equals("title")) {
properties.put(TITLE, xpp.getText());
} else if (tag.equals("res")) {
properties.put(URL, xpp.getText());
} else if (tag.contains("artist")) {
properties.put(ARTIST, xpp.getText());
} else if (tag.contains("albumArtURI")) {
properties.put(ALBUMART_URI, xpp.getText());
} else if (tag.contains(UPNP_CLASS)) {
properties.put(UPNP_CLASS, xpp.getText());
}
});
}
public static List<MediaObject> parseDidl(String didl) throws XmlPullParserException, IOException {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader(didl));
int eventType = xpp.getEventType();
List<MediaObject> results = new ArrayList<>();
Map<String, String> properties = new HashMap<>();
Stack<String> tagStack = new Stack<>();
while (eventType != XmlPullParser.END_DOCUMENT) {
eventTypes.getOrDefault(eventType, EMPTY).consume(xpp, tagStack, properties, results);
eventType = xpp.next();
}
return results;
}
private static String getTypeFromUpnpClass(String className) {
if (className == null) {
return MediaItem.TYPE_UNKNOWN;
}
if (className.contains("video")) {
return MediaItem.TYPE_VIDEO;
} else if (className.contains("audio")) {
return MediaItem.TYPE_AUDIO;
} else if (className.contains("image")) {
return MediaItem.TYPE_IMAGE;
}
return MediaItem.TYPE_UNKNOWN;
}
private DidlXmlPullParser() {
}
}