/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2003-2006 RSSOwl Development Team                                  **
 **   http://www.rssowl.org/                                                 **
 **                                                                          **
 **   All rights reserved                                                    **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the Eclipse Public License 1.0 which accompanies this     **
 **   distribution, and is available at:                                     **
 **   http://www.rssowl.org/legal/epl-v10.html                               **
 **                                                                          **
 **   A copy is found in the file epl-v10.html and important notices to the  **
 **   license from the team is found in the textfile LICENSE.txt distributed **
 **   in this package.                                                       **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Contributors:                                                          **
 **     RSSOwl - initial API and implementation (bpasero@rssowl.org)         **
 **                                                                          **
 **  **********************************************************************  */

package net.sourceforge.rssowl.dao.feedparser;

import net.sourceforge.rssowl.dao.NewsfeedFactoryException;
import net.sourceforge.rssowl.model.Channel;
import net.sourceforge.rssowl.model.ChannelImage;
import net.sourceforge.rssowl.model.NewsItem;
import net.sourceforge.rssowl.util.shop.StringShop;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.Text;

import java.util.Iterator;
import java.util.List;

/**
 * Parser for the RDF 1.0 Format <br />
 * Specification: http://web.resource.org/rss/1.0/spec
 * 
 * @author <a href="mailto:bpasero@rssowl.org">Benjamin Pasero </a>
 * @version 1.2.3
 */
public class RDF_1_0_Parser extends AbstractFeedParser {

  /**
   * Instantiate a new Parser for this format.
   * 
   * @param document The document containing the data to parse
   * @param rssChannel The Channel to fill with data from the document
   * @param url The URL of the Newsfeed that is parsed
   * @param nameSpaces Possible Namespaces of the XML document
   * @throws NewsfeedFactoryException If any error occurs
   */
  public RDF_1_0_Parser(Document document, Channel rssChannel, String url, Namespace nameSpaces[]) throws NewsfeedFactoryException {
    super(document, rssChannel, url, nameSpaces);
  }

