Android Open Source - SimpleReader R S S Handler






From Project

Back to project page SimpleReader.

License

The source code is released under:

Apache License

If you think the Android project SimpleReader listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2010 A. Horn//  ww w.j a  va2s .  c  o m
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.dreamteam.app.rss;

/**
 * Internal SAX handler to efficiently parse RSS feeds. Only a single thread
 * must use this SAX handler.
 * 
 * @author Mr Horn
 */
class RSSHandler extends org.xml.sax.helpers.DefaultHandler {

  /**
   * Constant for XML element name which identifies RSS items.
   */
  private static final String RSS_ITEM = "item";

  /**
   * Constant symbol table to ensure efficient treatment of handler states.
   */
  private final java.util.Map<String, Setter> setters;

  /**
   * Reference is never {@code null}. Visibility must be package-private to
   * ensure efficiency of inner classes.
   */
  final RSSFeed feed = new RSSFeed();

  /**
   * Reference is {@code null} unless started to parse &lt;item&gt; element.
   * Visibility must be package-private to ensure efficiency of inner classes.
   */
  RSSItem item;

  /**
   * If not {@code null}, then buffer the characters inside an XML text element.
   */
  private StringBuilder buffer;

  /**
   * Dispatcher to set either {@link #feed} or {@link #item} fields.
   */
  private Setter setter;

  /**
   * Interface to store information about RSS elements.
   */
  private static interface Setter {}

  /**
   * Closure to change fields in POJOs which store RSS content.
   */
  private static interface ContentSetter extends Setter {

    /**
     * Set the field of an object which represents an RSS element.
     */
    void set(String value);

  }

  /**
   * Closure to change fields in POJOs which store information
   * about RSS elements which have only attributes.
   */
  private static interface AttributeSetter extends Setter {

    /**
     * Set the XML attributes.
     */
    void set(org.xml.sax.Attributes attributes);

  }

  /**
   * Setter for RSS &lt;title&gt; elements inside a &lt;channel&gt; or an
   * &lt;item&gt; element. The title of the RSS feed is set only if
   * {@link #item} is {@code null}. Otherwise, the title of the RSS
   * {@link #item} is set.
   */
  private final Setter SET_TITLE = new ContentSetter() {
    @Override
    public void set(String title) {
      if (item == null) {
        feed.setTitle(title);
      } else {
        item.setTitle(title);
      }
    }
  };

  /**
   * Setter for RSS &lt;description&gt; elements inside a &lt;channel&gt; or an
   * &lt;item&gt; element. The title of the RSS feed is set only if
   * {@link #item} is {@code null}. Otherwise, the title of the RSS
   * {@link #item} is set.
   */
  private final Setter SET_DESCRIPTION = new ContentSetter() {
    @Override
    public void set(String description) {
      if (item == null) {
        feed.setDescription(description);
      } else {
        item.setDescription(description);
      }
    }
  };
  
  /**
   * Setter for an RSS &lt;content:encoded&gt; element inside an &lt;item&gt;
   * element.
   */
  private final Setter SET_CONTENT = new ContentSetter() {
    @Override
    public void set(String content) {
      if (item != null) {
        item.setContent(content);
      }
    }
  };

  /**
   * Setter for RSS &lt;link&gt; elements inside a &lt;channel&gt; or an
   * &lt;item&gt; element. The title of the RSS feed is set only if
   * {@link #item} is {@code null}. Otherwise, the title of the RSS
   * {@link #item} is set.
   */
  private final Setter SET_LINK = new ContentSetter() {
    @Override
    public void set(String link) {
      final android.net.Uri uri = android.net.Uri.parse(link);
      if (item == null) {
        feed.setLink(uri);
      } else {
        item.setLink(uri);
      }
    }
  };

