/*
* ____.____ __.____ ___ _____
* | | |/ _| | \ / _ \ ______ ______
* | | < | | / / /_\ \\____ \\____ \
* /\__| | | \| | / / | \ |_> > |_> >
* \________|____|__ \______/ \____|__ / __/| __/
* \/ \/|__| |__|
*
* Copyright (c) 2014-2015 Paul "Marunjar" Pretsch
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package org.voidsink.anewjkuapp.rss.lib;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
public class RssHandler implements PullParserHandler {
private static final String[] TIMEZONES = {"MEST", "EST", "PST"};
private static final String[] TIMEZONES_REPLACE = {"+0200", "-0500", "-0800"};
private static final SimpleDateFormat[] PUBDATE_FORMATS = {
new SimpleDateFormat("EEE', 'd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z", Locale.US),
new SimpleDateFormat("d' 'MMM' 'yyyy' 'HH:mm:ss' 'Z", Locale.US),
new SimpleDateFormat("EEE', 'd' 'MMM' 'yyyy' 'HH:mm:ss' 'z", Locale.US),
};
private final List<FeedEntry> mEntries = new ArrayList<>();
private FeedInfo mInfo = null;
public RssHandler() {
}
@Override
public void processEndDocument(String tag, XmlPullParser mXmlParser) {
}
@Override
public void processStartDocument(String tag, XmlPullParser mXmlParser) {
}
@Override
public List<FeedEntry> getFeedEntries() {
return mEntries;
}
@Override
public FeedInfo getFeedInfo() {
return mInfo;
}
@Override
public PullParserElement createElement(String mTag, XmlPullParser mXmlParser) {
if (mTag.equalsIgnoreCase("channel")) {
return new FeedInfoElement(mTag);
} else if (mTag.equalsIgnoreCase("item")) {
return new FeedEntryElement(mTag);
}
return null;
}
@Override
public void finishElement(String mTag, PullParserElement p) {
if (mTag.equalsIgnoreCase("channel")) {
mInfo = (FeedInfo) p;
} else if (mTag.equalsIgnoreCase("item")) {
mEntries.add((FeedEntry) p);
}
}
@Override
public void start() {
}
@Override
public void finish() {
for (FeedEntry entry : mEntries) {
((FeedEntryElement) entry).setFeedInfo(mInfo);
}
}
private class FeedInfoElement extends FeedInfoImpl implements PullParserElement {
private final String mTag;
public FeedInfoElement(String tag) {
super();
this.mTag = tag;
}
@Override
public String getTag() {
return mTag;
}
@Override
public void processEndElement(String mTag, XmlPullParser mXmlParser) throws IOException, XmlPullParserException {
}
@Override
public void processStartElement(String mTag, XmlPullParser mXmlParser) throws IOException, XmlPullParserException {
if (mTag.equalsIgnoreCase("title"))
this.mTitle = mXmlParser.nextText();
else if (mTag.equalsIgnoreCase("link"))
this.mLink = Uri.parse(mXmlParser.nextText());
else if (mTag.equalsIgnoreCase("description"))
this.mDescription = mXmlParser.nextText();
//article.setContent(xmlParser.getText().replaceAll("[<](/)?div[^>]*[>]", ""));
else if (mTag.equalsIgnoreCase("ttl"))
this.mTTL = Integer.parseInt(mXmlParser.nextText());
else if (mTag.equalsIgnoreCase("image"))
this.mImage = Uri.parse(mXmlParser.nextText());
}
@Override
public void processText(String mTag, XmlPullParser mXmlParser) throws IOException, XmlPullParserException {
}
}
private class FeedEntryElement extends FeedEntryImpl implements PullParserElement {
private final String mTag;
private final Pattern mPattern = Pattern.compile("-\\d{1,4}x\\d{1,4}");
public FeedEntryElement(String tag) {
super();
this.mTag = tag;
}
@Override
public String getTag() {
return this.mTag;
}
@Override
public void processEndElement(String mTag, XmlPullParser mXmlParser) throws IOException, XmlPullParserException {
}
@Override
public void processStartElement(String mTag, XmlPullParser mXmlParser) throws IOException, XmlPullParserException {
if (mTag.equalsIgnoreCase("title")) {
this.title = mXmlParser.nextText();
} else if (mTag.equalsIgnoreCase("link")) {
this.link = Uri.parse(mXmlParser.nextText());
} else if (mTag.equalsIgnoreCase("description")) {
this.description = mXmlParser.nextText();
this.mImage = Uri.parse(pullImageLink(this.description));
//article.setContent(xmlParser.getText().replaceAll("[<](/)?div[^>]*[>]", ""));
} else if (mTag.equalsIgnoreCase("author") || mTag.equalsIgnoreCase("dc:creator")) {
if (TextUtils.isEmpty(this.author))
this.author = mXmlParser.nextText();
} else if (mTag.equalsIgnoreCase("category")) {
this.addCategory(mXmlParser.nextText());
} else if (mTag.equalsIgnoreCase("comments")) {
this.comments = Uri.parse(mXmlParser.nextText());
} else if (mTag.equalsIgnoreCase("enclosure")) {
this.enclosure = Uri.parse(mXmlParser.nextText());
} else if (mTag.equalsIgnoreCase("guid")) {
this.guid = mXmlParser.nextText();
} else if (mTag.equalsIgnoreCase("pubDate")) {
this.pubDate = parseDate(mXmlParser.nextText());
} else if (mTag.equalsIgnoreCase("source")) {
this.source = Uri.parse(mXmlParser.nextText());
}
}
@Override
public void processText(String mTag, XmlPullParser mXmlParser) throws IOException, XmlPullParserException {
}
public void setFeedInfo(FeedInfo feedInfo) {
this.feedInfo = feedInfo;
}
private Date parseDate(String text) {
for (int n = 0; n < TIMEZONES.length; n++) {
text = text.replace(TIMEZONES[n], TIMEZONES_REPLACE[n]);
}
for (SimpleDateFormat PUBDATE_FORMAT : PUBDATE_FORMATS) {
try {
return PUBDATE_FORMAT.parse(text);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
private String pullImageLink(String encoded) {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader(encoded));
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG && "img".equals(xpp.getName())) {
int count = xpp.getAttributeCount();
for (int x = 0; x < count; x++) {
if (xpp.getAttributeName(x).equalsIgnoreCase("src"))
return mPattern.matcher(xpp.getAttributeValue(x)).replaceAll("");
}
}
eventType = xpp.next();
}
} catch (Exception e) {
Log.w(getClass().getSimpleName(), "pullImageLink failed", e);
}
return "";
}
}
}