Merge pull request #37 from mishako/itunes-more-fields

"Support more iTunes tags"

Looks good to me. Thanks Misha!
This commit is contained in:
David M. Johnson 2015-12-06 15:16:19 -05:00
commit a432e8d4d5
9 changed files with 114 additions and 60 deletions

View file

@ -40,6 +40,8 @@
*/ */
package com.rometools.modules.itunes; package com.rometools.modules.itunes;
import java.net.URL;
/** /**
* This is an abstract object that implements the attributes common across Feeds or Items in an * This is an abstract object that implements the attributes common across Feeds or Items in an
* iTunes compatible RSS feed. * iTunes compatible RSS feed.
@ -74,6 +76,7 @@ public abstract class AbstractITunesObject implements ITunes, java.lang.Cloneabl
private String author; private String author;
private boolean block; private boolean block;
private boolean explicit; private boolean explicit;
private URL image;
private String[] keywords; private String[] keywords;
private String subtitle; private String subtitle;
private String summary; private String summary;
@ -166,6 +169,16 @@ public abstract class AbstractITunesObject implements ITunes, java.lang.Cloneabl
this.explicit = explicit; this.explicit = explicit;
} }
@Override
public URL getImage() {
return image;
}
@Override
public void setImage(final URL image) {
this.image = image;
}
/** /**
* A list of keywords for this feed or entry * A list of keywords for this feed or entry
* *
@ -239,6 +252,8 @@ public abstract class AbstractITunesObject implements ITunes, java.lang.Cloneabl
sb.append(getBlock()); sb.append(getBlock());
sb.append(" Explicit: "); sb.append(" Explicit: ");
sb.append(getExplicit()); sb.append(getExplicit());
sb.append(" Image: ");
sb.append(getImage());
sb.append(" Keywords: "); sb.append(" Keywords: ");
if (getKeywords() != null) { if (getKeywords() != null) {

View file

@ -43,6 +43,12 @@ package com.rometools.modules.itunes;
import com.rometools.modules.itunes.types.Duration; import com.rometools.modules.itunes.types.Duration;
import com.rometools.rome.feed.CopyFrom; import com.rometools.rome.feed.CopyFrom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.MalformedURLException;
import java.net.URL;
/** /**
* This class contains information for iTunes podcast feeds that exist at the Item level. * This class contains information for iTunes podcast feeds that exist at the Item level.
* *
@ -54,6 +60,9 @@ public class EntryInformationImpl extends AbstractITunesObject implements EntryI
* *
*/ */
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(EntryInformationImpl.class);
private Duration duration; private Duration duration;
private boolean closedCaptioned; private boolean closedCaptioned;
private Integer order; private Integer order;
@ -121,6 +130,14 @@ public class EntryInformationImpl extends AbstractITunesObject implements EntryI
setExplicit(info.getExplicit()); setExplicit(info.getExplicit());
try {
if (info.getImage() != null) {
setImage(new URL(info.getImage().toExternalForm()));
}
} catch (final MalformedURLException e) {
LOG.debug("Error copying URL:" + info.getImage(), e);
}
if (info.getKeywords() != null) { if (info.getKeywords() != null) {
setKeywords(info.getKeywords().clone()); setKeywords(info.getKeywords().clone());
} }

View file

