FileDocCategorySizeDatePackage
XmlGDataParser.javaAPI DocAndroid 1.5 API17147Wed May 06 22:41:16 BST 2009com.google.wireless.gdata.parser.xml

XmlGDataParser

public class XmlGDataParser extends Object implements com.google.wireless.gdata.parser.GDataParser
{@link GDataParser} that uses an {@link XmlPullParser} to parse a GData feed.

Fields Summary
public static final String
NAMESPACE_ATOM_URI
Namespace URI for Atom
public static final String
NAMESPACE_OPENSEARCH
public static final String
NAMESPACE_OPENSEARCH_URI
public static final String
NAMESPACE_GD
Namespace prefix for GData
public static final String
NAMESPACE_GD_URI
Namespace URI for GData
private final InputStream
is
private final XmlPullParser
parser
private boolean
isInBadState
Constructors Summary
public XmlGDataParser(InputStream is, XmlPullParser parser)
Creates a new XmlGDataParser for a feed in the provided InputStream.

param
is The InputStream that should be parsed.
throws
ParseException Thrown if an XmlPullParser could not be created or set around this InputStream.


                                       
      
        
    this.is = is;
    this.parser = parser;
    this.isInBadState = false;
    if (this.is != null) {
      try {
        this.parser.setInput(is, null /* encoding */);
      } catch (XmlPullParserException e) {
        throw new ParseException("Could not create XmlGDataParser", e);
      }
    }
  
Methods Summary
public voidclose()

    if (is != null) {
      try {
        is.close();
      } catch (IOException ioe) {
        // ignore
      }
    }
  
protected com.google.wireless.gdata.data.EntrycreateEntry()
Creates a new {@link Entry} that should be filled with information about the entry that will be parsed.

return
The {@link Entry} that should be filled.

    return new Entry();
  
protected com.google.wireless.gdata.data.FeedcreateFeed()
Creates a new {@link Feed} that should be filled with information about the feed that will be parsed.

return
The {@link Feed} that should be filled.

    return new Feed();
  
protected final org.xmlpull.v1.XmlPullParsergetParser()
Returns the {@link XmlPullParser} being used to parse this feed.

    return parser;
  
private voidhandleAuthor(com.google.wireless.gdata.data.Entry entry)


    int eventType = parser.getEventType();
    String name = parser.getName();

    if (eventType != XmlPullParser.START_TAG ||
        (!"author".equals(parser.getName()))) {
      // should not happen.
      throw new
          IllegalStateException("Expected <author>: Actual element: <"
          + parser.getName() + ">");
    }

    eventType = parser.next();
    while (eventType != XmlPullParser.END_DOCUMENT) {
      switch (eventType) {
        case XmlPullParser.START_TAG:
          name = parser.getName();
          if ("name".equals(name)) {
            String authorName = XmlUtils.extractChildText(parser);
            entry.setAuthor(authorName);
          } else if ("email".equals(name)) {
            String email = XmlUtils.extractChildText(parser);
            entry.setEmail(email);
          }
          break;
        case XmlPullParser.END_TAG:
          name = parser.getName();
          if ("author".equals(name)) {
            return;
          }
        default:
          // ignore
      }

      eventType = parser.next();
    }
  
protected voidhandleEntry(com.google.wireless.gdata.data.Entry entry)
Parses the current entry in the XML document. Assumes that the parser is currently pointing just after an <entry>.

param
entry The entry that will be filled.
throws
XmlPullParserException Thrown if the XML cannot be parsed.
throws
IOException Thrown if the underlying inputstream cannot be read.

    int eventType = parser.getEventType();
    while (eventType != XmlPullParser.END_DOCUMENT) {
      switch (eventType) {
        case XmlPullParser.START_TAG:
          // TODO: make sure these elements are at the expected depth.
          String name = parser.getName();
          if ("entry".equals(name)) {
            // stop parsing here.
            return;
          } else if ("id".equals(name)) {
            entry.setId(XmlUtils.extractChildText(parser));
          } else if ("title".equals(name)) {
            entry.setTitle(XmlUtils.extractChildText(parser));
          } else if ("link".equals(name)) {
            String rel =
                parser.getAttributeValue(null /* ns */, "rel");
            String type =
                parser.getAttributeValue(null /* ns */, "type");
            String href =
                parser.getAttributeValue(null /* ns */, "href");
            if ("edit".equals(rel)) {
              entry.setEditUri(href);
            } else if (("alternate").equals(rel) && ("text/html".equals(type))) {
                entry.setHtmlUri(href);
            } else {
              handleExtraLinkInEntry(rel,
                  type,
                  href,
                  entry);
            }
          } else if ("summary".equals(name)) {
            entry.setSummary(XmlUtils.extractChildText(parser));
          } else if ("content".equals(name)) {
            // TODO: parse the type
            entry.setContent(XmlUtils.extractChildText(parser));
          } else if ("author".equals(name)) {
            handleAuthor(entry);
          } else if ("category".equals(name)) {
            String category =
                parser.getAttributeValue(null /* ns */, "term");
            if (category != null && category.length() > 0) {
              entry.setCategory(category);
            }
            String categoryScheme =
                parser.getAttributeValue(null /* ns */, "scheme");
            if (categoryScheme != null && category.length() > 0) {
              entry.setCategoryScheme(categoryScheme);
            }
          } else if ("published".equals(name)) {
            entry.setPublicationDate(
                XmlUtils.extractChildText(parser));
          } else if ("updated".equals(name)) {
            entry.setUpdateDate(XmlUtils.extractChildText(parser));
          } else if ("deleted".equals(name)) {
            entry.setDeleted(true);
          } else {
            handleExtraElementInEntry(entry);
          }
          break;
        default:
          break;
      }

      eventType = parser.next();
    }
  
