/*
* Copyright (c) 1999-2002 ChurchillObjects.com All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. Neither the name of the copyright
* holder nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT, INCLUDING NEGLIGENCE OR OTHERWISE, ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
package churchillobjects.rss4j.parser;
import java.util.Vector;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import churchillobjects.rss4j.RssChannel;
import churchillobjects.rss4j.RssChannelImage;
import churchillobjects.rss4j.RssChannelItem;
import churchillobjects.rss4j.RssChannelTextInput;
import churchillobjects.rss4j.RssDocument;
/**
* Class to parse an RSS document according to the specifications of the RSS
* .90 standard. This object is created when the base parser already started
* parsing the document (and knows what the version number is), so it is given
* the document object and the known namespaces up to that point.
*/
class RssParserImpl090 extends RssParser{
/**
* Indicates that the SAX handling process is currently in a channel.
*/
protected boolean inChannel = false;
/**
* Indicates that the SAX handling process is currently in an item.
*/
protected boolean inItem = false;
/**
* Indicates that the SAX handling process is currently in a text input.
*/
protected boolean inTextInput = false;
/**
* Indicates that the SAX handling process is currently in an image.
*/
protected boolean inImage = false;
/**
* Hard-coded version number for this handler's RSS version.
*/
private static final String VERSION = "0.90";
/**
* Constructor for this RSS verion's parser. Provided with an already
* set-up document and namespace.
* @param document
* @param namespaces
*/
RssParserImpl090(RssDocument document, Vector namespaces){
super(document, namespaces);
}
/**
* SAX interface method. Creates containers for channel, item, textinput and
* image and sets flags to indicate that we are within that element.
* @param uri
* @param name
* @param qName
* @param attrs
*/
public void startElement(String uri, String name, String qName, Attributes attrs) throws SAXException{
if("channel".equals(name)){
currentChannel = new RssChannel();
inChannel = true;
}
if("item".equals(name)){
currentItem = new RssChannelItem();
inItem = true;
}
if("textInput".equals(name)){
currentTextInput = new RssChannelTextInput();
inTextInput = true;
}
if("image".equals(name)){
currentImage = new RssChannelImage();
inImage = true;
}
}
/**
* SAX interface method. Upon closing an element, add that element to the
* document (or containing element) and set the flags to indicate we are no
* longer within that element. For attributes of elements, set the characters
* to the containing element.
* @param uri
* @param name
* @param qName
* @throws SAXException
*/
public void endElement(String uri, String name, String qName) throws SAXException{
// add subelements
if("channel".equals(name)){
closeChannelElement();
return;
}
if("item".equals(name)){
closeItemElement();
return;
}
if("textInput".equals(name)){
closeTextInputElement();
return;
}
if("image".equals(name)){
closeImageElement();
return;
}
// all others are fields within others,
// if no chars then no sense in continuing
if(!hasChars()){
return;
}
// add attributes to elements
if("title".equals(name)){
handleTitleAttribute();
}
if("description".equals(name)){
handleDescriptionAttribute();
}
if("link".equals(name)){
handleLinkAttribute();
}
if("url".equals(name)){
handleUrlAttribute();
}
if("name".equals(name)){
handleNameAttribute();
}
// If this is the current version, then reset the chars
if(VERSION.equals(document.getVersion())){
resetChars();
}
}
/**
* Upon close of channel element, adds the current channel to the document,
* sets it to null and sets the inChannel flag to false.
*/
private void closeChannelElement(){
if(currentChannel!=null){
document.addChannel(currentChannel);
currentChannel = null;
}
inChannel = false;
}
/**
* Upon close of item element, adds the current item to the channel,
* sets it to null and sets the inItem flag to false.
*/
private void closeItemElement(){
if(currentItem!=null && currentChannel!=null){
currentChannel.addItem(currentItem);
currentItem = null;
}
inItem = false;
}
/**
* Upon close of TextInput element, adds the current text input to the channel,
* sets it to null and sets the inTextInput flag to false.
*/
private void closeTextInputElement(){
if(currentTextInput!=null && currentChannel!=null){
currentChannel.setChannelTextInput(currentTextInput);
currentTextInput = null;
}
inTextInput = false;
}
/**
* Upon close of image element, adds the current image to the channel,
* sets it to null and sets the inImage flag to false.
*/
private void closeImageElement(){
if(currentImage!=null && currentChannel!=null){
currentChannel.setChannelImage(currentImage);
currentImage = null;
}
inImage = false;
}
/**
* Handles the title attribute by adding the characters to the current
* text input, image, item or channel, depending on the flags.
*/
private void handleTitleAttribute(){
if(inTextInput){
currentTextInput.setInputTitle(getChars());
}
else if(inImage){
currentImage.setImageTitle(getChars());
}
else if(inItem){
currentItem.setItemTitle(getChars());
}
else if(inChannel){
currentChannel.setChannelTitle(getChars());
}
}
/**
* Handles the description attribute by adding the characters to the current
* text input or channel, depending on the flags.
*/
private void handleDescriptionAttribute(){
if(inTextInput){
currentTextInput.setInputDescription(getChars());
}
else if(inChannel && !inItem && !inImage){
currentChannel.setChannelDescription(getChars());
}
}
/**
* Handles the link attribute by adding the characters to the current
* text input, image, item or channel, depending on the flags.
*/
private void handleLinkAttribute(){
if(inTextInput){
currentTextInput.setInputLink(getChars());
}
else if(inImage){
currentImage.setImageLink(getChars());
}
else if(inItem){
currentItem.setItemLink(getChars());
}
else if(inChannel){
currentChannel.setChannelLink(getChars());
}
}
/**
* Handles the url attribute by adding the characters to the current
* image if that flag is set.
*/
private void handleUrlAttribute(){
if(inImage){
currentImage.setImageUrl(getChars());
}
}
/**
* Handles the name attribute by adding the characters to the current
* text input if that flag is set.
*/
private void handleNameAttribute(){
if(inTextInput){
currentTextInput.setInputName(getChars());
}
}
}