  /**
   * @see net.sourceforge.rssowl.dao.feedparser.AbstractFeedParser#parse()
   */
  public void parse() throws NewsfeedFactoryException {

    /** Temp String */
    String str;

    /** Get Channel Element */
    Element channel = getChildElement(root, "channel");

    /** Raw attempt to parse a Channel */
    if (channel == null) {
      List rootChilds = root.getChildren();

      /** For each Element as Child of the Root */
      for (Iterator iter = rootChilds.iterator(); iter.hasNext();) {
        Element child = (Element) iter.next();

        /** This is the Channel Element */
        if ("channel".equals(child.getName())) {
          channel = child;

          /**
           * The most likely reason for the parser not finding the Channel
           * Element at first is that the default Namespace is not given. Try to
           * parse the default Namespace out of the Channel Element then.
           */
          if (defNs == Namespace.NO_NAMESPACE && child.getNamespace("") != null)
            defNs = child.getNamespace("");

          break;
        }
      }
    }

    if (channel == null)
      throw new NewsfeedFactoryException(url, null, null, NewsfeedFactoryException.ERROR_INVALID_NEWSFEED);

    /** Parse Elements with default namespace */

    /** Title of channel */
    str = getChildValue("title", channel);
    if (StringShop.isset(str))
      rssChannel.setTitle(Text.normalizeString(str));

    /** Link of feed homepage */
    str = getChildValue("link", channel);
    if (StringShop.isset(str))
      rssChannel.setHomepage(str);

    /** Description of channel */
    str = getChildValue("description", channel);
    if (StringShop.isset(str))
      rssChannel.setDescription(Text.normalizeString(str));

    /** pubDate of channel */
    str = getChildValue("pubDate", channel);
    if (StringShop.isset(str))
      rssChannel.setPubDate(str);

    /** lastBuildDate of channel */
    str = getChildValue("lastBuildDate", channel);
    if (StringShop.isset(str))
      rssChannel.setLastBuildDate(str);

    /** Copyright of channel */
    str = getChildValue("copyright", channel);
    if (StringShop.isset(str))
      rssChannel.setCopyright(str);

    /** Parse Elements with Dublin Core Module namespace */
    if (dc != null) {

      /** Title of the channel */
      str = getChildValue("title", channel, dc);
      if (StringShop.isset(str))
        rssChannel.setTitle(Text.normalizeString(str));

      /** Description of the channel */
      str = getChildValue("description", channel, dc);
      if (StringShop.isset(str))
        rssChannel.setDescription(Text.normalizeString(str));

      /** Language of channel */
      str = getChildValue("language", channel, dc);
      if (StringShop.isset(str)) {
        rssChannel.setLanguage(str);
      } else {

        /** Check for language declaration in the first NewsItem */
        Element firstNewsItem = getChildElement(root, "item");

        if (firstNewsItem != null) {
          Element language = firstNewsItem.getChild("language", dc);

          if (language != null)
            rssChannel.setLanguage(language.getTextTrim());
        }
      }

      /** Publisher of the channel */
      str = getChildValue("publisher", channel, dc);
      if (StringShop.isset(str))
        rssChannel.setPublisher(str);

      /** Copyrights of the channel */
      str = getChildValue("rights", channel, dc);
      if (StringShop.isset(str))
        rssChannel.setCopyright(str);

      /** Date of the channel */
      str = getChildValue("date", channel, dc);
      if (StringShop.isset(str))
        rssChannel.setLastBuildDate(str);

      /** Creator of the channel */
      str = getChildValue("creator", channel, dc);
      if (StringShop.isset(str))
        rssChannel.setCreator(str);

      /** Category of the channel */
      str = getChildValue("subject", channel, dc);
      if (StringShop.isset(str))
        rssChannel.setCategory(str);
    }

    /** Parse Elements with Syndication Module namespace */
    if (sy != null) {

      /** updatePeriod of the channel */
      str = getChildValue("updatePeriod", channel, sy);
      if (StringShop.isset(str))
        rssChannel.setUpdatePeriod(str);

      /** updateFrequency of the channel */
      str = getChildValue("updateFrequency", channel, sy);
      if (StringShop.isset(str))
        rssChannel.setUpdateFrequency(str);
    }

    /** Parse Elements with RDF Module namespace */
    if (rdf != null) {

      /** Image of the channel */
      Element image = getChildElement(channel, "image");

      if (image != null) {
        ChannelImage rssChannelImage = new ChannelImage();

        if (image.getAttributeValue("resource", rdf) != null)
          rssChannelImage.setImgUrl(image.getAttributeValue("resource", rdf));
        else if (getChildElement(image, "url") != null)
          rssChannelImage.setImgUrl(getChildValue("url", image));

        /** Only add Image if a URL is provided */
        if (StringShop.isset(rssChannelImage.getImgUrl()))
          rssChannel.setImage(rssChannelImage);
      }
    }

    /** Get the Channel Newsitems */
    List items = getChildren(root, "item");

    /** Try validating for items in root element */
    if (items.size() == 0)
      items = getChildren(channel, "item");

    Iterator itemsIt = items.iterator();

    /** For each newsitem */
    while (itemsIt.hasNext()) {
      Element item = (Element) itemsIt.next();
      NewsItem newsItem = new NewsItem();

      /** Title of NewsItem */
      str = getChildValue("title", item);
      if (StringShop.isset(str))
        newsItem.setTitle(str);

      /** Link of NewsItem */
      str = getChildValue("link", item);
      if (StringShop.isset(str))
        newsItem.setLink(str);

      /** Description of NewsItem */
      str = getChildValue("description", item);
      if (StringShop.isset(str))
        newsItem.setDescription(str);

      /** Set part of description as title if title is not available */
      if (!StringShop.isset(newsItem.getTitle()) && newsItem.getDescription() != null)
        newsItem.setTitle(newsItem.getDescription(), true);

      /** Parse dublin core module */
      parseDCModule(item, newsItem);

      /** Parse content module */
      parseContentModule(item, newsItem);

      /** Add NewsItem to Channel */
      rssChannel.insertItem(newsItem);
    }
  }
}