  /**
   * Setter for RSS &lt;pubDate&gt; elements inside a &lt;channel&gt; or an
   * &lt;item&gt; element. The title of the RSS feed is set only if
   * {@link #item} is {@code null}. Otherwise, the title of the RSS
   * {@link #item} is set.
   */
  private final Setter SET_PUBDATE = new ContentSetter() {
    @Override
    public void set(String pubDate) {
      final java.util.Date date = Dates.parseRfc822(pubDate);
      if (item == null) {
        feed.setPubDate(date);
      } else {
        item.setPubDate(date);
      }
    }
  };

  /**
   * Setter for RSS &lt;lastBuildDate&gt; elements inside a &lt;channel&gt;.
   */
  private final Setter SET_LAST_BUILE_DATE = new ContentSetter() {
    @Override
    public void set(String pubDate) {
      final java.util.Date date = Dates.parseRfc822(pubDate);
      if (item == null) {
        feed.setLastBuildDate(date);
      } else {
        // Ignore invalid elements which are inside item elements.
      }
    }
  };

  /**
   * Setter for RSS &lt;ttl&gt; elements inside a &lt;channel&gt;.
   */
  private final Setter SET_TTL = new ContentSetter() {
    @Override
    public void set(String ttl) {
      final Integer value = Integers.parseInteger(ttl);
      if (item == null) {
        feed.setTTL(value);
      } else {
        // Ignore invalid elements which are inside item elements.
      }
    }
  };

  /**
   * Setter for one or multiple RSS &lt;category&gt; elements inside a
   * &lt;channel&gt; or an &lt;item&gt; element. The title of the RSS feed is
   * set only if {@link #item} is {@code null}. Otherwise, the title of the RSS
   * {@link #item} is set.
   */
  private final Setter ADD_CATEGORY = new ContentSetter() {

    @Override
    public void set(String category) {
      if (item == null) {
        feed.addCategory(category);
      } else {
        item.addCategory(category);
      }
    }
  };

  /**
   * Setter for one or multiple RSS &lt;media:thumbnail&gt; elements inside an
   * &lt;item&gt; element. The thumbnail element has only attributes. Both its
   * height and width are optional. Invalid elements are ignored.
   */
  private final Setter ADD_MEDIA_THUMBNAIL = new AttributeSetter() {

    private static final String MEDIA_THUMBNAIL_HEIGHT = "height";
    private static final String MEDIA_THUMBNAIL_WIDTH = "width";
    private static final String MEDIA_THUMBNAIL_URL = "url";
    private static final int DEFAULT_DIMENSION = -1;

    @Override
    public void set(org.xml.sax.Attributes attributes) {
      if (item == null) {
        // ignore invalid media:thumbnail elements which are not inside item
        // elements
        return;
      }

      final int height = MediaAttributes.intValue(attributes, MEDIA_THUMBNAIL_HEIGHT, DEFAULT_DIMENSION);
      final int width = MediaAttributes.intValue(attributes, MEDIA_THUMBNAIL_WIDTH, DEFAULT_DIMENSION);
      final String url = MediaAttributes.stringValue(attributes, MEDIA_THUMBNAIL_URL);

      if (url == null) {
        // ignore invalid media:thumbnail elements which have no URL.
        return;
      }

      item.addThumbnail(new MediaThumbnail(android.net.Uri.parse(url), height, width));
    }

  };

  /**
   * Setter for RSS &lt;enclosure&gt; elements inside an &lt;item&gt; element.
   */
  private final Setter SET_ENCLOSURE = new AttributeSetter() {

    private static final String URL = "url";
    private static final String LENGTH = "length";
    private static final String MIMETYPE = "type";

    @Override
    public void set(org.xml.sax.Attributes attributes) {
      if (item == null) {
        // Ignore invalid elements which are not inside item elements.
        return;
      }

      final String url = MediaAttributes.stringValue(attributes, URL);
      final Integer length = MediaAttributes.intValue(attributes, LENGTH);
      final String mimeType = MediaAttributes.stringValue(attributes,
          MIMETYPE);

      if (url == null || length == null || mimeType == null) {
        // Ignore invalid elements.
        return;
      }

      MediaEnclosure enclosure = new MediaEnclosure(
          android.net.Uri.parse(url), length, mimeType);
      item.setEnclosure(enclosure);
    }
  };

