// Copyright 2009 Google Inc.
//
// 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 org.npr.api;
import android.content.Context;
import android.util.Log;
import org.apache.http.client.ClientProtocolException;
import org.npr.android.util.NodeUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public class Podcast {
private final String title;
private final String summary;
private final String link;
private final List<Item> items;
public Podcast(String title, String summary, String link, List<Item> items) {
this.title = title;
this.summary = summary;
this.link = link;
this.items = items;
}
public static class Item {
private final String title;
private final String pubDate;
private final String duration;
private final String guid;
private final String url;
public Item(String title, String pubDate, String guid, String url,
String duration) {
this.title = title;
this.pubDate = pubDate;
this.guid = guid;
this.url = url;
this.duration = duration;
}
public String getTitle() {
return title;
}
public String getPubDate() {
return pubDate;
}
public String getGuid() {
return guid;
}
public String getUrl() {
return url;
}
public String getDuration() {
return duration;
}
@Override
public String toString() {
return title;
}
}
public String getTitle() {
return title;
}
public String getSummary() {
return summary;
}
public String getLink() {
return link;
}
public List<Item> getItems() {
return items;
}
public static class PodcastBuilder {
private String title;
private String summary;
private String link;
private final List<Item> items = new LinkedList<Item>();
public PodcastBuilder withTitle(String title) {
this.title = title;
return this;
}
public PodcastBuilder withSummary(String summary) {
this.summary = summary;
return this;
}
public PodcastBuilder withLink(String link) {
this.title = link;
return this;
}
public PodcastBuilder withItem(Item item) {
this.items.add(item);
return this;
}
public Podcast build() {
return new Podcast(title, summary, link, items);
}
}
public static class PodcastFactory {
private static final String LOG_TAG = PodcastFactory.class.getName();
private static Podcast parsePodcast(Node rootNode) {
if (!rootNode.getNodeName().equals("rss") ||
!rootNode.hasChildNodes()) {
return null;
}
PodcastBuilder pb = new PodcastBuilder();
// Presumes one channel
Node channel = null;
for (Node n : new IterableNodeList(rootNode.getChildNodes())) {
String nodeName = n.getNodeName();
if (nodeName.equals("channel")) {
channel = n;
break;
}
}
if (channel == null) {
return null;
}
for (Node n : new IterableNodeList(channel.getChildNodes())) {
String nodeName = n.getNodeName();
Node nodeChild = n.getChildNodes().item(0);
if (nodeName.equals("title")) {
pb.withTitle(NodeUtils.getTextContent(n));
} else if (nodeName.equals("link") && nodeChild != null) {
pb.withLink(NodeUtils.getTextContent(n));
} else if (nodeName.equals("itunes:summary") && nodeChild != null) {
pb.withSummary(NodeUtils.getTextContent(n));
} else if (nodeName.equals("item")) {
Item item = createItem(n);
if (item != null) {
pb.withItem(item);
}
}
}
return pb.build();
}
private static Item createItem(Node node) {
if (!node.getNodeName().equals("item") ||
!node.hasChildNodes()) {
return null;
}
String title = null, guid = null, url = null, pubDate = null,
duration = null;
for (Node n : new IterableNodeList(node.getChildNodes())) {
String nodeName = n.getNodeName();
Node nodeChild = n.getChildNodes().item(0);
if (nodeName.equals("title")) {
title = NodeUtils.getTextContent(n);
} else if (nodeName.equals("guid") && nodeChild != null) {
guid = NodeUtils.getTextContent(n);
} else if (nodeName.equals("pubDate") && nodeChild != null) {
pubDate = NodeUtils.getTextContent(n);
} else if (nodeName.equals("enclosure")) {
Attr urlAttr = (Attr) n.getAttributes().getNamedItem("url");
if (urlAttr != null) {
url = urlAttr.getNodeValue();
}
} else if (nodeName.equals("itunes:duration")) {
String[] dur = NodeUtils.getTextContent(n).split(":");
if (dur.length == 2) {
duration = dur[0] + " min " + dur[1] + " sec";
}
}
if (title != null && pubDate != null && guid != null && url != null) {
// There may be multiple enclosures. Use the first one.
// TODO(mfrederick): Support multiple enclosures.
break;
}
}
return new Item(title, pubDate, guid, url, duration);
}
public static Podcast downloadPodcast(String url, Context context) {
Log.d(LOG_TAG, "downloading podcast: " + url);
Node podcasts = null;
try {
podcasts = new Client(url, context).execute();
} catch (ClientProtocolException e) {
Log.e(LOG_TAG, "", e);
} catch (IOException e) {
Log.e(LOG_TAG, "", e);
} catch (SAXException e) {
Log.e(LOG_TAG, "", e);
} catch (ParserConfigurationException e) {
Log.e(LOG_TAG, "", e);
}
if (podcasts == null) {
return null;
}
Log.d(LOG_TAG, "node " + podcasts.getNodeName() + " "
+ podcasts.getChildNodes().getLength());
return parsePodcast(podcasts);
}
}
}