@ -67,23 +67,13 @@ public interface FeedInformation extends ITunes {
*/ */
public void setCategories(List<Category> categories); public void setCategories(List<Category> categories);
/** public boolean getComplete();
* Sets the URL for the image.
*
* NOTE: To specification images should be in PNG or JPEG format.
*
* @param image Sets the URL for the image.
*/
public void setImage(URL image);
/** public void setComplete(boolean complete);
* Returns the URL for the image.
* public String getNewFeedUrl();
* NOTE: To specification images should be in PNG or JPEG format.
* public void setNewFeedUrl(String newFeedUrl);
* @return Returns the URL for the image.
*/
public URL getImage();
/** /**
* Sets the owner email address for the feed. * Sets the owner email address for the feed.

View file

@ -66,8 +66,9 @@ public class FeedInformationImpl extends AbstractITunesObject implements FeedInf
private String ownerName; private String ownerName;
private String ownerEmailAddress; private String ownerEmailAddress;
private URL image;
private List<Category> categories; private List<Category> categories;
private boolean complete;
private String newFeedUrl;
/** /**
* Creates a new instance of FeedInformationImpl * Creates a new instance of FeedInformationImpl
@ -95,6 +96,26 @@ public class FeedInformationImpl extends AbstractITunesObject implements FeedInf
this.categories = categories; this.categories = categories;
} }
@Override
public boolean getComplete() {
return complete;
}
@Override
public void setComplete(boolean complete) {
this.complete = complete;
}
@Override
public String getNewFeedUrl() {
return newFeedUrl;
}
@Override
public void setNewFeedUrl(String newFeedUrl) {
this.newFeedUrl = newFeedUrl;
}
/** /**
* Returns the owner name for the feed * Returns the owner name for the feed
* *
@ -135,30 +156,6 @@ public class FeedInformationImpl extends AbstractITunesObject implements FeedInf
this.ownerEmailAddress = ownerEmailAddress; this.ownerEmailAddress = ownerEmailAddress;
} }
/**
* Returns the URL for the image.
*
* NOTE: To specification images should be in PNG or JPEG format.
*
* @return Returns the URL for the image.
*/
@Override
public URL getImage() {
return image;
}
/**
* Sets the URL for the image.
*
* NOTE: To specification images should be in PNG or JPEG format.
*
* @param image Sets the URL for the image.
*/
@Override
public void setImage(final URL image) {
this.image = image;
}
/** /**
* Required by the ROME API * Required by the ROME API
* *
@ -175,6 +172,8 @@ public class FeedInformationImpl extends AbstractITunesObject implements FeedInf
getCategories().addAll(info.getCategories()); getCategories().addAll(info.getCategories());
} }
setComplete(info.getComplete());
setNewFeedUrl(info.getNewFeedUrl());
setExplicit(info.getExplicit()); setExplicit(info.getExplicit());
try { try {
@ -215,10 +214,12 @@ public class FeedInformationImpl extends AbstractITunesObject implements FeedInf
sb.append(getOwnerEmailAddress()); sb.append(getOwnerEmailAddress());
sb.append(" name: "); sb.append(" name: ");
sb.append(getOwnerName()); sb.append(getOwnerName());
sb.append(" image: ");
sb.append(getImage());
sb.append(" categories: "); sb.append(" categories: ");
sb.append(getCategories()); sb.append(getCategories());
sb.append(" complete: ");
sb.append(getComplete());
sb.append(" newFeedUrl: ");
sb.append(getNewFeedUrl());
sb.append("]"); sb.append("]");
sb.append(super.toString()); sb.append(super.toString());

View file

@ -42,6 +42,8 @@ package com.rometools.modules.itunes;
import com.rometools.rome.feed.module.Module; import com.rometools.rome.feed.module.Module;
import java.net.URL;
/** /**
* This interface contains the methods common to all iTunes module points. * This interface contains the methods common to all iTunes module points.
* *
@ -94,6 +96,10 @@ public interface ITunes extends Module {
*/ */
public void setExplicit(boolean explicit); public void setExplicit(boolean explicit);
public URL getImage();
public void setImage(URL image);
/** /**
* A list of keywords for this feed or entry * A list of keywords for this feed or entry
* *

View file

@ -98,12 +98,6 @@ public class ITunesGenerator implements ModuleGenerator {
owner.addContent(name); owner.addContent(name);
element.addContent(owner); element.addContent(owner);
if (info.getImage() != null) {
final Element image = generateSimpleElement("image", "");
image.setAttribute("href", info.getImage().toExternalForm());
element.addContent(image);
}
final List<Category> categories = info.getCategories(); final List<Category> categories = info.getCategories();
for (final Category cat : categories) { for (final Category cat : categories) {
@ -118,6 +112,15 @@ public class ITunesGenerator implements ModuleGenerator {
element.addContent(category); element.addContent(category);
} }
if (info.getComplete()) {
element.addContent(generateSimpleElement("complete", "yes"));
}
if (info.getNewFeedUrl() != null) {
element.addContent(generateSimpleElement("new-feed-url", info.getNewFeedUrl()));
}
} else if (itunes instanceof EntryInformationImpl) { } else if (itunes instanceof EntryInformationImpl) {
final EntryInformationImpl info = (EntryInformationImpl) itunes; final EntryInformationImpl info = (EntryInformationImpl) itunes;
@ -146,6 +149,12 @@ public class ITunesGenerator implements ModuleGenerator {
element.addContent(generateSimpleElement("explicit", "no")); element.addContent(generateSimpleElement("explicit", "no"));
} }
if (itunes.getImage() != null) {
final Element image = generateSimpleElement("image", "");
image.setAttribute("href", itunes.getImage().toExternalForm());
element.addContent(image);
}
if (itunes.getKeywords() != null) { if (itunes.getKeywords() != null) {
final StringBuffer sb = new StringBuffer(); final StringBuffer sb = new StringBuffer();

View file

@ -109,17 +109,6 @@ public class ITunesParser implements ModuleParser {
} }
} }
final Element image = element.getChild("image", ns);
if (image != null && image.getAttributeValue("href") != null) {
try {
final URL imageURL = new URL(image.getAttributeValue("href").trim());
feedInfo.setImage(imageURL);
} catch (final MalformedURLException e) {
LOG.debug("Malformed URL Exception reading itunes:image tag: {}", image.getAttributeValue("href"));
}
}
final List<Element> categories = element.getChildren("category", ns); final List<Element> categories = element.getChildren("category", ns);
for (final Element element2 : categories) { for (final Element element2 : categories) {
final Element category = element2; final Element category = element2;
@ -139,6 +128,16 @@ public class ITunesParser implements ModuleParser {
} }
} }
final Element complete = element.getChild("complete", ns);
if (complete != null) {
feedInfo.setComplete("yes".equals(complete.getTextTrim().toLowerCase()));
}
final Element newFeedUrl = element.getChild("new-feed-url", ns);
if (newFeedUrl != null) {
feedInfo.setNewFeedUrl(newFeedUrl.getTextTrim());
}
} else if (element.getName().equals("item")) { } else if (element.getName().equals("item")) {
final EntryInformationImpl entryInfo = new EntryInformationImpl(); final EntryInformationImpl entryInfo = new EntryInformationImpl();
module = entryInfo; module = entryInfo;
@ -209,6 +208,17 @@ public class ITunesParser implements ModuleParser {
if (summary != null) { if (summary != null) {
module.setSummary(summary.getTextTrim()); module.setSummary(summary.getTextTrim());
} }
final Element image = element.getChild("image", ns);
if (image != null && image.getAttributeValue("href") != null) {
try {
final URL imageURL = new URL(image.getAttributeValue("href").trim());
module.setImage(imageURL);
} catch (final MalformedURLException e) {
LOG.debug("Malformed URL Exception reading itunes:image tag: {}", image.getAttributeValue("href"));
}
}
} }
return module; return module;

View file

@ -81,6 +81,8 @@ public class ITunesParserTest extends AbstractTestCase {
"summary", "summary",
"A weekly, hour-long romp through the worlds of media, politics, sports and show business, leavened with an eclectic mix of mysterious music, hosted by Harry Shearer.", "A weekly, hour-long romp through the worlds of media, politics, sports and show business, leavened with an eclectic mix of mysterious music, hosted by Harry Shearer.",
feedInfo.getSummary()); feedInfo.getSummary());
assertEquals(true, feedInfo.getComplete());
assertEquals("http://example.org", feedInfo.getNewFeedUrl());
List<SyndEntry> entries = syndfeed.getEntries(); List<SyndEntry> entries = syndfeed.getEntries();
Iterator<SyndEntry> it = entries.iterator(); Iterator<SyndEntry> it = entries.iterator();
@ -116,5 +118,6 @@ public class ITunesParserTest extends AbstractTestCase {
EntryInformationImpl entryInfo = (EntryInformationImpl) entry.getModule(AbstractITunesObject.URI); EntryInformationImpl entryInfo = (EntryInformationImpl) entry.getModule(AbstractITunesObject.URI);
assertEquals(true, entryInfo.getClosedCaptioned()); assertEquals(true, entryInfo.getClosedCaptioned());
assertEquals(Integer.valueOf(2), entryInfo.getOrder()); assertEquals(Integer.valueOf(2), entryInfo.getOrder());
assertEquals("http://example.org/image.png", entryInfo.getImage().toString());
} }
} }

View file

@ -7,6 +7,8 @@
<description>A weekly, hour-long romp through the worlds of media, politics, sports and show business, leavened with an eclectic mix of mysterious music, hosted by Harry Shearer.</description> <description>A weekly, hour-long romp through the worlds of media, politics, sports and show business, leavened with an eclectic mix of mysterious music, hosted by Harry Shearer.</description>
<itunes:subtitle>An hour&#39;s worth of Harry Shearer</itunes:subtitle> <itunes:subtitle>An hour&#39;s worth of Harry Shearer</itunes:subtitle>
<itunes:summary>A weekly, hour-long romp through the worlds of media, politics, sports and show business, leavened with an eclectic mix of mysterious music, hosted by Harry Shearer.</itunes:summary> <itunes:summary>A weekly, hour-long romp through the worlds of media, politics, sports and show business, leavened with an eclectic mix of mysterious music, hosted by Harry Shearer.</itunes:summary>
<itunes:complete>yes</itunes:complete>
<itunes:new-feed-url>http://example.org</itunes:new-feed-url>
<language>en</language> <language>en</language>
<copyright>KCRW 2005</copyright> <copyright>KCRW 2005</copyright>
@ -68,6 +70,7 @@
<itunes:keywords></itunes:keywords> <itunes:keywords></itunes:keywords>
<itunes:isClosedCaptioned>yes</itunes:isClosedCaptioned> <itunes:isClosedCaptioned>yes</itunes:isClosedCaptioned>
<itunes:order>2</itunes:order> <itunes:order>2</itunes:order>
<itunes:image href="http://example.org/image.png"></itunes:image>
</item> </item>