package com.droidworks.syndication.atom;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import android.text.TextUtils;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import android.sax.Element;
import android.sax.EndElementListener;
import android.sax.EndTextElementListener;
import android.sax.RootElement;
import android.sax.StartElementListener;
import android.util.Log;
import com.droidworks.syndication.FeedItem;
import com.droidworks.syndication.FeedItemFactory;
import com.droidworks.xml.FeedParser;
public class AtomParser extends FeedParser {
RootElement mRootElement;
private FeedItem mFeedItem;
private Date mDatePublished;
private String mTitle;
private String mDescription;
private String mYouTubeUrl;
private long mDuration;
private String mSmallThumbnailUrl;
private String mLargeThumbnailUrl;
private FeedItemFactory mFeedItemFactory;
public AtomParser() {
super("http://www.w3.org/2005/Atom");
}
public AtomParser(FeedItemFactory feedItemFactory) {
super("http://www.w3.org/2005/Atom");
mFeedItemFactory = feedItemFactory;
}
@Override
protected ContentHandler getContentHandler() {
return mRootElement.getContentHandler();
}
@Override
protected void setupNodes() {
mRootElement = new RootElement(getDefaultNamespace(), "feed");
// atom uses RFC3339 format ex: 2011-02-06T08:26:07-08:00
// and also 2012-04-28T20:52:22Z
//
// parsing this format is hard, i have a backup parser in case the
// first one fails.
final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
final SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
df2.setTimeZone(TimeZone.getTimeZone("UTC"));
Element entryNode = mRootElement.getChild(getDefaultNamespace(), "entry");
Element entryAutherNode = entryNode.getChild(getDefaultNamespace(), "author");
Element entryAuthorNameNode = entryAutherNode.getChild(getDefaultNamespace(), "name");
Element entryPubDateNode = entryNode.getChild(getDefaultNamespace(), "updated");
Element entryItemGuidNode = entryNode.getChild(getDefaultNamespace(), "id");
Element entryItemLinkNode = entryNode.getChild(getDefaultNamespace(), "link");
Element entryItemTitleNode = entryNode.getChild(getDefaultNamespace(), "title");
Element entryItemContentNode = entryNode.getChild(getDefaultNamespace(), "content");
Element entryItemCategoryNode = entryNode.getChild(getDefaultNamespace(), "category");
entryItemCategoryNode.setStartElementListener(new StartElementListener() {
public void start(Attributes attrs) {
mFeedItem.setCategory(attrs.getValue("term"));
}
});
entryItemContentNode.setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
mFeedItem.setDescription(body);
}
});
entryItemTitleNode.setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
mFeedItem.setTitle(body);
}
});
entryItemLinkNode.setStartElementListener(new StartElementListener() {
public void start(Attributes attrs) {
mFeedItem.setLink(attrs.getValue("href"));
}
});
entryItemGuidNode.setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
mFeedItem.setGuid(body);
}
});
entryPubDateNode.setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
try {
mFeedItem.setPubDate(df.parse(body));
}
catch (ParseException e) {
try {
mFeedItem.setPubDate(df2.parse(body));
} catch (ParseException e1) {
Log.e(getLogTag(), "Error parsing pubDate: " + body, e);
}
}
}
});
Element pubDateNode = entryNode.getChild(getDefaultNamespace(), "published");
Element titleNode = entryNode.getChild(getDefaultNamespace(), "title");
entryAuthorNameNode.setEndTextElementListener(new EndTextElementListener() {
@Override
public void end(String text) {
mFeedItem.setAuthorNode(text);
}
});
entryNode.setStartElementListener(new StartElementListener() {
public void start(Attributes attributes) {
if (mFeedItemFactory != null)
mFeedItem = mFeedItemFactory.create();
else
mFeedItem = new FeedItem();
}
});
entryNode.setEndElementListener(new EndElementListener() {
public void end() {
final FeedItem tmpItem = mFeedItem;
mFeedItem = null;
// try to fix a broken description
if (TextUtils.isEmpty(tmpItem.getDescription()) && !TextUtils.isEmpty(tmpItem.getItunesSummary())) {
tmpItem.setDescription(tmpItem.getItunesSummary());
}
// try to fix a broken itunes summary
if (TextUtils.isEmpty(tmpItem.getItunesSummary()) && !TextUtils.isEmpty(tmpItem.getDescription())) {
tmpItem.setItunesSummary(tmpItem.getDescription());
}
// only add feeditem if the pubdate isn't null,
// null pubdates cause a crash, and we can't sort
// without it..
if (tmpItem.getPubDate() != null)
getFeed().addItem(tmpItem);
// notify a listener if present
if (getListener() != null) {
getListener().onItemParsed(tmpItem);
}
}
});
}
}