Home | History | Annotate | Download | only in picasa
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.cooliris.picasa;
     18 
     19 import org.xml.sax.Attributes;
     20 import org.xml.sax.ContentHandler;
     21 import org.xml.sax.Locator;
     22 import org.xml.sax.SAXException;
     23 import org.xml.sax.helpers.AttributesImpl;
     24 
     25 import android.text.format.Time;
     26 
     27 public final class GDataParser implements ContentHandler {
     28     public static final String APP_NAMESPACE = "http://www.w3.org/2007/app";
     29     public static final String ATOM_NAMESPACE = "http://www.w3.org/2005/Atom";
     30     public static final String GD_NAMESPACE = "http://schemas.google.com/g/2005";
     31     public static final String GPHOTO_NAMESPACE = "http://schemas.google.com/photos/2007";
     32     public static final String MEDIA_RSS_NAMESPACE = "http://search.yahoo.com/mrss/";
     33     public static final String GML_NAMESPACE = "http://www.opengis.net/gml";
     34     private static final String FEED_ELEMENT = "feed";
     35     private static final String ENTRY_ELEMENT = "entry";
     36 
     37     private static final int STATE_DOCUMENT = 0;
     38     private static final int STATE_FEED = 1;
     39     private static final int STATE_ENTRY = 2;
     40 
     41     private static final int NUM_LEVELS = 5;
     42 
     43     private Entry mEntry = null;
     44     private EntryHandler mHandler = null;
     45     private int mState = STATE_DOCUMENT;
     46     private int mLevel = 0;
     47     private String[] mUri = new String[NUM_LEVELS];
     48     private String[] mName = new String[NUM_LEVELS];
     49     private AttributesImpl[] mAttributes = new AttributesImpl[NUM_LEVELS];
     50     private final StringBuilder mValue = new StringBuilder(128);
     51 
     52     public interface EntryHandler {
     53         void handleEntry(Entry entry);
     54     }
     55 
     56     public GDataParser() {
     57         AttributesImpl[] attributes = mAttributes;
     58         for (int i = 0; i != NUM_LEVELS; ++i) {
     59             attributes[i] = new AttributesImpl();
     60         }
     61     }
     62 
     63     public void setEntry(Entry entry) {
     64         mEntry = entry;
     65     }
     66 
     67     public void setHandler(EntryHandler handler) {
     68         mHandler = handler;
     69     }
     70 
     71     public static long parseAtomTimestamp(String timestamp) {
     72         Time time = new Time();
     73         time.parse3339(timestamp);
     74         return time.toMillis(true);
     75     }
     76 
     77     public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
     78         switch (mState) {
     79         case STATE_DOCUMENT:
     80             // Expect an atom:feed element.
     81             if (uri.equals(ATOM_NAMESPACE) && localName.equals(FEED_ELEMENT)) {
     82                 mState = STATE_FEED;
     83             } else {
     84                 throw new SAXException();
     85             }
     86             break;
     87         case STATE_FEED:
     88             // Expect a feed property element or an atom:entry element.
     89             if (uri.equals(ATOM_NAMESPACE) && localName.equals(ENTRY_ELEMENT)) {
     90                 mState = STATE_ENTRY;
     91                 mEntry.clear();
     92             } else {
     93                 startProperty(uri, localName, attrs);
     94             }
     95             break;
     96         case STATE_ENTRY:
     97             startProperty(uri, localName, attrs);
     98             break;
     99         }
    100     }
    101 
    102     public void endElement(String uri, String localName, String qName) throws SAXException {
    103         if (mLevel > 0) {
    104             // Handle property exit.
    105             endProperty();
    106         } else {
    107             // Handle state exit.
    108             switch (mState) {
    109             case STATE_DOCUMENT:
    110                 throw new SAXException();
    111             case STATE_FEED:
    112                 mState = STATE_DOCUMENT;
    113                 break;
    114             case STATE_ENTRY:
    115                 mState = STATE_FEED;
    116                 mHandler.handleEntry(mEntry);
    117                 break;
    118             }
    119         }
    120     }
    121 
    122     private void startProperty(String uri, String localName, Attributes attrs) {
    123         // Push element information onto the property stack.
    124         int level = mLevel + 1;
    125         mLevel = level;
    126         mValue.setLength(0);
    127         mUri[level] = uri;
    128         mName[level] = localName;
    129         mAttributes[level].setAttributes(attrs);
    130     }
    131 
    132     private void endProperty() {
    133         // Apply property to the entry, then pop the stack.
    134         int level = mLevel;
    135         mEntry.setPropertyFromXml(mUri[level], mName[level], mAttributes[level], mValue.toString());
    136         mLevel = level - 1;
    137     }
    138 
    139     public void characters(char[] ch, int start, int length) throws SAXException {
    140         mValue.append(ch, start, length);
    141     }
    142 
    143     public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
    144         // Ignored.
    145     }
    146 
    147     public void processingInstruction(String target, String data) throws SAXException {
    148         // Ignored.
    149     }
    150 
    151     public void setDocumentLocator(Locator locator) {
    152         // Ignored.
    153     }
    154 
    155     public void skippedEntity(String name) throws SAXException {
    156         // Ignored.
    157     }
    158 
    159     public void startDocument() throws SAXException {
    160         // Ignored.
    161     }
    162 
    163     public void endDocument() throws SAXException {
    164         // Ignored.
    165     }
    166 
    167     public void startPrefixMapping(String prefix, String uri) throws SAXException {
    168         // Ignored.
    169     }
    170 
    171     public void endPrefixMapping(String prefix) throws SAXException {
    172         // Ignored.
    173     }
    174 }
    175