protected voidhandleExtraElementInEntry(com.google.wireless.gdata.data.Entry entry)
Hook that allows extra (service-specific) elements in an <entry> to be parsed.

param
entry The {@link Entry} being filled.

    // no-op in this class.
  
protected voidhandleExtraElementInFeed(com.google.wireless.gdata.data.Feed feed)
Hook that allows extra (service-specific) elements in a <feed> to be parsed.

param
feed The {@link Feed} being filled.

    // no-op in this class.
  
protected voidhandleExtraLinkInEntry(java.lang.String rel, java.lang.String type, java.lang.String href, com.google.wireless.gdata.data.Entry entry)
Hook that allows extra (service-specific) <link>s in an entry to be parsed.

param
rel The rel attribute value.
param
type The type attribute value.
param
href The href attribute value.
param
entry The {@link Entry} being filled.

    // no-op in this class.
  
public booleanhasMoreData()

    if (isInBadState) {
      return false;
    }
    try {
      int eventType = parser.getEventType();
      return (eventType != XmlPullParser.END_DOCUMENT);
    } catch (XmlPullParserException xppe) {
      return false;
    }
  
public final com.google.wireless.gdata.data.Feedinit()

    int eventType;
    try {
      eventType = parser.getEventType();
    } catch (XmlPullParserException e) {
      throw new ParseException("Could not parse GData feed.", e);
    }
    if (eventType != XmlPullParser.START_DOCUMENT) {
      throw new ParseException("Attempting to initialize parsing beyond "
          + "the start of the document.");
    }

    try {
      eventType = parser.next();
    } catch (XmlPullParserException xppe) {
      throw new ParseException("Could not read next event.", xppe);
    } catch (IOException ioe) {
      throw new ParseException("Could not read next event.", ioe);
    }
    while (eventType != XmlPullParser.END_DOCUMENT) {
      switch (eventType) {
        case XmlPullParser.START_TAG:
          String name = parser.getName();
          if ("feed".equals(name)) {
            try {
              return parseFeed();
            } catch (XmlPullParserException xppe) {
              throw new ParseException("Unable to parse <feed>.",
                  xppe);
            } catch (IOException ioe) {
              throw new ParseException("Unable to parse <feed>.",
                  ioe);
            }
          }
          break;
        default:
          // ignore
          break;
      }

      try {
        eventType = parser.next();
      } catch (XmlPullParserException xppe) {
        throw new ParseException("Could not read next event.", xppe);
      } catch (IOException ioe) {
        throw new ParseException("Could not read next event." , ioe);
      }
    }
    throw new ParseException("No <feed> found in document.");
  
private final com.google.wireless.gdata.data.FeedparseFeed()
Parses the feed (but not any entries).

return
A new {@link Feed} containing information about the feed.
throws
XmlPullParserException Thrown if the XML document cannot be parsed.
throws
IOException Thrown if the {@link InputStream} behind the feed cannot be read.

    Feed feed = createFeed();
    // parsing <feed>
    // not interested in any attributes -- move onto the children.
    int eventType = parser.next();
    while (eventType != XmlPullParser.END_DOCUMENT) {
      switch (eventType) {
        case XmlPullParser.START_TAG:
          String name = parser.getName();
          if ("totalResults".equals(name)) {
            feed.setTotalResults(StringUtils.parseInt(
                XmlUtils.extractChildText(parser), 0));
          } else if ("startIndex".equals(name)) {
            feed.setStartIndex(StringUtils.parseInt(
                XmlUtils.extractChildText(parser), 0));
          } else if ("itemsPerPage".equals(name)) {
            feed.setItemsPerPage(StringUtils.parseInt(
                XmlUtils.extractChildText(parser), 0));
          } else if ("title".equals(name)) {
            feed.setTitle(XmlUtils.extractChildText(parser));
          } else if ("id".equals(name)) {
            feed.setId(XmlUtils.extractChildText(parser));
          } else if ("updated".equals(name)) {
            feed.setLastUpdated(XmlUtils.extractChildText(parser));
          } else if ("category".equals(name)) {
            String category =
                parser.getAttributeValue(null /* ns */, "term");
            if (!StringUtils.isEmpty(category)) {
              feed.setCategory(category);
            }
            String categoryScheme =
                parser.getAttributeValue(null /* ns */, "scheme");
            if (!StringUtils.isEmpty(categoryScheme)) {
              feed.setCategoryScheme(categoryScheme);
            }
          } else if ("entry".equals(name)) {
            // stop parsing here.
            // TODO: pay attention to depth?
            return feed;
          } else {
            handleExtraElementInFeed(feed);
          }
          break;
        default:
          break;
      }
      eventType = parser.next();
    }
    // if we get here, we have a feed with no entries.
    return feed;
  
