#248 Adds support for MediaRSS 1.5.1

This commit is contained in:
Patrick Gotthard 2016-02-20 17:10:50 +01:00
parent 10d6b126a3
commit db2644adf6
22 changed files with 3856 additions and 728 deletions

View file

@ -241,6 +241,13 @@
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- XMLUnit -->
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
<!-- Hamcrest -->
<dependency>
<groupId>org.hamcrest</groupId>

View file

@ -112,6 +112,11 @@
<artifactId>hamcrest-library</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View file

@ -21,29 +21,42 @@
*/
package com.rometools.modules.mediarss.io;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import org.jdom2.Element;
import org.jdom2.Namespace;
import com.rometools.modules.georss.GMLGenerator;
import com.rometools.modules.mediarss.MediaEntryModule;
import com.rometools.modules.mediarss.MediaModule;
import com.rometools.modules.mediarss.types.Category;
import com.rometools.modules.mediarss.types.Credit;
import com.rometools.modules.mediarss.types.Embed.Param;
import com.rometools.modules.mediarss.types.License;
import com.rometools.modules.mediarss.types.Location;
import com.rometools.modules.mediarss.types.MediaContent;
import com.rometools.modules.mediarss.types.MediaGroup;
import com.rometools.modules.mediarss.types.Metadata;
import com.rometools.modules.mediarss.types.PeerLink;
import com.rometools.modules.mediarss.types.PlayerReference;
import com.rometools.modules.mediarss.types.Price;
import com.rometools.modules.mediarss.types.Rating;
import com.rometools.modules.mediarss.types.Restriction;
import com.rometools.modules.mediarss.types.Scene;
import com.rometools.modules.mediarss.types.SubTitle;
import com.rometools.modules.mediarss.types.Tag;
import com.rometools.modules.mediarss.types.Text;
import com.rometools.modules.mediarss.types.Thumbnail;
import com.rometools.modules.mediarss.types.UrlReference;
import com.rometools.rome.feed.module.Module;
import com.rometools.rome.io.ModuleGenerator;
//this class TBI
/**
* Generator for MediaRSS module.
*
*/
public class MediaModuleGenerator implements ModuleGenerator {
private static final Namespace NS = Namespace.getNamespace("media", MediaModule.URI);
@ -73,15 +86,10 @@ public class MediaModuleGenerator implements ModuleGenerator {
if (module instanceof MediaEntryModule) {
final MediaEntryModule m = (MediaEntryModule) module;
final MediaGroup[] g = m.getMediaGroups();
for (final MediaGroup element2 : g) {
for (final MediaGroup element2 : m.getMediaGroups()) {
generateGroup(element2, element);
}
final MediaContent[] c = m.getMediaContents();
for (final MediaContent element2 : c) {
for (final MediaContent element2 : m.getMediaContents()) {
generateContent(element2, element);
}
}
@ -197,9 +205,43 @@ public class MediaModuleGenerator implements ModuleGenerator {
addNotNullAttribute(t, "end", element.getEnd());
}
final Thumbnail[] thumbs = m.getThumbnail();
final Element title = addNotNullElement(e, "title", m.getTitle());
addNotNullAttribute(title, "type", m.getTitleType());
for (final Thumbnail thumb : thumbs) {
generateBackLinks(m, e);
generateComments(m, e);
generateCommunity(m, e);
generateEmbed(m, e);
generateLicenses(m, e);
generateLocations(m, e);
generatePeerLinks(m, e);
generatePrices(m, e);
generateResponses(m, e);
final Restriction[] r = m.getRestrictions();
for (final Restriction element : r) {
final Element res = addNotNullElement(e, "restriction", element.getValue());
addNotNullAttribute(res, "type", element.getType());
addNotNullAttribute(res, "relationship", element.getRelationship());
}
if (m.getRights() != null) {
final Element rights = new Element("rights", NS);
rights.setAttribute("status", m.getRights().name());
e.addContent(rights);
}
generateScenes(m, e);
generateStatus(m, e);
generateSubTitles(m, e);
generateThumbails(m, e);
}
/**
* Generation of thumbnail tags.
*
* @param m source
* @param e element to attach new element to
*/
private void generateThumbails(final Metadata m, final Element e) {
for (final Thumbnail thumb : m.getThumbnail()) {
final Element t = new Element("thumbnail", NS);
addNotNullAttribute(t, "url", thumb.getUrl());
addNotNullAttribute(t, "width", thumb.getWidth());
@ -207,16 +249,275 @@ public class MediaModuleGenerator implements ModuleGenerator {
addNotNullAttribute(t, "time", thumb.getTime());
e.addContent(t);
}
}
final Element title = addNotNullElement(e, "title", m.getTitle());
addNotNullAttribute(title, "type", m.getTitleType());
/**
* Generation of backLinks tag.
*
* @param m source
* @param e element to attach new element to
*/
private void generateBackLinks(final Metadata m, final Element e) {
final Element backLinksElements = new Element("backLinks", NS);
for (final URL backLink : m.getBackLinks()) {
addNotNullElement(backLinksElements, "backLink", backLink);
}
if (!backLinksElements.getChildren().isEmpty()) {
e.addContent(backLinksElements);
}
}
final Restriction[] r = m.getRestrictions();
/**
* Generation of comments tag.
*
* @param m source
* @param e element to attach new element to
*/
private void generateComments(final Metadata m, final Element e) {
final Element commentsElements = new Element("comments", NS);
for (final String comment : m.getComments()) {
addNotNullElement(commentsElements, "comment", comment);
}
if (!commentsElements.getChildren().isEmpty()) {
e.addContent(commentsElements);
}
}
for (final Restriction element : r) {
final Element res = addNotNullElement(e, "restriction", element.getValue());
addNotNullAttribute(res, "type", element.getType());
addNotNullAttribute(res, "relationship", element.getRelationship());
/**
* Generation of community tag.
*
* @param m source
* @param e element to attach new element to
*/
private void generateCommunity(final Metadata m, final Element e) {
if (m.getCommunity() == null) {
return;
}
final Element communityElement = new Element("community", NS);
if (m.getCommunity().getStarRating() != null) {
final Element starRatingElement = new Element("starRating", NS);
addNotNullAttribute(starRatingElement, "average", m.getCommunity().getStarRating().getAverage());
addNotNullAttribute(starRatingElement, "count", m.getCommunity().getStarRating().getCount());
addNotNullAttribute(starRatingElement, "min", m.getCommunity().getStarRating().getMin());
addNotNullAttribute(starRatingElement, "max", m.getCommunity().getStarRating().getMax());
if (starRatingElement.hasAttributes()) {
communityElement.addContent(starRatingElement);
}
}
if (m.getCommunity().getStatistics() != null) {
final Element statisticsElement = new Element("statistics", NS);
addNotNullAttribute(statisticsElement, "views", m.getCommunity().getStatistics().getViews());
addNotNullAttribute(statisticsElement, "favorites", m.getCommunity().getStatistics().getFavorites());
if (statisticsElement.hasAttributes()) {
communityElement.addContent(statisticsElement);
}
}
if (m.getCommunity().getTags() != null && !m.getCommunity().getTags().isEmpty()) {
final Element tagsElement = new Element("tags", NS);
for (final Tag tag : m.getCommunity().getTags()) {
if (!tagsElement.getTextTrim().isEmpty()) {
tagsElement.addContent(", ");
}
if (tag.getWeight() == null) {
tagsElement.addContent(tag.getName());
} else {
tagsElement.addContent(tag.getName());
tagsElement.addContent(":");
tagsElement.addContent(String.valueOf(tag.getWeight()));
}
}
if (!tagsElement.getTextTrim().isEmpty()) {
communityElement.addContent(tagsElement);
}
}
if (!communityElement.getChildren().isEmpty()) {
e.addContent(communityElement);
}
}
/**
* Generation of embed tag.
*
* @param m source
* @param e element to attach new element to
*/
private void generateEmbed(final Metadata m, final Element e) {
if (m.getEmbed() == null) {
return;
}
final Element embedElement = new Element("embed", NS);
addNotNullAttribute(embedElement, "url", m.getEmbed().getUrl());
addNotNullAttribute(embedElement, "width", m.getEmbed().getWidth());
addNotNullAttribute(embedElement, "height", m.getEmbed().getHeight());
for (final Param param : m.getEmbed().getParams()) {
final Element paramElement = addNotNullElement(embedElement, "param", param.getValue());
if (paramElement != null) {
addNotNullAttribute(paramElement, "name", param.getName());
}
}
if (embedElement.hasAttributes() || !embedElement.getChildren().isEmpty()) {
e.addContent(embedElement);
}
}
/**
* Generation of scenes tag.
*
* @param m source
* @param e element to attach new element to
*/
private void generateScenes(final Metadata m, final Element e) {
final Element scenesElement = new Element("scenes", NS);
for (final Scene scene : m.getScenes()) {
final Element sceneElement = new Element("scene", NS);
addNotNullElement(sceneElement, "sceneTitle", scene.getTitle());
addNotNullElement(sceneElement, "sceneDescription", scene.getDescription());
addNotNullElement(sceneElement, "sceneStartTime", scene.getStartTime());
addNotNullElement(sceneElement, "sceneEndTime", scene.getEndTime());
if (!sceneElement.getChildren().isEmpty()) {
scenesElement.addContent(sceneElement);
}
}
if (!scenesElement.getChildren().isEmpty()) {
e.addContent(scenesElement);
}
}
/**
* Generation of location tags.
*
* @param m source
* @param e element to attach new element to
*/
private void generateLocations(final Metadata m, final Element e) {
final GMLGenerator geoRssGenerator = new GMLGenerator();
for (final Location location : m.getLocations()) {
final Element locationElement = new Element("location", NS);
addNotNullAttribute(locationElement, "description", location.getDescription());
addNotNullAttribute(locationElement, "start", location.getStart());
addNotNullAttribute(locationElement, "end", location.getEnd());
if (location.getGeoRss() != null) {
geoRssGenerator.generate(location.getGeoRss(), locationElement);
}
if (locationElement.hasAttributes() || !locationElement.getChildren().isEmpty()) {
e.addContent(locationElement);
}
}
}
/**
* Generation of peerLink tags.
*
* @param m source
* @param e element to attach new element to
*/
private void generatePeerLinks(final Metadata m, final Element e) {
for (final PeerLink peerLink : m.getPeerLinks()) {
final Element peerLinkElement = new Element("peerLink", NS);
addNotNullAttribute(peerLinkElement, "type", peerLink.getType());
addNotNullAttribute(peerLinkElement, "href", peerLink.getHref());
if (peerLinkElement.hasAttributes()) {
e.addContent(peerLinkElement);
}
}
}
/**
* Generation of subTitle tags.
*
* @param m source
* @param e element to attach new element to
*/
private void generateSubTitles(final Metadata m, final Element e) {
for (final SubTitle subTitle : m.getSubTitles()) {
final Element subTitleElement = new Element("subTitle", NS);
addNotNullAttribute(subTitleElement, "type", subTitle.getType());
addNotNullAttribute(subTitleElement, "lang", subTitle.getLang());
addNotNullAttribute(subTitleElement, "href", subTitle.getHref());
if (subTitleElement.hasAttributes()) {
e.addContent(subTitleElement);
}
}
}
/**
* Generation of license tags.
*
* @param m source
* @param e element to attach new element to
*/
private void generateLicenses(final Metadata m, final Element e) {
for (final License license : m.getLicenses()) {
final Element licenseElement = new Element("license", NS);
addNotNullAttribute(licenseElement, "type", license.getType());
addNotNullAttribute(licenseElement, "href", license.getHref());
if (license.getValue() != null) {
licenseElement.addContent(license.getValue());
}
if (licenseElement.hasAttributes() || !licenseElement.getTextTrim().isEmpty()) {
e.addContent(licenseElement);
}
}
}
/**
* Generation of backLinks tag.
*
* @param m source
* @param e element to attach new element to
*/
private void generatePrices(final Metadata m, final Element e) {
for (final Price price : m.getPrices()) {
if (price == null) {
continue;
}
final Element priceElement = new Element("price", NS);
if (price.getType() != null) {
priceElement.setAttribute("type", price.getType().name().toLowerCase());
}
addNotNullAttribute(priceElement, "info", price.getInfo());
addNotNullAttribute(priceElement, "price", price.getPrice());
addNotNullAttribute(priceElement, "currency", price.getCurrency());
if (priceElement.hasAttributes()) {
e.addContent(priceElement);
}
}
}
/**
* Generation of responses tag.
*
* @param m source
* @param e element to attach new element to
*/
private void generateResponses(final Metadata m, final Element e) {
if (m.getResponses() == null || m.getResponses().length == 0) {
return;
}
final Element responsesElements = new Element("responses", NS);
for (final String response : m.getResponses()) {
addNotNullElement(responsesElements, "response", response);
}
e.addContent(responsesElements);
}
/**
* Generation of status tag.
*
* @param m source
* @param e element to attach new element to
*/
private void generateStatus(final Metadata m, final Element e) {
if (m.getStatus() == null) {
return;
}
final Element statusElement = new Element("status", NS);
if (m.getStatus().getState() != null) {
statusElement.setAttribute("state", m.getStatus().getState().name());
}
addNotNullAttribute(statusElement, "reason", m.getStatus().getReason());
if (statusElement.hasAttributes()) {
e.addContent(statusElement);
}
}
@ -258,3 +559,4 @@ public class MediaModuleGenerator implements ModuleGenerator {
return element;
}
}

View file

@ -21,7 +21,9 @@
*/
package com.rometools.modules.mediarss.io;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@ -32,32 +34,49 @@ import org.jdom2.Namespace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.rometools.modules.georss.GeoRSSModule;
import com.rometools.modules.georss.SimpleParser;
import com.rometools.modules.mediarss.MediaEntryModuleImpl;
import com.rometools.modules.mediarss.MediaModule;
import com.rometools.modules.mediarss.MediaModuleImpl;
import com.rometools.modules.mediarss.types.Category;
import com.rometools.modules.mediarss.types.Community;
import com.rometools.modules.mediarss.types.Credit;
import com.rometools.modules.mediarss.types.Embed;
import com.rometools.modules.mediarss.types.Embed.Param;
import com.rometools.modules.mediarss.types.Expression;
import com.rometools.modules.mediarss.types.Hash;
import com.rometools.modules.mediarss.types.License;
import com.rometools.modules.mediarss.types.Location;
import com.rometools.modules.mediarss.types.MediaContent;
import com.rometools.modules.mediarss.types.MediaGroup;
import com.rometools.modules.mediarss.types.Metadata;
import com.rometools.modules.mediarss.types.Metadata.RightsStatus;
import com.rometools.modules.mediarss.types.PeerLink;
import com.rometools.modules.mediarss.types.PlayerReference;
import com.rometools.modules.mediarss.types.Price;
import com.rometools.modules.mediarss.types.Rating;
import com.rometools.modules.mediarss.types.Restriction;
import com.rometools.modules.mediarss.types.Scene;
import com.rometools.modules.mediarss.types.StarRating;
import com.rometools.modules.mediarss.types.Statistics;
import com.rometools.modules.mediarss.types.Status;
import com.rometools.modules.mediarss.types.SubTitle;
import com.rometools.modules.mediarss.types.Tag;
import com.rometools.modules.mediarss.types.Text;
import com.rometools.modules.mediarss.types.Thumbnail;
import com.rometools.modules.mediarss.types.Time;
import com.rometools.modules.mediarss.types.UrlReference;
import com.rometools.rome.feed.module.Module;
import com.rometools.rome.io.ModuleParser;
import com.rometools.utils.Doubles;
import com.rometools.utils.Integers;
import com.rometools.utils.Longs;
import com.rometools.utils.Strings;
/**
* @author Nathanial X. Freitas
*
*
*/
public class MediaModuleParser implements ModuleParser {
@ -80,19 +99,24 @@ public class MediaModuleParser implements ModuleParser {
mod = new MediaEntryModuleImpl();
}
mod.setMetadata(parseMetadata(mmRoot));
mod.setMetadata(parseMetadata(mmRoot, locale));
mod.setPlayer(parsePlayer(mmRoot));
if (mod instanceof MediaEntryModuleImpl) {
final MediaEntryModuleImpl m = (MediaEntryModuleImpl) mod;
m.setMediaContents(parseContent(mmRoot));
m.setMediaGroups(parseGroup(mmRoot));
m.setMediaContents(parseContent(mmRoot, locale));
m.setMediaGroups(parseGroup(mmRoot, locale));
}
return mod;
}
private MediaContent[] parseContent(final Element e) {
/**
* @param e element to parse
* @param locale locale for parsing
* @return array of media:content elements
*/
private MediaContent[] parseContent(final Element e, final Locale locale) {
final List<Element> contents = e.getChildren("content", getNS());
final ArrayList<MediaContent> values = new ArrayList<MediaContent>();
@ -173,7 +197,7 @@ public class MediaModuleParser implements ModuleParser {
}
mc.setLanguage(content.getAttributeValue("lang"));
mc.setMetadata(parseMetadata(content));
mc.setMetadata(parseMetadata(content, locale));
try {
if (content.getAttributeValue("samplingrate") != null) {
mc.setSamplingrate(Float.valueOf(content.getAttributeValue("samplingrate")));
@ -206,13 +230,18 @@ public class MediaModuleParser implements ModuleParser {
return values.toArray(new MediaContent[values.size()]);
}
private MediaGroup[] parseGroup(final Element e) {
/**
* @param e element to parse
* @param locale locale for parsing
* @return array of media:group elements
*/
private MediaGroup[] parseGroup(final Element e, final Locale locale) {
final List<Element> groups = e.getChildren("group", getNS());
final ArrayList<MediaGroup> values = new ArrayList<MediaGroup>();
for (int i = 0; groups != null && i < groups.size(); i++) {
final Element group = groups.get(i);
final MediaGroup g = new MediaGroup(parseContent(group));
final MediaGroup g = new MediaGroup(parseContent(group, locale));
for (int j = 0; j < g.getContents().length; j++) {
if (g.getContents()[j].isDefaultContent()) {
@ -222,60 +251,372 @@ public class MediaModuleParser implements ModuleParser {
}
}
g.setMetadata(parseMetadata(group));
g.setMetadata(parseMetadata(group, locale));
values.add(g);
}
return values.toArray(new MediaGroup[values.size()]);
}
private Metadata parseMetadata(final Element e) {
/**
* @param e element to parse
* @param locale locale for parsing
* @return Metadata of media:group or media:content
*/
private Metadata parseMetadata(final Element e, final Locale locale) {
final Metadata md = new Metadata();
// categories
{
final List<Element> categories = e.getChildren("category", getNS());
final ArrayList<Category> values = new ArrayList<Category>();
parseCategories(e, md);
parseCopyright(e, md);
parseCredits(e, md);
parseDescription(e, md);
parseHash(e, md);
parseKeywords(e, md);
parseRatings(e, md);
parseText(e, md);
parseThumbnail(e, md);
parseTitle(e, md);
parseRestrictions(e, md);
parseAdultMetadata(e, md);
parseBackLinks(e, md);
parseComments(e, md);
parseCommunity(e, md);
parsePrices(e, md);
parseResponses(e, md);
parseStatus(e, md);
parseEmbed(e, md);
parseLicenses(e, md);
parseSubTitles(e, md);
parsePeerLinks(e, md);
parseRights(e, md);
parseLocations(e, md, locale);
parseScenes(e, md);
return md;
}
for (int i = 0; categories != null && i < categories.size(); i++) {
try {
final Element cat = categories.get(i);
values.add(new Category(cat.getAttributeValue("scheme"), cat.getAttributeValue("label"), cat.getText()));
} catch (final Exception ex) {
LOG.warn("Exception parsing category tag.", ex);
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseScenes(final Element e, final Metadata md) {
final Element scenesElement = e.getChild("scenes", getNS());
if (scenesElement != null) {
final List<Element> sceneElements = scenesElement.getChildren("scene", getNS());
final Scene[] scenes = new Scene[sceneElements.size()];
for (int i = 0; i < sceneElements.size(); i++) {
scenes[i] = new Scene();
scenes[i].setTitle(sceneElements.get(i).getChildText("sceneTitle", getNS()));
scenes[i].setDescription(sceneElements.get(i).getChildText("sceneDescription", getNS()));
final String sceneStartTime = sceneElements.get(i).getChildText("sceneStartTime", getNS());
if (sceneStartTime != null) {
scenes[i].setStartTime(new Time(sceneStartTime));
}
final String sceneEndTime = sceneElements.get(i).getChildText("sceneEndTime", getNS());
if (sceneEndTime != null) {
scenes[i].setEndTime(new Time(sceneEndTime));
}
}
md.setScenes(scenes);
}
}
md.setCategories(values.toArray(new Category[values.size()]));
/**
* @param e element to parse
* @param md metadata to fill in
* @param locale locale for parser
*/
private void parseLocations(final Element e, final Metadata md, final Locale locale) {
final List<Element> locationElements = e.getChildren("location", getNS());
final Location[] locations = new Location[locationElements.size()];
final SimpleParser geoRssParser = new SimpleParser();
for (int i = 0; i < locationElements.size(); i++) {
locations[i] = new Location();
locations[i].setDescription(locationElements.get(i).getAttributeValue("description"));
if (locationElements.get(i).getAttributeValue("start") != null) {
locations[i].setStart(new Time(locationElements.get(i).getAttributeValue("start")));
}
if (locationElements.get(i).getAttributeValue("end") != null) {
locations[i].setEnd(new Time(locationElements.get(i).getAttributeValue("end")));
}
final Module geoRssModule = geoRssParser.parse(locationElements.get(i), locale);
if (geoRssModule != null && geoRssModule instanceof GeoRSSModule) {
locations[i].setGeoRss((GeoRSSModule) geoRssModule);
}
}
md.setLocations(locations);
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseRights(final Element e, final Metadata md) {
final Element rightsElement = e.getChild("rights", getNS());
if (rightsElement != null && rightsElement.getAttributeValue("status") != null) {
md.setRights(RightsStatus.valueOf(rightsElement.getAttributeValue("status")));
}
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parsePeerLinks(final Element e, final Metadata md) {
final List<Element> peerLinkElements = e.getChildren("peerLink", getNS());
final PeerLink[] peerLinks = new PeerLink[peerLinkElements.size()];
for (int i = 0; i < peerLinkElements.size(); i++) {
peerLinks[i] = new PeerLink();
peerLinks[i].setType(peerLinkElements.get(i).getAttributeValue("type"));
if (peerLinkElements.get(i).getAttributeValue("href") != null) {
try {
peerLinks[i].setHref(new URL(peerLinkElements.get(i).getAttributeValue("href")));
} catch (MalformedURLException ex) {
LOG.warn("Exception parsing peerLink href attribute.", ex);
}
}
}
md.setPeerLinks(peerLinks);
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseSubTitles(final Element e, final Metadata md) {
final List<Element> subTitleElements = e.getChildren("subTitle", getNS());
final SubTitle[] subtitles = new SubTitle[subTitleElements.size()];
for (int i = 0; i < subTitleElements.size(); i++) {
subtitles[i] = new SubTitle();
subtitles[i].setType(subTitleElements.get(i).getAttributeValue("type"));
subtitles[i].setLang(subTitleElements.get(i).getAttributeValue("lang"));
if (subTitleElements.get(i).getAttributeValue("href") != null) {
try {
subtitles[i].setHref(new URL(subTitleElements.get(i).getAttributeValue("href")));
} catch (MalformedURLException ex) {
LOG.warn("Exception parsing subTitle href attribute.", ex);
}
}
}
md.setSubTitles(subtitles);
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseLicenses(final Element e, final Metadata md) {
final List<Element> licenseElements = e.getChildren("license", getNS());
final License[] licenses = new License[licenseElements.size()];
for (int i = 0; i < licenseElements.size(); i++) {
licenses[i] = new License();
licenses[i].setType(licenseElements.get(i).getAttributeValue("type"));
licenses[i].setValue(licenseElements.get(i).getTextTrim());
if (licenseElements.get(i).getAttributeValue("href") != null) {
try {
licenses[i].setHref(new URL(licenseElements.get(i).getAttributeValue("href")));
} catch (MalformedURLException ex) {
LOG.warn("Exception parsing license href attribute.", ex);
}
}
}
md.setLicenses(licenses);
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parsePrices(final Element e, final Metadata md) {
final List<Element> priceElements = e.getChildren("price", getNS());
final Price[] prices = new Price[priceElements.size()];
for (int i = 0; i < priceElements.size(); i++) {
final Element priceElement = priceElements.get(i);
prices[i] = new Price();
prices[i].setCurrency(priceElement.getAttributeValue("currency"));
prices[i].setPrice(Doubles.parse(priceElement.getAttributeValue("price")));
if (priceElement.getAttributeValue("type") != null) {
prices[i].setType(Price.Type.valueOf(priceElement.getAttributeValue("type").toUpperCase()));
}
if (priceElement.getAttributeValue("info") != null) {
try {
prices[i].setInfo(new URL(priceElement.getAttributeValue("info")));
} catch (MalformedURLException ex) {
LOG.warn("Exception parsing price info attribute.", ex);
}
}
}
md.setPrices(prices);
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseStatus(final Element e, final Metadata md) {
final Element statusElement = e.getChild("status", getNS());
if (statusElement != null) {
final Status status = new Status();
status.setState(Status.State.valueOf(statusElement.getAttributeValue("state")));
status.setReason(statusElement.getAttributeValue("reason"));
md.setStatus(status);
}
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseBackLinks(final Element e, final Metadata md) {
final Element backLinksElement = e.getChild("backLinks", getNS());
if (backLinksElement != null) {
final List<Element> backLinkElements = backLinksElement.getChildren("backLink", getNS());
final URL[] backLinks = new URL[backLinkElements.size()];
for (int i = 0; i < backLinkElements.size(); i++) {
try {
backLinks[i] = new URL(backLinkElements.get(i).getTextTrim());
} catch (MalformedURLException ex) {
LOG.warn("Exception parsing backLink tag.", ex);
}
}
md.setBackLinks(backLinks);
}
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseComments(final Element e, final Metadata md) {
final Element commentsElement = e.getChild("comments", getNS());
if (commentsElement != null) {
final List<Element> commentElements = commentsElement.getChildren("comment", getNS());
final String[] comments = new String[commentElements.size()];
for (int i = 0; i < commentElements.size(); i++) {
comments[i] = commentElements.get(i).getTextTrim();
}
md.setComments(comments);
}
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseResponses(final Element e, final Metadata md) {
final Element responsesElement = e.getChild("responses", getNS());
if (responsesElement != null) {
final List<Element> responseElements = responsesElement.getChildren("response", getNS());
final String[] responses = new String[responseElements.size()];
for (int i = 0; i < responseElements.size(); i++) {
responses[i] = responseElements.get(i).getTextTrim();
}
md.setResponses(responses);
}
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseCommunity(final Element e, final Metadata md) {
final Element communityElement = e.getChild("community", getNS());
if (communityElement != null) {
final Community community = new Community();
final Element starRatingElement = communityElement.getChild("starRating", getNS());
if (starRatingElement != null) {
final StarRating starRating = new StarRating();
starRating.setAverage(Doubles.parse(starRatingElement.getAttributeValue("average")));
starRating.setCount(Integers.parse(starRatingElement.getAttributeValue("count")));
starRating.setMax(Integers.parse(starRatingElement.getAttributeValue("max")));
starRating.setMin(Integers.parse(starRatingElement.getAttributeValue("min")));
community.setStarRating(starRating);
}
final Element statisticsElement = communityElement.getChild("statistics", getNS());
if (statisticsElement != null) {
final Statistics statistics = new Statistics();
statistics.setFavorites(Integers.parse(statisticsElement.getAttributeValue("favorites")));
statistics.setViews(Integers.parse(statisticsElement.getAttributeValue("views")));
community.setStatistics(statistics);
}
final Element tagsElement = communityElement.getChild("tags", getNS());
if (tagsElement != null) {
final String tagsText = tagsElement.getTextTrim();
final String[] tags = tagsText.split("\\s*,\\s*");
for (String tagText : tags) {
final String[] tagParts = tagText.split("\\s*:\\s*");
final Tag tag = new Tag(tagParts[0]);
if (tagParts.length > 1) {
tag.setWeight(Integers.parse(tagParts[1]));
}
community.getTags().add(tag);
}
}
md.setCommunity(community);
}
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseCategories(final Element e, final Metadata md) {
final List<Element> categories = e.getChildren("category", getNS());
final ArrayList<Category> values = new ArrayList<Category>();
for (int i = 0; categories != null && i < categories.size(); i++) {
try {
final Element cat = categories.get(i);
values.add(new Category(cat.getAttributeValue("scheme"), cat.getAttributeValue("label"), cat.getText()));
} catch (final Exception ex) {
LOG.warn("Exception parsing category tag.", ex);
}
}
// copyright
md.setCategories(values.toArray(new Category[values.size()]));
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseCopyright(final Element e, final Metadata md) {
try {
final Element copy = e.getChild("copyright", getNS());
if (copy != null) {
md.setCopyright(copy.getText());
md.setCopyrightUrl(copy.getAttributeValue("url") != null ? new URI(copy.getAttributeValue("url")) : null);
if (copy.getAttributeValue("url") != null) {
md.setCopyrightUrl(new URI(copy.getAttributeValue("url")));
}
}
} catch (final Exception ex) {
LOG.warn("Exception parsing copyright tag.", ex);
}
// credits
{
final List<Element> credits = e.getChildren("credit", getNS());
final ArrayList<Credit> values = new ArrayList<Credit>();
}
for (int i = 0; credits != null && i < credits.size(); i++) {
try {
final Element cred = credits.get(i);
values.add(new Credit(cred.getAttributeValue("scheme"), cred.getAttributeValue("role"), cred.getText()));
md.setCredits(values.toArray(new Credit[values.size()]));
} catch (final Exception ex) {
LOG.warn("Exception parsing credit tag.", ex);
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseCredits(final Element e, final Metadata md) {
final List<Element> credits = e.getChildren("credit", getNS());
final ArrayList<Credit> values = new ArrayList<Credit>();
for (int i = 0; credits != null && i < credits.size(); i++) {
try {
final Element cred = credits.get(i);
values.add(new Credit(cred.getAttributeValue("scheme"), cred.getAttributeValue("role"), cred.getText()));
md.setCredits(values.toArray(new Credit[values.size()]));
} catch (final Exception ex) {
LOG.warn("Exception parsing credit tag.", ex);
}
}
}
// description
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseDescription(final Element e, final Metadata md) {
try {
final Element description = e.getChild("description", getNS());
@ -286,8 +627,39 @@ public class MediaModuleParser implements ModuleParser {
} catch (final Exception ex) {
LOG.warn("Exception parsing description tag.", ex);
}
}
// hash
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseEmbed(final Element e, final Metadata md) {
final Element embedElement = e.getChild("embed", getNS());
if (embedElement != null) {
final Embed embed = new Embed();
embed.setWidth(Integers.parse(embedElement.getAttributeValue("width")));
embed.setHeight(Integers.parse(embedElement.getAttributeValue("height")));
if (embedElement.getAttributeValue("url") != null) {
try {
embed.setUrl(new URL(embedElement.getAttributeValue("url")));
} catch (MalformedURLException ex) {
LOG.warn("Exception parsing embed tag.", ex);
}
}
final List<Element> paramElements = embedElement.getChildren("param", getNS());
embed.setParams(new Param[paramElements.size()]);
for (int i = 0; i < paramElements.size(); i++) {
embed.getParams()[i] = new Param(paramElements.get(i).getAttributeValue("name"), paramElements.get(i).getTextTrim());
}
md.setEmbed(embed);
}
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseHash(final Element e, final Metadata md) {
try {
final Element hash = e.getChild("hash", getNS());
@ -297,161 +669,204 @@ public class MediaModuleParser implements ModuleParser {
} catch (final Exception ex) {
LOG.warn("Exception parsing hash tag.", ex);
}
// keywords
{
final Element keywords = e.getChild("keywords", getNS());
if (keywords != null) {
final StringTokenizer tok = new StringTokenizer(keywords.getText(), ",");
final String[] value = new String[tok.countTokens()];
for (int i = 0; tok.hasMoreTokens(); i++) {
value[i] = tok.nextToken().trim();
}
md.setKeywords(value);
}
}
// ratings
{
final ArrayList<Rating> values = new ArrayList<Rating>();
final List<Element> ratings = e.getChildren("rating", getNS());
for (final Element ratingElement : ratings) {
try {
final String ratingText = ratingElement.getText();
String ratingScheme = Strings.trimToNull(ratingElement.getAttributeValue("scheme"));
if (ratingScheme == null) {
ratingScheme = "urn:simple";
}
final Rating rating = new Rating(ratingScheme, ratingText);
values.add(rating);
} catch (final Exception ex) {
LOG.warn("Exception parsing rating tag.", ex);
}
}
md.setRatings(values.toArray(new Rating[values.size()]));
}
// text
{
final List<Element> texts = e.getChildren("text", getNS());
final ArrayList<Text> values = new ArrayList<Text>();
for (int i = 0; texts != null && i < texts.size(); i++) {
try {
final Element text = texts.get(i);
final Time start = text.getAttributeValue("start") == null ? null : new Time(text.getAttributeValue("start"));
final Time end = text.getAttributeValue("end") == null ? null : new Time(text.getAttributeValue("end"));
values.add(new Text(text.getAttributeValue("type"), text.getTextTrim(), start, end));
} catch (final Exception ex) {
LOG.warn("Exception parsing text tag.", ex);
}
}
md.setText(values.toArray(new Text[values.size()]));
}
// thumbnails
{
final ArrayList<Thumbnail> values = new ArrayList<Thumbnail>();
final List<Element> thumbnails = e.getChildren("thumbnail", getNS());
for (final Element thumb : thumbnails) {
try {
final String timeAttr = Strings.trimToNull(thumb.getAttributeValue("time"));
Time time = null;
if (timeAttr != null) {
time = new Time(timeAttr);
}
final String widthAttr = thumb.getAttributeValue("width");
final Integer width = Integers.parse(widthAttr);
final String heightAttr = thumb.getAttributeValue("height");
final Integer height = Integers.parse(heightAttr);
final String url = thumb.getAttributeValue("url");
final URI uri = new URI(url);
final Thumbnail thumbnail = new Thumbnail(uri, width, height, time);
values.add(thumbnail);
} catch (final Exception ex) {
LOG.warn("Exception parsing thumbnail tag.", ex);
}
}
md.setThumbnail(values.toArray(new Thumbnail[values.size()]));
}
// title
{
final Element title = e.getChild("title", getNS());
if (title != null) {
md.setTitle(title.getText());
md.setTitleType(title.getAttributeValue("type"));
}
}
// restrictions
{
final List<Element> restrictions = e.getChildren("restriction", getNS());
final ArrayList<Restriction> values = new ArrayList<Restriction>();
for (int i = 0; i < restrictions.size(); i++) {
final Element r = restrictions.get(i);
Restriction.Type type = null;
if (r.getAttributeValue("type").equalsIgnoreCase("uri")) {
type = Restriction.Type.URI;
} else if (r.getAttributeValue("type").equalsIgnoreCase("country")) {
type = Restriction.Type.COUNTRY;
}
Restriction.Relationship relationship = null;
if (r.getAttributeValue("relationship").equalsIgnoreCase("allow")) {
relationship = Restriction.Relationship.ALLOW;
} else if (r.getAttributeValue("relationship").equalsIgnoreCase("deny")) {
relationship = Restriction.Relationship.DENY;
}
final Restriction value = new Restriction(relationship, type, r.getTextTrim());
values.add(value);
}
md.setRestrictions(values.toArray(new Restriction[values.size()]));
}
// handle adult
{
final Element adult = e.getChild("adult", getNS());
if (adult != null && md.getRatings().length == 0) {
final Rating[] r = new Rating[1];
if (adult.getTextTrim().equals("true")) {
r[0] = new Rating("urn:simple", "adult");
} else {
r[0] = new Rating("urn:simple", "nonadult");
}
md.setRatings(r);
}
}
return md;
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseKeywords(final Element e, final Metadata md) {
final Element keywords = e.getChild("keywords", getNS());
if (keywords != null) {
final StringTokenizer tok = new StringTokenizer(keywords.getText(), ",");
final String[] value = new String[tok.countTokens()];
for (int i = 0; tok.hasMoreTokens(); i++) {
value[i] = tok.nextToken().trim();
}
md.setKeywords(value);
}
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseRatings(final Element e, final Metadata md) {
final ArrayList<Rating> values = new ArrayList<Rating>();
final List<Element> ratings = e.getChildren("rating", getNS());
for (final Element ratingElement : ratings) {
try {
final String ratingText = ratingElement.getText();
String ratingScheme = Strings.trimToNull(ratingElement.getAttributeValue("scheme"));
if (ratingScheme == null) {
ratingScheme = "urn:simple";
}
final Rating rating = new Rating(ratingScheme, ratingText);
values.add(rating);
} catch (final Exception ex) {
LOG.warn("Exception parsing rating tag.", ex);
}
}
md.setRatings(values.toArray(new Rating[values.size()]));
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseText(final Element e, final Metadata md) {
final List<Element> texts = e.getChildren("text", getNS());
final ArrayList<Text> values = new ArrayList<Text>();
for (int i = 0; texts != null && i < texts.size(); i++) {
try {
final Element text = texts.get(i);
Time start = null;
if (text.getAttributeValue("start") != null) {
start = new Time(text.getAttributeValue("start"));
}
Time end = null;
if (text.getAttributeValue("end") != null) {
end = new Time(text.getAttributeValue("end"));
}
values.add(new Text(text.getAttributeValue("type"), text.getTextTrim(), start, end));
} catch (final Exception ex) {
LOG.warn("Exception parsing text tag.", ex);
}
}
md.setText(values.toArray(new Text[values.size()]));
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseThumbnail(final Element e, final Metadata md) {
final ArrayList<Thumbnail> values = new ArrayList<Thumbnail>();
final List<Element> thumbnails = e.getChildren("thumbnail", getNS());
for (final Element thumb : thumbnails) {
try {
final String timeAttr = Strings.trimToNull(thumb.getAttributeValue("time"));
Time time = null;
if (timeAttr != null) {
time = new Time(timeAttr);
}
final String widthAttr = thumb.getAttributeValue("width");
final Integer width = Integers.parse(widthAttr);
final String heightAttr = thumb.getAttributeValue("height");
final Integer height = Integers.parse(heightAttr);
final String url = thumb.getAttributeValue("url");
final URI uri = new URI(url);
final Thumbnail thumbnail = new Thumbnail(uri, width, height, time);
values.add(thumbnail);
} catch (final Exception ex) {
LOG.warn("Exception parsing thumbnail tag.", ex);
}
}
md.setThumbnail(values.toArray(new Thumbnail[values.size()]));
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseTitle(final Element e, final Metadata md) {
final Element title = e.getChild("title", getNS());
if (title != null) {
md.setTitle(title.getText());
md.setTitleType(title.getAttributeValue("type"));
}
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseRestrictions(final Element e, final Metadata md) {
final List<Element> restrictions = e.getChildren("restriction", getNS());
final ArrayList<Restriction> values = new ArrayList<Restriction>();
for (int i = 0; i < restrictions.size(); i++) {
final Element r = restrictions.get(i);
Restriction.Type type = null;
if (r.getAttributeValue("type").equalsIgnoreCase(Restriction.Type.URI.toString())) {
type = Restriction.Type.URI;
} else if (r.getAttributeValue("type").equalsIgnoreCase(Restriction.Type.COUNTRY.toString())) {
type = Restriction.Type.COUNTRY;
} else if (r.getAttributeValue("type").equalsIgnoreCase(Restriction.Type.SHARING.toString())) {
type = Restriction.Type.SHARING;
}
Restriction.Relationship relationship = null;
if (r.getAttributeValue("relationship").equalsIgnoreCase("allow")) {
relationship = Restriction.Relationship.ALLOW;
} else if (r.getAttributeValue("relationship").equalsIgnoreCase("deny")) {
relationship = Restriction.Relationship.DENY;
}
final Restriction value = new Restriction(relationship, type, r.getTextTrim());
values.add(value);
}
md.setRestrictions(values.toArray(new Restriction[values.size()]));
}
/**
* @param e element to parse
* @param md metadata to fill in
*/
private void parseAdultMetadata(final Element e, final Metadata md) {
final Element adult = e.getChild("adult", getNS());
if (adult != null && md.getRatings().length == 0) {
final Rating[] r = new Rating[1];
if (adult.getTextTrim().equals("true")) {
r[0] = new Rating("urn:simple", "adult");
} else {
r[0] = new Rating("urn:simple", "nonadult");
}
md.setRatings(r);
}
}
/**
* @param e element to parse
* @return PlayerReference element
*/
private PlayerReference parsePlayer(final Element e) {
final Element player = e.getChild("player", getNS());
PlayerReference p = null;
if (player != null) {
final Integer width = player.getAttributeValue("width") == null ? null : new Integer(player.getAttributeValue("width"));
final Integer height = player.getAttributeValue("height") == null ? null : new Integer(player.getAttributeValue("height"));
try {
Integer width = null;
if (player.getAttributeValue("width") != null) {
width = Integer.valueOf(player.getAttributeValue("width"));
}
Integer height = null;
if (player.getAttributeValue("height") != null) {
height = Integer.valueOf(player.getAttributeValue("height"));
}
p = new PlayerReference(new URI(player.getAttributeValue("url")), width, height);
} catch (final Exception ex) {
LOG.warn("Exception parsing player tag.", ex);

View file

@ -0,0 +1,109 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
import java.util.Set;
import java.util.TreeSet;
/**
* media:community element.
*
* @since MediaRSS 1.5.0
*/
public class Community implements Serializable {
private static final long serialVersionUID = 1176552685678871066L;
private StarRating starRating;
private Statistics statistics;
private final Set<Tag> tags = new TreeSet<Tag>();
public Set<Tag> getTags() {
return tags;
}
public StarRating getStarRating() {
return starRating;
}
public void setStarRating(final StarRating starRating) {
this.starRating = starRating;
}
public Statistics getStatistics() {
return statistics;
}
public void setStatistics(final Statistics statistics) {
this.statistics = statistics;
}
//CHECKSTYLE:OFF
@Override
public String toString() {
return "Community [starRating=" + starRating + ", statistics=" + statistics + ", tags=" + tags + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (starRating == null ? 0 : starRating.hashCode());
result = prime * result + (statistics == null ? 0 : statistics.hashCode());
result = prime * result + (tags == null ? 0 : tags.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Community other = (Community) obj;
if (starRating == null) {
if (other.starRating != null) {
return false;
}
} else if (!starRating.equals(other.starRating)) {
return false;
}
if (statistics == null) {
if (other.statistics != null) {
return false;
}
} else if (!statistics.equals(other.statistics)) {
return false;
}
if (tags == null) {
if (other.tags != null) {
return false;
}
} else if (!tags.equals(other.tags)) {
return false;
}
return true;
}
//CHECKSTYLE:ON
}

View file

@ -0,0 +1,219 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
import java.net.URL;
import java.util.Arrays;
/**
* Optional tag to include embed information about a media object.
*
* @since MediaRSS 1.5.0
*/
public class Embed implements Serializable {
private static final long serialVersionUID = -6950838495477768173L;
private Param[] params = new Param[0];
private URL url;
private Integer width;
private Integer height;
public URL getUrl() {
return url;
}
public void setUrl(final URL url) {
this.url = url;
}
public Integer getWidth() {
return width;
}
public void setWidth(final Integer width) {
this.width = width;
}
public Integer getHeight() {
return height;
}
public void setHeight(final Integer height) {
this.height = height;
}
public Param[] getParams() {
return params;
}
/**
* @param params the embed params
*/
public void setParams(final Param[] params) {
if (params == null) {
this.params = new Param[0];
} else {
this.params = params;
}
}
// CHECKSTYLE:OFF
@Override
public String toString() {
return "Embed [params=" + Arrays.toString(params) + ", url=" + url + ", width=" + width + ", height=" + height + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (height == null ? 0 : height.hashCode());
result = prime * result + Arrays.hashCode(params);
result = prime * result + (url == null ? 0 : url.hashCode());
result = prime * result + (width == null ? 0 : width.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Embed other = (Embed) obj;
if (height == null) {
if (other.height != null) {
return false;
}
} else if (!height.equals(other.height)) {
return false;
}
if (!Arrays.equals(params, other.params)) {
return false;
}
if (url == null) {
if (other.url != null) {
return false;
}
} else if (!url.equals(other.url)) {
return false;
}
if (width == null) {
if (other.width != null) {
return false;
}
} else if (!width.equals(other.width)) {
return false;
}
return true;
}
// CHECKSTYLE:ON
/**
* param for embed.
*/
public static class Param implements Serializable {
private static final long serialVersionUID = -1191307096400967579L;
private String name;
private String value;
/**
*/
public Param() {
}
/**
* @param name name of the param
* @param value value of the param
*/
public Param(final String name, final String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(final String value) {
this.value = value;
}
// CHECKSTYLE:OFF
@Override
public String toString() {
return "Param [name=" + name + ", value=" + value + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (name == null ? 0 : name.hashCode());
result = prime * result + (value == null ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Param other = (Param) obj;
if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
}
if (value == null) {
if (other.value != null) {
return false;
}
} else if (!value.equals(other.value)) {
return false;
}
return true;
}
// CHECKSTYLE:ON
}
}

View file

@ -0,0 +1,114 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
import java.net.URL;
/**
* Optional tag to include machine-readable license information about a media object.
*
* @since MediaRSS 1.5.0
*
*/
public class License implements Serializable {
private static final long serialVersionUID = 8468812050262548541L;
private String type;
private URL href;
private String value;
public String getType() {
return type;
}
public void setType(final String type) {
this.type = type;
}
public URL getHref() {
return href;
}
public void setHref(final URL href) {
this.href = href;
}
public String getValue() {
return value;
}
public void setValue(final String value) {
this.value = value;
}
// CHECKSTYLE:OFF
@Override
public String toString() {
return "License [type=" + type + ", href=" + href + ", value=" + value + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (href == null ? 0 : href.hashCode());
result = prime * result + (type == null ? 0 : type.hashCode());
result = prime * result + (value == null ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final License other = (License) obj;
if (href == null) {
if (other.href != null) {
return false;
}
} else if (!href.equals(other.href)) {
return false;
}
if (type == null) {
if (other.type != null) {
return false;
}
} else if (!type.equals(other.type)) {
return false;
}
if (value == null) {
if (other.value != null) {
return false;
}
} else if (!value.equals(other.value)) {
return false;
}
return true;
}
// CHECKSTYLE:ON
}

View file

@ -0,0 +1,132 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
import com.rometools.modules.georss.GeoRSSModule;
/**
* Optional tag to include location information about a media object.
*
* @since MediaRSS 1.5.0
*/
public class Location implements Serializable {
private static final long serialVersionUID = 2899286634307076735L;
private String description;
private Time start;
private Time end;
private GeoRSSModule geoRss;
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
public Time getStart() {
return start;
}
public void setStart(final Time start) {
this.start = start;
}
public Time getEnd() {
return end;
}
public void setEnd(final Time end) {
this.end = end;
}
public GeoRSSModule getGeoRss() {
return geoRss;
}
public void setGeoRss(final GeoRSSModule geoRss) {
this.geoRss = geoRss;
}
// CHECKSTYLE:OFF
@Override
public String toString() {
return "Location [description=" + description + ", start=" + start + ", end=" + end + ", geoRss=" + geoRss + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (description == null ? 0 : description.hashCode());
result = prime * result + (end == null ? 0 : end.hashCode());
result = prime * result + (geoRss == null ? 0 : geoRss.hashCode());
result = prime * result + (start == null ? 0 : start.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Location other = (Location) obj;
if (description == null) {
if (other.description != null) {
return false;
}
} else if (!description.equals(other.description)) {
return false;
}
if (end == null) {
if (other.end != null) {
return false;
}
} else if (!end.equals(other.end)) {
return false;
}
if (geoRss == null) {
if (other.geoRss != null) {
return false;
}
} else if (!geoRss.equals(other.geoRss)) {
return false;
}
if (start == null) {
if (other.start != null) {
return false;
}
} else if (!start.equals(other.start)) {
return false;
}
return true;
}
// CHECKSTYLE:ON
}

View file

@ -0,0 +1,96 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
import java.net.URL;
/**
* Optional tag to include peerLink information about a media object.
*
* @since MediaRSS 1.5.0
*/
public class PeerLink implements Serializable {
private static final long serialVersionUID = -7117791317811346321L;
private String type;
private URL href;
public String getType() {
return type;
}
public void setType(final String type) {
this.type = type;
}
public URL getHref() {
return href;
}
public void setHref(final URL href) {
this.href = href;
}
// CHECKSTYLE:OFF
@Override
public String toString() {
return "PeerLink [type=" + type + ", href=" + href + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (href == null ? 0 : href.hashCode());
result = prime * result + (type == null ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final PeerLink other = (PeerLink) obj;
if (href == null) {
if (other.href != null) {
return false;
}
} else if (!href.equals(other.href)) {
return false;
}
if (type == null) {
if (other.type != null) {
return false;
}
} else if (!type.equals(other.type)) {
return false;
}
return true;
}
// CHECKSTYLE:ON
}

View file

@ -0,0 +1,183 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
import java.net.URL;
/**
* Optional tag to include pricing information about a media object.
*
* @since MediaRSS 1.5.0
*/
public class Price implements Serializable {
private static final long serialVersionUID = 446362162632617445L;
/**
* Valid values are {@code rent}, {@code purchase}, {@code package} or {@code subscription}.
*
* If nothing is specified, then the media is free.
*/
public enum Type {
RENT, PURCHASE, PACKAGE, SUBSCRIPTION;
}
private Type type;
private Double price;
private String currency;
private URL info;
/**
* Valid values are "rent", "purchase", "package" or "subscription". If nothing is specified, then the media is free.
*
* @return the type
*/
public Type getType() {
return type;
}
/**
* Valid values are "rent", "purchase", "package" or "subscription". If nothing is specified, then the media is free.
*
* @param type the type
*/
public void setType(final Type type) {
this.type = type;
}
/**
* price is the price of the media object.
*
* This is an optional attribute.
*
* @return the price
*/
public Double getPrice() {
return price;
}
/**
* price is the price of the media object.
*
* This is an optional attribute.
*
* @param price the price
*/
public void setPrice(final Double price) {
this.price = price;
}
/**
* use ISO 4217 {@link http://en.wikipedia.org/wiki/ISO_4217} for currency codes. This is an optional attribute.
*
* @return ISO 4217 currency code
*/
public String getCurrency() {
return currency;
}
/**
* use ISO 4217 {@link http://en.wikipedia.org/wiki/ISO_4217} for currency codes. This is an optional attribute.
*
* @param currency ISO 4217 currency code
*/
public void setCurrency(final String currency) {
this.currency = currency;
}
/**
* if the type is "package" or "subscription", then info is a URL pointing to package or subscription information.
*
* This is an optional attribute.
*
* @return info url
*/
public URL getInfo() {
return info;
}
/**
* if the type is "package" or "subscription", then info is a URL pointing to package or subscription information.
*
* This is an optional attribute.
*
* @param info url
*/
public void setInfo(final URL info) {
this.info = info;
}
// CHECKSTYLE:OFF
@Override
public String toString() {
return "Price [type=" + type + ", price=" + price + ", currency=" + currency + ", info=" + info + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (currency == null ? 0 : currency.hashCode());
result = prime * result + (info == null ? 0 : info.hashCode());
result = prime * result + (price == null ? 0 : price.hashCode());
result = prime * result + (type == null ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Price other = (Price) obj;
if (currency == null) {
if (other.currency != null) {
return false;
}
} else if (!currency.equals(other.currency)) {
return false;
}
if (info == null) {
if (other.info != null) {
return false;
}
} else if (!info.equals(other.info)) {
return false;
}
if (price == null) {
if (other.price != null) {
return false;
}
} else if (!price.equals(other.price)) {
return false;
}
if (type != other.type) {
return false;
}
return true;
}
// CHECKSTYLE:ON
}

View file

@ -31,14 +31,11 @@ import com.rometools.rome.feed.impl.ToStringBean;
* <strong>&lt;media:restriction&gt; </strong></p>
*
* <p>
* Allows restrictions to be placed on the aggregator rendering the media in the feed. Currently,
* restrictions are based on distributor (uri) and country codes. This element is purely
* informational and no obligation can be assumed or implied. Only one &lt;media:restriction&gt;
* element of the same <em>type</em> can be applied to a media object - all others will be
* ignored.&nbsp;Entities in this element should be space separated. To allow the producer to
* explicitly declare his/her intentions, two literals are reserved: 'all', 'none'. These literals
* can only be used once. This element has 1 required attribute, and 1 optional attribute (with
* strict requirements for its exclusion).
* Allows restrictions to be placed on the aggregator rendering the media in the feed. Currently, restrictions are based on distributor (uri) and country codes.
* This element is purely informational and no obligation can be assumed or implied. Only one &lt;media:restriction&gt; element of the same <em>type</em> can be
* applied to a media object - all others will be ignored.&nbsp;Entities in this element should be space separated. To allow the producer to explicitly declare
* his/her intentions, two literals are reserved: 'all', 'none'. These literals can only be used once. This element has 1 required attribute, and 1 optional
* attribute (with strict requirements for its exclusion).
* </p>
*
* <pre>
@ -46,14 +43,13 @@ import com.rometools.rome.feed.impl.ToStringBean;
* </pre>
*
* <p>
* <em>relationship</em> indicates the type of relationship that the restriction represents (allow |
* deny). In the example above, the media object should only be syndicated in Australia and the
* United States. It is a required attribute.
* <em>relationship</em> indicates the type of relationship that the restriction represents (allow | deny). In the example above, the media object should only
* be syndicated in Australia and the United States. It is a required attribute.
* </p>
*
* <p>
* <strong>Note:</strong> If the "allow" element is empty and the type is relationship is "allow",
* it is assumed that the empty list means "allow nobody" and the media should not be syndicated.
* <strong>Note:</strong> If the "allow" element is empty and the type is relationship is "allow", it is assumed that the empty list means "allow nobody" and
* the media should not be syndicated.
* </p>
* <p>
* A more explicit method would be:
@ -64,23 +60,20 @@ import com.rometools.rome.feed.impl.ToStringBean;
* </pre>
*
* <p>
* <em>type</em> specifies the type of restriction (country | uri) that the media can be syndicated.
* It is an optional attribute; however can only be excluded when using one of the literal values
* "all" or "none".
* <em>type</em> specifies the type of restriction (country | uri) that the media can be syndicated. It is an optional attribute; however can only be excluded
* when using one of the literal values "all" or "none".
* </p>
*
* <p>
* "country" allows restrictions to be placed based on country code. [<a
* href="http://www.iso.org/iso/en/prods-services/iso3166ma/index.html">ISO 3166</a>]
* "country" allows restrictions to be placed based on country code. [<a href="http://www.iso.org/iso/en/prods-services/iso3166ma/index.html">ISO 3166</a>]
* </p>
* <p>
* "uri" allows restrictions based on URI. Examples: urn:apple, http://images.google.com, urn:yahoo,
* etc.
* "uri" allows restrictions based on URI. Examples: urn:apple, http://images.google.com, urn:yahoo, etc.
*
* @author cooper
*/
public class Restriction implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 7944281267467298628L;
private final Relationship relationship;
private final String value;
@ -141,11 +134,11 @@ public class Restriction implements Serializable {
}
/**
* Indicates the action of the relationship
* Indicates the action of the relationship.
*/
public static class Relationship {
public static final class Relationship {
/**
* An Allow relationship
* An Allow relationship.
*/
public static final Relationship ALLOW = new Relationship("allow");
@ -155,6 +148,9 @@ public class Restriction implements Serializable {
public static final Relationship DENY = new Relationship("deny");
private final String value;
/**
* @param value realtion name
*/
private Relationship(final String value) {
this.value = value;
}
@ -166,20 +162,26 @@ public class Restriction implements Serializable {
}
/**
* Indicated the type of the relationship
* Indicated the type of the relationship.
*/
public static class Type {
public static final class Type {
/**
* Indicates a Country type.
*/
public static final Type COUNTRY = new Type("country");
/**
* Indicates a sharing type.
*/
public static final Type SHARING = new Type("sharing");
/**
* Indicates a URI for a special restriction type.
*/
public static final Type URI = new Type("uri");
private final String value;
/**
* @param value type name
*/
private Type(final String value) {
this.value = value;
}
@ -190,3 +192,4 @@ public class Restriction implements Serializable {
}
}
}

View file

@ -0,0 +1,130 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
/**
* Optional tag to include scene information about a media object.
*
* @since MediaRSS 1.5.0
*/
public class Scene implements Serializable {
private static final long serialVersionUID = 7901019257277734134L;
private String title;
private String description;
private Time startTime;
private Time endTime;
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
public Time getStartTime() {
return startTime;
}
public void setStartTime(final Time startTime) {
this.startTime = startTime;
}
public Time getEndTime() {
return endTime;
}
public void setEndTime(final Time endTime) {
this.endTime = endTime;
}
// CHECKSTYLE:OFF
@Override
public String toString() {
return "Scene [title=" + title + ", description=" + description + ", startTime=" + startTime + ", endTime=" + endTime + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (description == null ? 0 : description.hashCode());
result = prime * result + (endTime == null ? 0 : endTime.hashCode());
result = prime * result + (startTime == null ? 0 : startTime.hashCode());
result = prime * result + (title == null ? 0 : title.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Scene other = (Scene) obj;
if (description == null) {
if (other.description != null) {
return false;
}
} else if (!description.equals(other.description)) {
return false;
}
if (endTime == null) {
if (other.endTime != null) {
return false;
}
} else if (!endTime.equals(other.endTime)) {
return false;
}
if (startTime == null) {
if (other.startTime != null) {
return false;
}
} else if (!startTime.equals(other.startTime)) {
return false;
}
if (title == null) {
if (other.title != null) {
return false;
}
} else if (!title.equals(other.title)) {
return false;
}
return true;
}
// CHECKSTYLE:ON
}

View file

@ -0,0 +1,128 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
/**
* This element specifies the rating-related information about a media object.
*
* @since MediaRSS 1.5.0
*/
public class StarRating implements Serializable {
private static final long serialVersionUID = -6807718323210492980L;
private Double average;
private Integer count;
private Integer min;
private Integer max;
public Double getAverage() {
return average;
}
public void setAverage(final Double average) {
this.average = average;
}
public Integer getCount() {
return count;
}
public void setCount(final Integer count) {
this.count = count;
}
public Integer getMin() {
return min;
}
public void setMin(final Integer min) {
this.min = min;
}
public Integer getMax() {
return max;
}
public void setMax(final Integer max) {
this.max = max;
}
//CHECKSTYLE:OFF
@Override
public String toString() {
return "StarRating [average=" + average + ", count=" + count + ", min=" + min + ", max=" + max + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (average == null ? 0 : average.hashCode());
result = prime * result + (count == null ? 0 : count.hashCode());
result = prime * result + (max == null ? 0 : max.hashCode());
result = prime * result + (min == null ? 0 : min.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final StarRating other = (StarRating) obj;
if (average == null) {
if (other.average != null) {
return false;
}
} else if (!average.equals(other.average)) {
return false;
}
if (count == null) {
if (other.count != null) {
return false;
}
} else if (!count.equals(other.count)) {
return false;
}
if (max == null) {
if (other.max != null) {
return false;
}
} else if (!max.equals(other.max)) {
return false;
}
if (min == null) {
if (other.min != null) {
return false;
}
} else if (!min.equals(other.min)) {
return false;
}
return true;
}
//CHECKSTYLE:ON
}

View file

@ -0,0 +1,95 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
/**
*
* media:statistics element.
*
* @since MediaRSS 1.5.0
*/
public class Statistics implements Serializable {
private static final long serialVersionUID = -2184017520632902691L;
private Integer views;
private Integer favorites;
public Integer getViews() {
return views;
}
public void setViews(final Integer views) {
this.views = views;
}
public Integer getFavorites() {
return favorites;
}
public void setFavorites(final Integer favorites) {
this.favorites = favorites;
}
// CHECKSTYLE:OFF
@Override
public String toString() {
return "Statistics [views=" + views + ", favorites=" + favorites + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (favorites == null ? 0 : favorites.hashCode());
result = prime * result + (views == null ? 0 : views.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Statistics other = (Statistics) obj;
if (favorites == null) {
if (other.favorites != null) {
return false;
}
} else if (!favorites.equals(other.favorites)) {
return false;
}
if (views == null) {
if (other.views != null) {
return false;
}
} else if (!views.equals(other.views)) {
return false;
}
return true;
}
// CHECKSTYLE:ON
}

View file

@ -0,0 +1,127 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
/**
* Optional tag to specify the status of a media object -- whether it's still active or it has been blocked/deleted.
*
* @since MediaRSS 1.5.0
*/
public class Status implements Serializable {
private static final long serialVersionUID = 7136177408594285103L;
/**
* state can have values {@code active}, {@code blocked} or {@code deleted}.
*
* {@code active} means a media object is active in the system, {@code blocked} means a media object is blocked by
* the publisher, {@code deleted} means a media object has been deleted by the publisher.
*/
public enum State {
active, blocked, deleted;
}
private State state;
private String reason;
/**
* state can have values {@code active}, {@code blocked} or {@code deleted}.
*
* {@code active} means a media object is active in the system, {@code blocked} means a media object is blocked by
* the publisher, {@code deleted} means a media object has been deleted by the publisher.
*
* @return the state
*/
public State getState() {
return state;
}
/**
* state can have values {@code active}, {@code blocked} or {@code deleted}.
*
* {@code active} means a media object is active in the system, {@code blocked} means a media object is blocked by
* the publisher, {@code deleted} means a media object has been deleted by the publisher.
*
* @param state the state
*/
public void setState(final State state) {
this.state = state;
}
/**
* reason is a reason explaining why a media object has been blocked/deleted. It can be plain text or a URL.
*
* @return plain text or URL
*/
public String getReason() {
return reason;
}
/**
* reason is a reason explaining why a media object has been blocked/deleted. It can be plain text or a URL.
*
* @param reason plain text or URL
*/
public void setReason(final String reason) {
this.reason = reason;
}
// CHECKSTYLE:OFF
@Override
public String toString() {
return "Status [state=" + state + ", reason=" + reason + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (reason == null ? 0 : reason.hashCode());
result = prime * result + (state == null ? 0 : state.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Status other = (Status) obj;
if (reason == null) {
if (other.reason != null) {
return false;
}
} else if (!reason.equals(other.reason)) {
return false;
}
if (state != other.state) {
return false;
}
return true;
}
// CHECKSTYLE:ON
}

View file

@ -0,0 +1,113 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
import java.net.URL;
/**
* Optional tag to include subTitle information about a media object.
*
* @since MediaRSS 1.5.0
*/
public class SubTitle implements Serializable {
private static final long serialVersionUID = -4453481267661711890L;
private String type;
private String lang;
private URL href;
public String getType() {
return type;
}
public void setType(final String type) {
this.type = type;
}
public String getLang() {
return lang;
}
public void setLang(final String lang) {
this.lang = lang;
}
public URL getHref() {
return href;
}
public void setHref(final URL href) {
this.href = href;
}
// CHECKSTYLE:OFF
@Override
public String toString() {
return "SubTitle [type=" + type + ", lang=" + lang + ", href=" + href + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (href == null ? 0 : href.hashCode());
result = prime * result + (lang == null ? 0 : lang.hashCode());
result = prime * result + (type == null ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final SubTitle other = (SubTitle) obj;
if (href == null) {
if (other.href != null) {
return false;
}
} else if (!href.equals(other.href)) {
return false;
}
if (lang == null) {
if (other.lang != null) {
return false;
}
} else if (!lang.equals(other.lang)) {
return false;
}
if (type == null) {
if (other.type != null) {
return false;
}
} else if (!type.equals(other.type)) {
return false;
}
return true;
}
// CHECKSTYLE:ON
}

View file

@ -0,0 +1,122 @@
/*
* This code is currently released under the Mozilla Public License.
* http://www.mozilla.org/MPL/
*
* Alternately you may apply the terms of the Apache Software License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.rometools.modules.mediarss.types;
import java.io.Serializable;
/**
* optionally weighted tag in media:tags.
*
* @since MediaRSS 1.5.0
*/
public class Tag implements Serializable, Comparable<Tag> {
private static final long serialVersionUID = 6410023938827034872L;
private final String name;
private Integer weight;
/**
* @param name the tag name
*/
public Tag(final String name) {
this(name, null);
}
/**
* @param name the tag name
* @param weight the weight of the tag
*/
public Tag(final String name, final Integer weight) {
super();
this.name = name;
this.weight = weight;
}
public String getName() {
return name;
}
public Integer getWeight() {
return weight;
}
public void setWeight(final Integer weight) {
this.weight = weight;
}
@Override
public int compareTo(final Tag o) {
// weight is 1 when not set
Integer thisWeight = 1;
if (weight != null) {
thisWeight = weight;
}
Integer otherWeight = 1;
if (o != null && o.weight != null) {
otherWeight = o.weight;
}
// revert comparision, highest values first
return otherWeight.compareTo(thisWeight);
}
//CHECKSTYLE:OFF
@Override
public String toString() {
return "Tag [name=" + name + ", weight=" + weight + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (name == null ? 0 : name.hashCode());
result = prime * result + (weight == null ? 0 : weight.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Tag other = (Tag) obj;
if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
}
if (weight == null) {
if (other.weight != null) {
return false;
}
} else if (!weight.equals(other.weight)) {
return false;
}
return true;
}
//CHECKSTYLE:ON
}

View file

@ -8,9 +8,7 @@
MediaRSS
This plugin is for use with Yahoo! MediaRSS/Flickr Photostreams
The latest version is 0.1 available.
This plugin is for use with Yahoo! MediaRSS/Flickr Photostreams, see {{{http://www.rssboard.org/media-rss}Media RSS Specification}}.
*Sample Usage
@ -39,6 +37,10 @@ mySyndEntry.getModules().add( module );
*Changes
**1.7.0-SNAPSHOT
new elements from in MediaRSS 1.5.1 supported
**0.2.1
Bugfix for metadata on MediaGroups.

View file

@ -6,34 +6,17 @@
*/
package com.rometools.modules.atom;
import java.io.File;
import com.rometools.modules.AbstractTestCase;
import com.rometools.modules.atom.io.AtomModuleGenerator;
import com.rometools.modules.atom.modules.AtomLinkModule;
import com.rometools.modules.sle.SimpleListExtension;
import com.rometools.modules.sse.SSE091Generator;
import com.rometools.modules.sse.modules.Conflict;
import com.rometools.modules.sse.modules.History;
import com.rometools.modules.sse.modules.SSEModule;
import com.rometools.modules.sse.modules.Sync;
import com.rometools.rome.feed.atom.Link;
import com.rometools.rome.feed.rss.Item;
import com.rometools.rome.feed.synd.SyndEntry;
import com.rometools.rome.feed.synd.SyndFeed;
import com.rometools.rome.io.SyndFeedInput;
import com.rometools.rome.io.SyndFeedOutput;
import com.rometools.rome.io.XmlReader;
import com.rometools.rome.io.impl.DateParser;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jdom2.Attribute;
import org.jdom2.Content;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import java.io.File;
import java.net.URL;
import java.util.*;
/**
* Test to verify correctness of SSE subproject.

View file

@ -13,16 +13,26 @@ import static org.hamcrest.Matchers.notNullValue;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.Difference;
import org.custommonkey.xmlunit.DifferenceConstants;
import org.custommonkey.xmlunit.DifferenceListener;
import org.custommonkey.xmlunit.ElementNameQualifier;
import org.custommonkey.xmlunit.XMLAssert;
import org.custommonkey.xmlunit.XMLUnit;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import com.rometools.modules.AbstractTestCase;
import com.rometools.modules.mediarss.MediaEntryModule;
import com.rometools.modules.mediarss.MediaModule;
import com.rometools.modules.mediarss.types.MediaContent;
import com.rometools.modules.mediarss.types.Rating;
import com.rometools.modules.mediarss.types.Thumbnail;
@ -33,7 +43,7 @@ import com.rometools.rome.io.SyndFeedInput;
import com.rometools.rome.io.SyndFeedOutput;
/**
*
*
* @author cooper
*/
public class MediaModuleTest extends AbstractTestCase {
@ -56,7 +66,7 @@ public class MediaModuleTest extends AbstractTestCase {
* @throws Exception if file not found or not accessible
*/
public void testGoogleVideo() throws Exception {
final SyndFeed feed = getSyndFeed(new File(getTestFile("data/YouTube-MostPopular.rss")));
final SyndFeed feed = getSyndFeed("data/YouTube-MostPopular.rss");
for (final Object element : feed.getEntries()) {
final SyndEntry entry = (SyndEntry) element;
final MediaEntryModule m = (MediaEntryModule) entry.getModule(MediaModule.URI);
@ -68,110 +78,197 @@ public class MediaModuleTest extends AbstractTestCase {
* @throws Exception if file not found or not accessible
*/
public void testParse() throws Exception {
final File test = new File(super.getTestFile("xml"));
final File test = new File(getTestFile("xml"));
final File[] files = test.listFiles();
for (int j = 0; j < files.length; j++) {
if (!files[j].getName().endsWith(".xml")) {
continue;
}
final SyndFeed feed = getSyndFeed(files[j]);
final List<SyndEntry> entries = feed.getEntries();
final SyndFeedOutput output = new SyndFeedOutput();
output.output(feed, new File("target/" + j + ".xml"));
final SyndFeed feed2 = getSyndFeed(new File("target/" + j + ".xml"));
for (int i = 0; i < entries.size(); i++) {
BufferedWriter b = new BufferedWriter(new FileWriter("target/" + j + "a.txt"));
b.write("" + entries.get(i).getModule(MediaModule.URI));
b.close();
b = new BufferedWriter(new FileWriter("target/" + j + "b.txt"));
b.write("" + feed2.getEntries().get(i).getModule(MediaModule.URI));
b.close();
assertEquals(entries.get(i).getModule(MediaModule.URI), feed2.getEntries().get(i).getModule(MediaModule.URI));
}
compareFeedFiles(files[j], new File("target/" + j + ".xml"));
}
}
/**
* tests parsing thubnails with empty dimensions
* (https://github.com/rometools/rome-modules/issues/7).
*
* @param expected original file
* @param generated file for output
* @throws IOException if file not found or not accessible
* @throws FeedException when the feed can't be parsed
*/
private void compareFeedFiles(final File expected, final File generated) throws IOException, FeedException {
final SyndFeed feed = getSyndFeed(expected);
final List<SyndEntry> entries = feed.getEntries();
final SyndFeedOutput output = new SyndFeedOutput();
output.output(feed, generated);
final SyndFeed feed2 = getSyndFeed(generated);
for (int i = 0; i < entries.size(); i++) {
BufferedWriter b = new BufferedWriter(new FileWriter(generated.getAbsolutePath() + ".a.txt"));
b.write("" + entries.get(i).getModule(MediaModule.URI));
b.close();
b = new BufferedWriter(new FileWriter(generated.getAbsolutePath() + ".b.txt"));
b.write("" + feed2.getEntries().get(i).getModule(MediaModule.URI));
b.close();
assertEquals(entries.get(i).getModule(MediaModule.URI), feed2.getEntries().get(i).getModule(MediaModule.URI));
}
}
/**
* tests parsing thubnails with empty dimensions (https://github.com/rometools/rome-modules/issues/7).
*
* @throws IOException if file not found or not accessible
* @throws FeedException when the feed can't be parsed
*
*/
public void testParseThumbnailWithEmptyDimensions() throws FeedException, IOException {
final SyndFeed feed = getSyndFeed("org/rometools/feed/module/mediarss/issue-07.xml");
final SyndEntry entry = feed.getEntries().get(0);
final MediaEntryModule module = (MediaEntryModule) entry.getModule(MediaModule.URI);
final MediaEntryModule module = getFirstModuleFromFile("org/rometools/feed/module/mediarss/issue-07.xml");
final Thumbnail[] thumbnails = module.getMetadata().getThumbnail();
assertThat(thumbnails, is(notNullValue()));
}
/**
* tests parsing a decimal duration (https://github.com/rometools/rome-modules/issues/8).
*
*
* @throws IOException if file not found or not accessible
* @throws FeedException when the feed can't be parsed
*
*/
public void testParseDecimalDuration() throws FeedException, IOException {
final SyndFeed feed = getSyndFeed("org/rometools/feed/module/mediarss/issue-08.xml");
final SyndEntry entry = feed.getEntries().get(0);
final MediaEntryModule module = (MediaEntryModule) entry.getModule(MediaModule.URI);
final MediaEntryModule module = getFirstModuleFromFile("org/rometools/feed/module/mediarss/issue-08.xml");
final Thumbnail[] thumbnails = module.getMetadata().getThumbnail();
assertThat(thumbnails, is(notNullValue()));
}
/**
* tests parsing rating without scheme (https://github.com/rometools/rome-modules/issues/12).
*
*
* @throws IOException if file not found or not accessible
* @throws FeedException when the feed can't be parsed
*
*/
public void testParseRatingWithoutScheme() throws FeedException, IOException {
final SyndFeed feed = getSyndFeed("org/rometools/feed/module/mediarss/issue-12.xml");
final SyndEntry entry = feed.getEntries().get(0);
final MediaEntryModule module = (MediaEntryModule) entry.getModule(MediaModule.URI);
final MediaEntryModule module = getFirstModuleFromFile("org/rometools/feed/module/mediarss/issue-12.xml");
final Rating[] ratings = module.getMetadata().getRatings();
assertThat(ratings, is(notNullValue()));
}
/**
* test url with whitespace in media element
* (https://github.com/rometools/rome-modules/issues/20).
*
* @throws Exception if file not found or not accessible
* test url with whitespace in media element (https://github.com/rometools/rome-modules/issues/20).
*
* @throws IOException if file not found or not accessible
* @throws FeedException when the feed can't be parsed
*/
public void testParseMediaContentContainingURLWithSpaces() throws Exception {
final SyndFeed feed = getSyndFeed("org/rometools/feed/module/mediarss/issue-20.xml");
final SyndEntry entry = feed.getEntries().get(0);
final MediaEntryModule m = (MediaEntryModule) entry.getModule(MediaModule.URI);
assertNotNull("missing media entry module", m);
final MediaContent[] mcs = m.getMediaContents();
assertNotNull("missing media:content", mcs);
assertEquals("wrong count of media:content", 1, mcs.length);
final MediaContent mc = mcs[0];
assertEquals("http://www.foo.com/path/containing+spaces/trailer.mov", mc.getReference().toString());
public void testParseMediaContentContainingURLWithSpaces() throws FeedException, IOException {
final MediaEntryModule module = getFirstModuleFromFile("org/rometools/feed/module/mediarss/issue-20.xml");
assertNotNull("missing media entry module", module);
final MediaContent[] mediaContents = module.getMediaContents();
assertNotNull("missing media:content", mediaContents);
assertEquals("wrong count of media:content", 1, mediaContents.length);
final MediaContent mediaContent = mediaContents[0];
assertEquals("http://www.foo.com/path/containing+spaces/trailer.mov", mediaContent.getReference().toString());
}
/**
* tests parsing of MediaRSS 1.5 elements (https://github.com/rometools/rome-modules/issues/15).
*
* @throws IOException if file not found or not accessible
* @throws FeedException when the feed can't be parsed
*/
public void testParseMediaRss15() throws FeedException, IOException {
final MediaEntryModule module = getFirstModuleFromFile("org/rometools/feed/module/mediarss/issue-15.xml");
assertNotNull("missing media entry module", module);
assertNotNull("missing metadata element", module.getMetadata());
assertNotNull("missing community", module.getMetadata().getCommunity());
assertNotNull("missing community starRating", module.getMetadata().getCommunity().getStarRating());
assertNotNull("missing community statistics", module.getMetadata().getCommunity().getStatistics());
assertNotNull("missing community tags", module.getMetadata().getCommunity().getTags());
assertEquals("missing comments", 2, module.getMetadata().getComments().length);
assertEquals("missing responses", 2, module.getMetadata().getResponses().length);
assertEquals("missing backLinks", 2, module.getMetadata().getBackLinks().length);
assertNotNull("missing state", module.getMetadata().getStatus());
assertEquals("missing price", 1, module.getMetadata().getPrices().length);
assertNotNull("missing embed", module.getMetadata().getEmbed());
assertEquals("missing embed params", 5, module.getMetadata().getEmbed().getParams().length);
assertEquals("missing license", 1, module.getMetadata().getLicenses().length);
assertEquals("missing subTitle", 1, module.getMetadata().getSubTitles().length);
assertEquals("missing peerLinks", 1, module.getMetadata().getPeerLinks().length);
assertEquals("missing subTitle", 1, module.getMetadata().getSubTitles().length);
assertEquals("missing location", 1, module.getMetadata().getLocations().length);
assertNotNull("missing rights", module.getMetadata().getRights());
assertEquals("missing scenes", 1, module.getMetadata().getScenes().length);
}
/**
* @throws IOException if file not found or not accessible
* @throws FeedException when the feed can't be parsed
* @throws SAXException if xml parsing fails
*/
public void testMediaRss15Generator() throws IOException, FeedException, SAXException {
final SyndFeed feed = getSyndFeed("org/rometools/feed/module/mediarss/issue-15.xml");
final SyndFeedOutput output = new SyndFeedOutput();
output.output(feed, new File("target/issue-15.xml"));
XMLUnit.setIgnoreWhitespace(true);
// text content and attribute values on some elements are reformatted, so they should be ignored
final List<String> tagsToIgnoreTextContent = Arrays.asList("tags", "sceneStartTime", "sceneEndTime");
final List<String> attributaVluesToIgnore = Arrays.asList("bitrate", "end", "start");
final Diff myDiff = new Diff(new FileReader(new File(getTestFile("org/rometools/feed/module/mediarss/issue-15.xml"))),
new FileReader(new File("target/issue-15.xml")));
myDiff.overrideElementQualifier(new ElementNameQualifier());
myDiff.overrideDifferenceListener(new DifferenceListener() {
@Override
public void skippedComparison(final Node control, final Node test) {
}
@Override
public int differenceFound(final Difference difference) {
if (difference.getId() == DifferenceConstants.TEXT_VALUE_ID) {
final Node diffNode = difference.getControlNodeDetail().getNode().getParentNode();
if (MediaModule.URI.equals(diffNode.getNamespaceURI()) && tagsToIgnoreTextContent.contains(diffNode.getLocalName())) {
return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
} else if (difference.getId() == DifferenceConstants.ATTR_VALUE_ID) {
final Node diffNode = difference.getControlNodeDetail().getNode();
if (attributaVluesToIgnore.contains(diffNode.getLocalName())) {
return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
}
});
XMLAssert.assertXMLEqual(myDiff, true);
}
/**
* @param filePath relative path to file
* @return MediaEntryModule of first feed item
* @throws IOException if file access failed
* @throws FeedException if parsing feed failed
*/
private MediaEntryModule getFirstModuleFromFile(final String filePath) throws IOException, FeedException {
final SyndFeed feed = getSyndFeed(filePath);
final SyndEntry entry = feed.getEntries().get(0);
return (MediaEntryModule) entry.getModule(MediaEntryModule.URI);
}
/**
* @param file to read
* @return SyndFeed from file
* @throws IOException if file not found or not accessible
* @throws FeedException when the feed can't be parsed
*/
private SyndFeed getSyndFeed(final File file) throws IOException, FeedException {
return new SyndFeedInput().build(file);
}
/**
* @param filePath relative path to file
* @return SyndFeed from file
* @throws IOException if file not found or not accessible
* @throws FeedException when the feed can't be parsed
*/
private SyndFeed getSyndFeed(final String filePath) throws IOException, FeedException {
final String fullPath = getTestFile(filePath);
final File file = new File(fullPath);
return new SyndFeedInput().build(file);
return getSyndFeed(file);
}
}

View file

@ -0,0 +1,66 @@
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"
xmlns:georss="http://www.georss.org/georss"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:gml="http://www.opengis.net/gml">
<channel>
<title>Song Site</title>
<link>http://www.rssboard.org/media-rss</link>
<description>Media RSS example with new fields added in v1.5.0</description>
<item>
<link>http://www.foo.com</link>
<pubDate>Tue, 28 Aug 2001 00:08:56 GMT</pubDate>
<guid isPermaLink="false">http://www.foo.com</guid>
<dc:date>2001-08-28T00:08:56Z</dc:date>
<media:community>
<media:starRating average="3.5" count="20" min="1" max="10" />
<media:statistics views="5" favorites="5" />
<media:tags>news: 5, abc:3</media:tags>
</media:community>
<media:comments>
<media:comment>comment1</media:comment>
<media:comment>comment2</media:comment>
</media:comments>
<media:embed url="http://www.foo.com/player.swf" width="512" height="323">
<media:param name="type">application/x-shockwave-flash</media:param>
<media:param name="width">512</media:param>
<media:param name="height">323</media:param>
<media:param name="allowFullScreen">true</media:param>
<media:param name="flashVars">
id=12345&amp;vid=678912i&amp;lang=en-us&amp;intl=us&amp;thumbUrl=http://www.foo.com/thumbnail.jpg
</media:param>
</media:embed>
<media:responses>
<media:response>http://www.response1.com</media:response>
<media:response>http://www.response2.com</media:response>
</media:responses>
<media:backLinks>
<media:backLink>http://www.backlink1.com</media:backLink>
<media:backLink>http://www.backlink2.com</media:backLink>
</media:backLinks>
<media:rights status="official" />
<media:status state="active" />
<media:price type="rent" price="19.99" currency="EUR" />
<media:license type="text/html" href="http://www.licensehost.com/license"> Sample license for a video</media:license>
<media:subTitle type="application/smil" lang="en-us" href="http://www.foo.org/subtitle.smil" />
<media:peerLink type="application/x-bittorrent " href="http://www.foo.org/sampleFile.torrent" />
<media:location description="My house" start="00:01" end="01:00">
<georss:where>
<gml:Point>
<gml:pos>35.669998 139.770004</gml:pos>
</gml:Point>
</georss:where>
</media:location>
<media:restriction type="sharing" relationship="deny" />
<media:scenes>
<media:scene>
<media:sceneTitle>sceneTitle1</media:sceneTitle>
<media:sceneDescription>sceneDesc1</media:sceneDescription>
<media:sceneStartTime>00:15</media:sceneStartTime>
<media:sceneEndTime>00:45</media:sceneEndTime>
</media:scene>
</media:scenes>
<media:content url="http://www.foo.com/video.mov" fileSize="2000" bitrate="128" type="video/quicktime" expression="full" />
</item>
</channel>
</rss>