  /**
   * Use configuration to optimize initial capacities of collections
   */
  private final RSSConfig config;

  /**
   * Instantiate a SAX handler which can parse a subset of RSS 2.0 feeds.
   * 
   * @param config configuration for the initial capacities of collections
   */
  RSSHandler(RSSConfig config) {
    this.config = config;

    // initialize dispatchers to manage the state of the SAX handler
    setters = new java.util.HashMap<String, Setter>(/* 2^3 */16);
    setters.put("title", SET_TITLE);
    setters.put("description", SET_DESCRIPTION);
    setters.put("content:encoded", SET_CONTENT);
    setters.put("link", SET_LINK);
    setters.put("category", ADD_CATEGORY);
    setters.put("pubDate", SET_PUBDATE);
    setters.put("media:thumbnail", ADD_MEDIA_THUMBNAIL);
    setters.put("lastBuildDate", SET_LAST_BUILE_DATE);
    setters.put("ttl", SET_TTL);
    setters.put("enclosure", SET_ENCLOSURE);
  }

  /**
   * Returns the RSS feed after this SAX handler has processed the XML document.
   */
  RSSFeed feed() {
    return feed;
  }

  /**
   * Identify the appropriate dispatcher which should be used to store XML data
   * in a POJO. Unsupported RSS 2.0 elements are currently ignored.
   */
  @Override
  public void startElement(String nsURI, String localName, String qname,
      org.xml.sax.Attributes attributes) {
    // Lookup dispatcher in hash table
    setter = setters.get(qname);
    if (setter == null) {
      if (RSS_ITEM.equals(qname)) {
        item = new RSSItem(config.categoryAvg, config.thumbnailAvg);
      }
    } else if (setter instanceof AttributeSetter) {
      ((AttributeSetter) setter).set(attributes);
    } else {
      // Buffer supported RSS content data
      buffer = new StringBuilder();
    }
  }

  @Override
  public void endElement(String nsURI, String localName, String qname) {
    if (isBuffering()) {
      // set field of an RSS feed or RSS item
      ((ContentSetter) setter).set(buffer.toString());

      // clear buffer
      buffer = null;
    } else if (RSS_ITEM.equals(qname)) {
      feed.addItem(item);

      // (re)enter <channel> scope
      item = null;
    }
  }

  @Override
  public void characters(char ch[], int start, int length) {
    if (isBuffering()) {
      buffer.append(ch, start, length);
    }
  }

  /**
   * Determines if the SAX parser is ready to receive data inside an XML element
   * such as &lt;title&gt; or &lt;description&gt;.
   * 
   * @return boolean {@code true} if the SAX handler parses data inside an XML
   *         element, {@code false} otherwise
   */
  boolean isBuffering() {
    return buffer != null && setter != null;
  }

}




Java Source Code List