public com.google.wireless.gdata.data.EntryparseStandaloneEntry()
Parses a GData entry. You can either call {@link #init()} or {@link #parseStandaloneEntry()} for a given feed.

return
The parsed entry.
throws
ParseException Thrown if the entry could not be parsed.

    Entry entry = createEntry();

    int eventType;
    try {
      eventType = parser.getEventType();
    } catch (XmlPullParserException e) {
      throw new ParseException("Could not parse GData entry.", e);
    }
    if (eventType != XmlPullParser.START_DOCUMENT) {
      throw new ParseException("Attempting to initialize parsing beyond "
          + "the start of the document.");
    }

    try {
      eventType = parser.next();
    } catch (XmlPullParserException xppe) {
      throw new ParseException("Could not read next event.", xppe);
    } catch (IOException ioe) {
      throw new ParseException("Could not read next event.", ioe);
    }
    while (eventType != XmlPullParser.END_DOCUMENT) {
      switch (eventType) {
        case XmlPullParser.START_TAG:
          String name = parser.getName();
          if ("entry".equals(name)) {
            try {
              parser.next();
              handleEntry(entry);
              return entry;
            } catch (XmlPullParserException xppe) {
              throw new ParseException("Unable to parse <entry>.",
                  xppe);
            } catch (IOException ioe) {
              throw new ParseException("Unable to parse <entry>.",
                  ioe);
            }
          }
          break;
        default:
          // ignore
          break;
      }

      try {
        eventType = parser.next();
      } catch (XmlPullParserException xppe) {
        throw new ParseException("Could not read next event.", xppe);
      }
    }
    throw new ParseException("No <entry> found in document.");
  
public com.google.wireless.gdata.data.EntryreadNextEntry(com.google.wireless.gdata.data.Entry entry)

    if (!hasMoreData()) {
      throw new IllegalStateException("you shouldn't call this if hasMoreData() is false");
    }

    int eventType;
    try {
      eventType = parser.getEventType();
    } catch (XmlPullParserException e) {
      throw new ParseException("Could not parse entry.", e);
    }

    if (eventType != XmlPullParser.START_TAG) {
      throw new ParseException("Expected event START_TAG: Actual event: "
          + XmlPullParser.TYPES[eventType]);
    }

    String name = parser.getName();
    if (!"entry".equals(name)) {
      throw new ParseException("Expected <entry>: Actual element: "
          + "<" + name + ">");
    }

    if (entry == null) {
      entry = createEntry();
    } else {
      entry.clear();
    }

    try {
      parser.next();
      handleEntry(entry);
      entry.validate();
    } catch (ParseException xppe1) {
      try {
        if (hasMoreData()) skipToNextEntry();
      } catch (XmlPullParserException xppe2) {
        // squelch the error -- let the original one stand.
        // set isInBadState to ensure that the next call to hasMoreData() will return false.
        isInBadState = true;
      }
      throw new ParseException("Could not parse <entry>, " + entry, xppe1);
    } catch (XmlPullParserException xppe1) {
      try {
        if (hasMoreData()) skipToNextEntry();
      } catch (XmlPullParserException xppe2) {
        // squelch the error -- let the original one stand.
        // set isInBadState to ensure that the next call to hasMoreData() will return false.
        isInBadState = true;
      }
      throw new ParseException("Could not parse <entry>, " + entry, xppe1);
    }
    return entry;
  
protected voidskipToNextEntry()
Skips the rest of the current entry until the parser reaches the next entry, if any. Does nothing if the parser is already at the beginning of an entry.

    if (!hasMoreData()) {
      throw new IllegalStateException("you shouldn't call this if hasMoreData() is false");
    }

    int eventType = parser.getEventType();

    // skip ahead until we reach an <entry> tag.
    while (eventType != XmlPullParser.END_DOCUMENT) {
      switch (eventType) {
        case XmlPullParser.START_TAG:
          if ("entry".equals(parser.getName())) {
            return;
          }
          break;
      }
      eventType = parser.next();
    }