//$Id: RSSHandler.java,v 1.2 2008/03/19 12:27:03 jw_mt Exp $
package org.gnu.stealthp.rsslib;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
/**
* Handler for SAX Parser.
* <p>
* This elements are <em>not</em> handled yet:<br><br>
* cloud<br>
* rating<br>
* skipHours<br>
* skipDays<br>
* category<br>
* </p>
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* </blockquote>
*
* @since RSSLIB4J 0.1
* @author Francesco aka 'StealthP' stealthp[@]stealthp.org
* @version 0.2
*/
public class RSSHandler extends DefaultHandler{
private StringBuffer buff;
private String current_tag;
private final RSSChannel chan;
private RSSItem itm;
private RSSImage img;
private RSSSequence seq;
private RSSSequenceElement seq_elem;
private RSSTextInput input;
private RSSSyndicationModule sy;
private boolean reading_chan;
private boolean reading_item;
private boolean reading_image;
private boolean reading_input;
public static final String CHANNEL_TAG = "channel";
public static final String TITLE_TAG = "title";
public static final String LINK_TAG = "link";
public static final String DESCRIPTION_TAG = "description";
public static final String ITEM_TAG = "item";
public static final String IMAGE_TAG = "image";
public static final String IMAGE_W_TAG = "width";
public static final String IMAGE_H_TAG = "height";
public static final String URL_TAG = "url";
public static final String SEQ_TAG = "rdf:seq";
public static final String SEQ_ELEMENT_TAG = "rdf:li";
public static final String TEXTINPUT_TAG = "textinput";
public static final String NAME_TAG = "name";
public static final String LANGUAGE_TAG = "language";
public static final String MANAGING_TAG = "managingEditor";
public static final String WMASTER_TAG = "webMaster";
public static final String COPY_TAG = "copyright";
public static final String PUB_DATE_TAG = "pubDate";
public static final String LAST_B_DATE_TAG = "lastBuildDate";
public static final String GENERATOR_TAG = "generator";
public static final String DOCS_TAG = "docs";
public static final String TTL_TAG = "ttl";
public static final String AUTHOR_TAG = "author";
public static final String COMMENTS_TAG = "comments";
public static final String CLOUD_TAG = "cloud"; //TODO
public static final String RATING_TAG = "rating"; //TODO
public static final String SKIPH_TAG = "skipHours"; //TODO
public static final String SKIPD_TAG = "skipDays"; //TODO
public static final String CATEGORY_TAG = "category"; //TODO
public static final String DC_TITLE_TAG = "dc:title";
public static final String DC_CREATOR_TAG = "dc:creator";
public static final String DC_SUBJECT_TAG = "dc:subject";
public static final String DC_DESCRIPTION_TAG = "dc:description";
public static final String DC_PUBLISHER_TAG = "dc:publisher";
public static final String DC_CONTRIBUTOR_TAG = "dc:contributor";
public static final String DC_DATE_TAG = "dc:date";
public static final String DC_TYPE_TAG = "dc:type";
public static final String DC_FORMAT_TAG = "dc:format";
public static final String DC_IDENTIFIER_TAG = "dc:identifier";
public static final String DC_SOURCE_TAG = "dc:source";
public static final String DC_LANGUAGE_TAG = "dc:language";
public static final String DC_RELATION_TAG = "dc:relation";
public static final String DC_COVERAGE_TAG = "dc:coverage";
public static final String DC_RIGHTS_TAG = "dc:rights";
public static final String SY_PERIOD_TAG = "sy:updatePeriod";
public static final String SY_FREQ_TAG = "sy:updateFrequency";
public static final String SY_BASE_TAG = "sy:updateBase";
public RSSHandler(){
buff = new StringBuffer();
current_tag = null;
chan = new RSSChannel();
reading_chan = false;
reading_item = false;
reading_image = false;
reading_input = false;
}
/**
* Receive notification of the start of an element.
* @param uri The Namespace URI, or the empty string if the element has no Namespace URI or if Namespace processing is not being performed.
* @param localName The local name (without prefix), or the empty string if Namespace processing is not being performed
* @param qName The qualified name (with prefix), or the empty string if qualified names are not available
* @param attributes The attributes attached to the element. If there are no attributes, it shall be an empty Attributes object
*/
@Override
public void startElement(String uri,
String localName,
String qName,
Attributes attributes){
if (tagIsEqual(qName,CHANNEL_TAG)){
reading_chan = true;
processChanAboutAttribute(attributes);
}
if (tagIsEqual(qName,ITEM_TAG)){
reading_item = true;
reading_chan = false;
itm = new RSSItem();
processItemAboutAttribute(attributes);
}
if (tagIsEqual(qName,IMAGE_TAG)){
reading_image = true;
reading_chan = false;
img = new RSSImage();
}
if (tagIsEqual(qName,SEQ_TAG)){
seq = new RSSSequence();
}
if (tagIsEqual(qName,TEXTINPUT_TAG)){
reading_input = true;
reading_chan = false;
input = new RSSTextInput();
}
if (tagIsEqual(qName,SEQ_ELEMENT_TAG))
processSeqElement(attributes);
if (qName.toUpperCase().startsWith("SY:"))
sy = new RSSSyndicationModule();
current_tag = qName;
}
/**
* Receive notification of the end of an element
* @param uri The Namespace URI, or the empty string if the element has no Namespace URI or if Namespace processing is not being performed.
* @param localName The local name (without prefix), or the empty string if Namespace processing is not being performed
* @param qName The qualified name (with prefix), or the empty string if qualified names are not available
*/
@Override
public void endElement(String uri,
String localName,
String qName){
String data = buff.toString().trim();
if (qName.equals(current_tag)){
data = buff.toString().trim();
buff = new StringBuffer();
}
if (reading_chan)
processChannel(qName,data);
if (reading_item)
processItem(qName,data);
if (reading_image)
processImage(qName,data);
if (reading_input)
processTextInput(qName,data);
if (tagIsEqual(qName,CHANNEL_TAG)){
reading_chan = false;
chan.setSyndicationModule(sy);
}
if (tagIsEqual(qName,ITEM_TAG)){
reading_item = false;
chan.addItem(itm);
}
if (tagIsEqual(qName,IMAGE_TAG)){
reading_image = false;
chan.setRSSImage(img);
}
if (tagIsEqual(qName,SEQ_TAG)){
chan.addRSSSequence(seq);
}
if (tagIsEqual(qName,TEXTINPUT_TAG)){
reading_input = false;
chan.setRSSTextInput(input);
}
}
/**
* Receive notification of character data inside an element
* @param ch The characters.
* @param start The start position in the character array.
* @param length The number of characters to use from the character array.
*/
@Override
public void characters(char[] ch,
int start,
int length){
String data = new String(ch,start,length);
//Jump blank chunk
if (data.trim().length() == 0)
return;
buff.append(data);
}
/**
* Receive notification when parse are scannering an image
* @param qName The tag name
* @param data The tag Value
*/
private void processImage(String qName,String data){
//System.out.println("RSSHandler:processImage():: TAG: " + qName);
if (tagIsEqual(qName,TITLE_TAG))
img.setTitle(data);
if (tagIsEqual(qName,LINK_TAG))
img.setLink(data);
if (tagIsEqual(qName,URL_TAG))
img.setUrl(data);
if (tagIsEqual(qName,IMAGE_W_TAG))
img.setWidth(data);
if (tagIsEqual(qName,IMAGE_H_TAG))
img.setHeight(data);
if (tagIsEqual(qName,DESCRIPTION_TAG))
img.setDescription(data);
if (qName.toUpperCase().startsWith("DC:"))
processDoublinCoreTags(qName,data,img);
}
/**
* Receive notification when parse are scannering a textinput
* @param qName The tag name
* @param data The tag Value
*/
private void processTextInput(String qName,String data){
if (tagIsEqual(qName,TITLE_TAG))
input.setTitle(data);
if (tagIsEqual(qName,LINK_TAG))
input.setLink(data);
if (tagIsEqual(qName,NAME_TAG))
input.setInputName(data);
if (tagIsEqual(qName,DESCRIPTION_TAG))
input.setDescription(data);
if (qName.toUpperCase().startsWith("DC:"))
processDoublinCoreTags(qName,data,input);
}
/**
* Receive notification when parse are scannering an Item
* @param qName The tag name
* @param data The tag Value
*/
private void processItem(String qName,String data){
if (tagIsEqual(qName,TITLE_TAG))
itm.setTitle(data);
if (tagIsEqual(qName,LINK_TAG))
itm.setLink(data);
if (tagIsEqual(qName,DESCRIPTION_TAG))
itm.setDescription(data);
if (tagIsEqual(qName,PUB_DATE_TAG))
itm.setPubDate(data);
if (tagIsEqual(qName,PUB_DATE_TAG))
itm.setPubDate(data);
if (tagIsEqual(qName,AUTHOR_TAG))
itm.setAuthor(data);
if (tagIsEqual(qName,COMMENTS_TAG))
itm.setComments(data);
if (qName.toUpperCase().startsWith("DC:"))
processDoublinCoreTags(qName,data,itm);
}
/**
* Receive notification when parse are scannering the Channel
* @param qName The tag name
* @param data The tag Value
*/
private void processChannel(String qName,String data){
if (tagIsEqual(qName,TITLE_TAG))
chan.setTitle(data);
if (tagIsEqual(qName,LINK_TAG))
chan.setLink(data);
if (tagIsEqual(qName,DESCRIPTION_TAG))
chan.setDescription(data);
if (tagIsEqual(qName,COPY_TAG))
chan.setCopyright(data);
if (tagIsEqual(qName,PUB_DATE_TAG))
chan.setPubDate(data);
if (tagIsEqual(qName,LAST_B_DATE_TAG))
chan.setLastBuildDate(data);
if (tagIsEqual(qName,GENERATOR_TAG))
chan.setGenerator(data);
if (tagIsEqual(qName,DOCS_TAG))
chan.setDocs(data);
if (tagIsEqual(qName,TTL_TAG))
chan.setTTL(data);
if (tagIsEqual(qName,LANGUAGE_TAG))
chan.setLanguage(data);
if (qName.toUpperCase().startsWith("DC:"))
processDoublinCoreTags(qName,data,chan);
if (qName.toUpperCase().startsWith("SY:"))
processSyndicationTags(qName,data);
}
/**
* Receive notification when parse are scannering a doublin core element
* @param qName tag name
* @param data tag value
* @param o RSSObject
*/
private void processDoublinCoreTags(String qName, String data,RSSObject o){
o.addDoublinCoreElement(qName.toLowerCase(),data);
}
private void processSyndicationTags(String qName, String data){
if (tagIsEqual(qName,SY_BASE_TAG))
sy.setSyUpdateBase(data);
if (tagIsEqual(qName,SY_FREQ_TAG))
sy.setSyUpdateFrequency(data);
if (tagIsEqual(qName,SY_PERIOD_TAG))
sy.setSyUpdatePeriod(data);
}
/**
* Receive notification when parse are scannering a Sequence Item
* @param a The Atrribute of the tag
*/
private void processSeqElement(Attributes a){
String res = a.getValue(0);
seq_elem = new RSSSequenceElement();
seq_elem.setResource(res);
seq.addElement(seq_elem);
}
/**
* Receive notification when parse are scannering an Item attribute
* @param a the attribute
*/
private void processItemAboutAttribute(Attributes a){
String res = a.getValue(0);
itm.setAboutAttribute(res);
}
/**
* Receive notification when parse are scannering a Chan attribute
* @param a the attribute
*/
private void processChanAboutAttribute(Attributes a){
String res = a.getValue(0);
chan.setAboutAttribute(res);
}
/**
* Check against non-casesentive tag name
* @param a The first tag
* @param b The tag to check
* @return True if the tags are the same
*/
protected static boolean tagIsEqual(String a, String b){
return a.equalsIgnoreCase(b);
}
/**
* Get the RSSChannel Object back from the parser
* @return The RSSChannell Object
*/
public RSSChannel getRSSChannel(){
return this.chan;
}
}