package com.cellasoft.univrapp.rss; import com.cellasoft.univrapp.model.Item; import com.cellasoft.univrapp.reader.BaseFeedReader.XML_TAGS; import com.cellasoft.univrapp.utils.DateUtils; import com.cellasoft.univrapp.utils.Html; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.util.Locale; public class RSSHandler extends DefaultHandler { final int RSS_CHANNEL = 0; final int RSS_CHANNEL_TITLE = 1; final int RSS_CHANNEL_LINK = 2; final int RSS_CHANNEL_DESCRIPTION = 3; final int RSS_CHANNEL_IMAGE = 4; final int RSS_ITEM = 10; final int RSS_ITEM_TITLE = 20; final int RSS_ITEM_LINK = 30; final int RSS_ITEM_DESCRIPTION = 40; final int RSS_ITEM_GUID = 50; final int RSS_ITEM_PUB_DATE = 60; private Item currentItem; private StringBuilder builder; private int maxItems = 20; private int currentState = 0; private RSSFeed feed; private OnNewEntryCallback callback; public RSSHandler(int maxItems) { this.maxItems = maxItems; } public OnNewEntryCallback getCallback() { return callback; } public void setCallback(OnNewEntryCallback callback) { this.callback = callback; } public RSSFeed getFeed() { return feed; } @Override public void startDocument() throws SAXException { super.startDocument(); currentState = RSS_CHANNEL; builder = new StringBuilder(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); try { switch (getTag(localName)) { case CHANNEL: feed = new RSSFeed(); currentState = RSS_CHANNEL; break; case ITEM: currentItem = new Item(); currentState = RSS_ITEM; break; case TITLE: if (currentState >= RSS_ITEM) { currentState = RSS_ITEM_TITLE; } else if (currentState == RSS_CHANNEL) { currentState = RSS_CHANNEL_TITLE; } break; case DESCRIPTION: if (currentState >= RSS_ITEM) { currentState = RSS_ITEM_DESCRIPTION; } else { currentState = RSS_CHANNEL_DESCRIPTION; } break; case LINK: if (currentState >= RSS_ITEM) { currentState = RSS_ITEM_LINK; } else if (currentState == RSS_CHANNEL) { currentState = RSS_CHANNEL_LINK; } break; case GUID: if (currentState >= RSS_ITEM) { currentState = RSS_ITEM_GUID; } break; case PUBDATE: if (currentState >= RSS_ITEM) { currentState = RSS_ITEM_PUB_DATE; } break; default: currentState = RSS_CHANNEL; } } catch (Exception e) { currentState = RSS_CHANNEL; throw new SAXException("Unknown TAG: " + localName.toUpperCase(Locale.getDefault()).trim()); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); String theFullText = cleanUpText(builder); switch (getTag(localName)) { case ITEM: if (callback != null) { try { callback.onNewEntry(currentItem); } catch (Throwable t) { throw new SAXException(t.getMessage()); } } feed.addItem(currentItem); currentState = RSS_CHANNEL; if (feed.getEntries().size() == maxItems) { throw new SAXException("Reaching maximum items (" + maxItems + "). Stop parsing."); } break; case TITLE: if (currentState == RSS_ITEM_TITLE) { currentItem.title = Html.decode(theFullText); currentState = RSS_ITEM; } else if (currentState == RSS_CHANNEL_TITLE) { feed.setTitle(Html.decode(theFullText)); currentState = RSS_CHANNEL; } break; case LINK: if (currentState == RSS_ITEM_LINK) { currentItem.link = theFullText; if (currentItem.exist()) { throw new SAXException( "Trovato item gi� esistente. Stop parsing."); } currentState = RSS_ITEM; } else if (currentState == RSS_CHANNEL_LINK) { feed.setLink(theFullText); currentState = RSS_CHANNEL; } break; case DESCRIPTION: if (currentState == RSS_ITEM_DESCRIPTION) { currentItem.description = theFullText.replace(",", "<br/>"); currentState = RSS_ITEM; } else if (currentState == RSS_CHANNEL_DESCRIPTION) { feed.setDescription(theFullText); currentState = RSS_CHANNEL; } break; case PUBDATE: if (currentState == RSS_ITEM_PUB_DATE) { currentItem.pubDate = DateUtils.parseRfc822(theFullText); currentState = RSS_ITEM; } else currentState = RSS_CHANNEL; break; case GUID: if (currentState == RSS_ITEM_GUID) { currentItem.guid = theFullText; currentState = RSS_ITEM; } else currentState = RSS_CHANNEL; break; default: } builder.setLength(0); } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (builder != null) builder.append(ch, start, length); } private XML_TAGS getTag(String localName) { return XML_TAGS.valueOf(localName.toUpperCase(Locale.getDefault()) .trim()); } private String cleanUpText(StringBuilder sb) { if (sb == null) return null; return sb.toString().replace("\r", "").replace("\t", "") .replace("\n", "").trim(); } public interface OnNewEntryCallback { void onNewEntry(Item item); } }