com.dreamteam.app.adapter.CategoryDetailAdapter.java
com.dreamteam.app.adapter.FeedCategoryAdapter.java
com.dreamteam.app.adapter.GridAdapter.java
com.dreamteam.app.adapter.GuideViewPagerAdapter.java
com.dreamteam.app.adapter.ItemListAdapter.java
com.dreamteam.app.adapter.MPagerAdapter.java
com.dreamteam.app.commons.AppConfig.java
com.dreamteam.app.commons.AppContext.java
com.dreamteam.app.commons.HtmlFilter.java
com.dreamteam.app.commons.IFlyHelper.java
com.dreamteam.app.commons.ItemListEntityParser.java
com.dreamteam.app.commons.SectionHelper.java
com.dreamteam.app.commons.SeriaHelper.java
com.dreamteam.app.commons.SkinManager.java
com.dreamteam.app.commons.UIHelper.java
com.dreamteam.app.config.Contants.java
com.dreamteam.app.db.DbManager.java
com.dreamteam.app.db.FavoItemDbHelper.java
com.dreamteam.app.db.FeedDBManager.java
com.dreamteam.app.db.provider.RSSFeedCategoryProvider.java
com.dreamteam.app.entity.FeedItem.java
com.dreamteam.app.entity.Feed.java
com.dreamteam.app.entity.ItemListEntity.java
com.dreamteam.app.entity.RSSFeedCategroy.java
com.dreamteam.app.entity.Section.java
com.dreamteam.app.img.FileCacheManager.java
com.dreamteam.app.img.FileCache.java
com.dreamteam.app.img.ICache.java
com.dreamteam.app.img.ImageLoadTask.java
com.dreamteam.app.img.ImageLoad.java
com.dreamteam.app.img.ImageLoader.java
com.dreamteam.app.img.MemoryCache.java
com.dreamteam.app.rss.Dates.java
com.dreamteam.app.rss.Integers.java
com.dreamteam.app.rss.MediaAttributes.java
com.dreamteam.app.rss.MediaEnclosure.java
com.dreamteam.app.rss.MediaThumbnail.java
com.dreamteam.app.rss.RSSBase.java
com.dreamteam.app.rss.RSSConfig.java
com.dreamteam.app.rss.RSSException.java
com.dreamteam.app.rss.RSSFault.java
com.dreamteam.app.rss.RSSFeed.java
com.dreamteam.app.rss.RSSHandler.java
com.dreamteam.app.rss.RSSItem.java
com.dreamteam.app.rss.RSSLoader.java
com.dreamteam.app.rss.RSSParserSPI.java
com.dreamteam.app.rss.RSSParser.java
com.dreamteam.app.rss.RSSReaderException.java
com.dreamteam.app.rss.RSSReader.java
com.dreamteam.app.rss.Resources.java
com.dreamteam.app.ui.About.java
com.dreamteam.app.ui.BaseActivity.java
com.dreamteam.app.ui.BaseTitledActivity.java
com.dreamteam.app.ui.CategoryDetailActivity.java
com.dreamteam.app.ui.ColorListActivity.java
com.dreamteam.app.ui.FavoriteItemList.java
com.dreamteam.app.ui.FeedCategoryActivity.java
com.dreamteam.app.ui.FeedbackUI.java
com.dreamteam.app.ui.GuideActivity.java
com.dreamteam.app.ui.ImageDialog.java
com.dreamteam.app.ui.ImagesBrowseActivity.java
com.dreamteam.app.ui.ItemDetailActivity.java
com.dreamteam.app.ui.ItemListActivity.java
com.dreamteam.app.ui.LocalImageBrowseActivity.java
com.dreamteam.app.ui.LoginDialog.java
com.dreamteam.app.ui.MainActivity.java
com.dreamteam.app.ui.Setting.java
com.dreamteam.app.ui.SplashActivity.java
com.dreamteam.app.ui.SwitchBgActivity.java
com.dreamteam.app.ui.WidgetProvider.java
com.dreamteam.app.ui.adapter.ColorListAdapter.java
com.dreamteam.app.utils.CategoryNameExchange.java
com.dreamteam.app.utils.DateUtils.java
com.dreamteam.app.utils.FileUtils.java
com.dreamteam.app.utils.HttpUtils.java
com.dreamteam.app.utils.ImageLoader.java
com.dreamteam.app.utils.ImageUtils.java
com.dreamteam.app.utils.Logger.java
com.dreamteam.app.utils.MD5.java
com.dreamteam.app.utils.StringUtils.java
com.dreamteam.app.wallpaper.ChildAdapter.java
com.dreamteam.app.wallpaper.GroupGridAdapter.java
com.dreamteam.app.wallpaper.ImageBean.java
com.dreamteam.app.wallpaper.MyImageView.java
com.dreamteam.app.wallpaper.NativeImageLoader.java
com.dreamteam.app.wallpaper.WallPaperManager.java
com.dreamteam.custom.ui.PathAnimations.java
com.dreamteam.custom.ui.PullToRefreshListView.java