Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2006 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.android.internal.util;
     18 
     19 import android.util.Xml;
     20 
     21 import org.xmlpull.v1.XmlPullParser;
     22 import org.xmlpull.v1.XmlPullParserException;
     23 import org.xmlpull.v1.XmlSerializer;
     24 
     25 import java.io.IOException;
     26 import java.io.InputStream;
     27 import java.io.OutputStream;
     28 import java.net.ProtocolException;
     29 import java.util.ArrayList;
     30 import java.util.HashMap;
     31 import java.util.HashSet;
     32 import java.util.Iterator;
     33 import java.util.List;
     34 import java.util.Map;
     35 import java.util.Set;
     36 
     37 /** {@hide} */
     38 public class XmlUtils {
     39 
     40     public static void skipCurrentTag(XmlPullParser parser)
     41             throws XmlPullParserException, IOException {
     42         int outerDepth = parser.getDepth();
     43         int type;
     44         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
     45                && (type != XmlPullParser.END_TAG
     46                        || parser.getDepth() > outerDepth)) {
     47         }
     48     }
     49 
     50     public static final int
     51     convertValueToList(CharSequence value, String[] options, int defaultValue)
     52     {
     53         if (null != value) {
     54             for (int i = 0; i < options.length; i++) {
     55                 if (value.equals(options[i]))
     56                     return i;
     57             }
     58         }
     59 
     60         return defaultValue;
     61     }
     62 
     63     public static final boolean
     64     convertValueToBoolean(CharSequence value, boolean defaultValue)
     65     {
     66         boolean result = false;
     67 
     68         if (null == value)
     69             return defaultValue;
     70 
     71         if (value.equals("1")
     72         ||  value.equals("true")
     73         ||  value.equals("TRUE"))
     74             result = true;
     75 
     76         return result;
     77     }
     78 
     79     public static final int
     80     convertValueToInt(CharSequence charSeq, int defaultValue)
     81     {
     82         if (null == charSeq)
     83             return defaultValue;
     84 
     85         String nm = charSeq.toString();
     86 
     87         // XXX This code is copied from Integer.decode() so we don't
     88         // have to instantiate an Integer!
     89 
     90         int value;
     91         int sign = 1;
     92         int index = 0;
     93         int len = nm.length();
     94         int base = 10;
     95 
     96         if ('-' == nm.charAt(0)) {
     97             sign = -1;
     98             index++;
     99         }
    100 
    101         if ('0' == nm.charAt(index)) {
    102             //  Quick check for a zero by itself
    103             if (index == (len - 1))
    104                 return 0;
    105 
    106             char    c = nm.charAt(index + 1);
    107 
    108             if ('x' == c || 'X' == c) {
    109                 index += 2;
    110                 base = 16;
    111             } else {
    112                 index++;
    113                 base = 8;
    114             }
    115         }
    116         else if ('#' == nm.charAt(index))
    117         {
    118             index++;
    119             base = 16;
    120         }
    121 
    122         return Integer.parseInt(nm.substring(index), base) * sign;
    123     }
    124 
    125     public static int convertValueToUnsignedInt(String value, int defaultValue) {
    126         if (null == value) {
    127             return defaultValue;
    128         }
    129 
    130         return parseUnsignedIntAttribute(value);
    131     }
    132 
    133     public static int parseUnsignedIntAttribute(CharSequence charSeq) {
    134         String  value = charSeq.toString();
    135 
    136         long    bits;
    137         int     index = 0;
    138         int     len = value.length();
    139         int     base = 10;
    140 
    141         if ('0' == value.charAt(index)) {
    142             //  Quick check for zero by itself
    143             if (index == (len - 1))
    144                 return 0;
    145 
    146             char    c = value.charAt(index + 1);
    147 
    148             if ('x' == c || 'X' == c) {     //  check for hex
    149                 index += 2;
    150                 base = 16;
    151             } else {                        //  check for octal
    152                 index++;
    153                 base = 8;
    154             }
    155         } else if ('#' == value.charAt(index)) {
    156             index++;
    157             base = 16;
    158         }
    159 
    160         return (int) Long.parseLong(value.substring(index), base);
    161     }
    162 
    163     /**
    164      * Flatten a Map into an output stream as XML.  The map can later be
    165      * read back with readMapXml().
    166      *
    167      * @param val The map to be flattened.
    168      * @param out Where to write the XML data.
    169      *
    170      * @see #writeMapXml(Map, String, XmlSerializer)
    171      * @see #writeListXml
    172      * @see #writeValueXml
    173      * @see #readMapXml
    174      */
    175     public static final void writeMapXml(Map val, OutputStream out)
    176             throws XmlPullParserException, java.io.IOException {
    177         XmlSerializer serializer = new FastXmlSerializer();
    178         serializer.setOutput(out, "utf-8");
    179         serializer.startDocument(null, true);
    180         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
    181         writeMapXml(val, null, serializer);
    182         serializer.endDocument();
    183     }
    184 
    185     /**
    186      * Flatten a List into an output stream as XML.  The list can later be
    187      * read back with readListXml().
    188      *
    189      * @param val The list to be flattened.
    190      * @param out Where to write the XML data.
    191      *
    192      * @see #writeListXml(List, String, XmlSerializer)
    193      * @see #writeMapXml
    194      * @see #writeValueXml
    195      * @see #readListXml
    196      */
    197     public static final void writeListXml(List val, OutputStream out)
    198     throws XmlPullParserException, java.io.IOException
    199     {
    200         XmlSerializer serializer = Xml.newSerializer();
    201         serializer.setOutput(out, "utf-8");
    202         serializer.startDocument(null, true);
    203         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
    204         writeListXml(val, null, serializer);
    205         serializer.endDocument();
    206     }
    207 
    208     /**
    209      * Flatten a Map into an XmlSerializer.  The map can later be read back
    210      * with readThisMapXml().
    211      *
    212      * @param val The map to be flattened.
    213      * @param name Name attribute to include with this list's tag, or null for
    214      *             none.
    215      * @param out XmlSerializer to write the map into.
    216      *
    217      * @see #writeMapXml(Map, OutputStream)
    218      * @see #writeListXml
    219      * @see #writeValueXml
    220      * @see #readMapXml
    221      */
    222     public static final void writeMapXml(Map val, String name, XmlSerializer out)
    223     throws XmlPullParserException, java.io.IOException
    224     {
    225         if (val == null) {
    226             out.startTag(null, "null");
    227             out.endTag(null, "null");
    228             return;
    229         }
    230 
    231         Set s = val.entrySet();
    232         Iterator i = s.iterator();
    233 
    234         out.startTag(null, "map");
    235         if (name != null) {
    236             out.attribute(null, "name", name);
    237         }
    238 
    239         while (i.hasNext()) {
    240             Map.Entry e = (Map.Entry)i.next();
    241             writeValueXml(e.getValue(), (String)e.getKey(), out);
    242         }
    243 
    244         out.endTag(null, "map");
    245     }
    246 
    247     /**
    248      * Flatten a List into an XmlSerializer.  The list can later be read back
    249      * with readThisListXml().
    250      *
    251      * @param val The list to be flattened.
    252      * @param name Name attribute to include with this list's tag, or null for
    253      *             none.
    254      * @param out XmlSerializer to write the list into.
    255      *
    256      * @see #writeListXml(List, OutputStream)
    257      * @see #writeMapXml
    258      * @see #writeValueXml
    259      * @see #readListXml
    260      */
    261     public static final void writeListXml(List val, String name, XmlSerializer out)
    262     throws XmlPullParserException, java.io.IOException
    263     {
    264         if (val == null) {
    265             out.startTag(null, "null");
    266             out.endTag(null, "null");
    267             return;
    268         }
    269 
    270         out.startTag(null, "list");
    271         if (name != null) {
    272             out.attribute(null, "name", name);
    273         }
    274 
    275         int N = val.size();
    276         int i=0;
    277         while (i < N) {
    278             writeValueXml(val.get(i), null, out);
    279             i++;
    280         }
    281 
    282         out.endTag(null, "list");
    283     }
    284 
    285     public static final void writeSetXml(Set val, String name, XmlSerializer out)
    286             throws XmlPullParserException, java.io.IOException {
    287         if (val == null) {
    288             out.startTag(null, "null");
    289             out.endTag(null, "null");
    290             return;
    291         }
    292 
    293         out.startTag(null, "set");
    294         if (name != null) {
    295             out.attribute(null, "name", name);
    296         }
    297 
    298         for (Object v : val) {
    299             writeValueXml(v, null, out);
    300         }
    301 
    302         out.endTag(null, "set");
    303     }
    304 
    305     /**
    306      * Flatten a byte[] into an XmlSerializer.  The list can later be read back
    307      * with readThisByteArrayXml().
    308      *
    309      * @param val The byte array to be flattened.
    310      * @param name Name attribute to include with this array's tag, or null for
    311      *             none.
    312      * @param out XmlSerializer to write the array into.
    313      *
    314      * @see #writeMapXml
    315      * @see #writeValueXml
    316      */
    317     public static final void writeByteArrayXml(byte[] val, String name,
    318             XmlSerializer out)
    319             throws XmlPullParserException, java.io.IOException {
    320 
    321         if (val == null) {
    322             out.startTag(null, "null");
    323             out.endTag(null, "null");
    324             return;
    325         }
    326 
    327         out.startTag(null, "byte-array");
    328         if (name != null) {
    329             out.attribute(null, "name", name);
    330         }
    331 
    332         final int N = val.length;
    333         out.attribute(null, "num", Integer.toString(N));
    334 
    335         StringBuilder sb = new StringBuilder(val.length*2);
    336         for (int i=0; i<N; i++) {
    337             int b = val[i];
    338             int h = b>>4;
    339             sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
    340             h = b&0xff;
    341             sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
    342         }
    343 
    344         out.text(sb.toString());
    345 
    346         out.endTag(null, "byte-array");
    347     }
    348 
    349     /**
    350      * Flatten an int[] into an XmlSerializer.  The list can later be read back
    351      * with readThisIntArrayXml().
    352      *
    353      * @param val The int array to be flattened.
    354      * @param name Name attribute to include with this array's tag, or null for
    355      *             none.
    356      * @param out XmlSerializer to write the array into.
    357      *
    358      * @see #writeMapXml
    359      * @see #writeValueXml
    360      * @see #readThisIntArrayXml
    361      */
    362     public static final void writeIntArrayXml(int[] val, String name,
    363             XmlSerializer out)
    364             throws XmlPullParserException, java.io.IOException {
    365 
    366         if (val == null) {
    367             out.startTag(null, "null");
    368             out.endTag(null, "null");
    369             return;
    370         }
    371 
    372         out.startTag(null, "int-array");
    373         if (name != null) {
    374             out.attribute(null, "name", name);
    375         }
    376 
    377         final int N = val.length;
    378         out.attribute(null, "num", Integer.toString(N));
    379 
    380         for (int i=0; i<N; i++) {
    381             out.startTag(null, "item");
    382             out.attribute(null, "value", Integer.toString(val[i]));
    383             out.endTag(null, "item");
    384         }
    385 
    386         out.endTag(null, "int-array");
    387     }
    388 
    389     /**
    390      * Flatten an object's value into an XmlSerializer.  The value can later
    391      * be read back with readThisValueXml().
    392      *
    393      * Currently supported value types are: null, String, Integer, Long,
    394      * Float, Double Boolean, Map, List.
    395      *
    396      * @param v The object to be flattened.
    397      * @param name Name attribute to include with this value's tag, or null
    398      *             for none.
    399      * @param out XmlSerializer to write the object into.
    400      *
    401      * @see #writeMapXml
    402      * @see #writeListXml
    403      * @see #readValueXml
    404      */
    405     public static final void writeValueXml(Object v, String name, XmlSerializer out)
    406     throws XmlPullParserException, java.io.IOException
    407     {
    408         String typeStr;
    409         if (v == null) {
    410             out.startTag(null, "null");
    411             if (name != null) {
    412                 out.attribute(null, "name", name);
    413             }
    414             out.endTag(null, "null");
    415             return;
    416         } else if (v instanceof String) {
    417             out.startTag(null, "string");
    418             if (name != null) {
    419                 out.attribute(null, "name", name);
    420             }
    421             out.text(v.toString());
    422             out.endTag(null, "string");
    423             return;
    424         } else if (v instanceof Integer) {
    425             typeStr = "int";
    426         } else if (v instanceof Long) {
    427             typeStr = "long";
    428         } else if (v instanceof Float) {
    429             typeStr = "float";
    430         } else if (v instanceof Double) {
    431             typeStr = "double";
    432         } else if (v instanceof Boolean) {
    433             typeStr = "boolean";
    434         } else if (v instanceof byte[]) {
    435             writeByteArrayXml((byte[])v, name, out);
    436             return;
    437         } else if (v instanceof int[]) {
    438             writeIntArrayXml((int[])v, name, out);
    439             return;
    440         } else if (v instanceof Map) {
    441             writeMapXml((Map)v, name, out);
    442             return;
    443         } else if (v instanceof List) {
    444             writeListXml((List)v, name, out);
    445             return;
    446         } else if (v instanceof Set) {
    447             writeSetXml((Set)v, name, out);
    448             return;
    449         } else if (v instanceof CharSequence) {
    450             // XXX This is to allow us to at least write something if
    451             // we encounter styled text...  but it means we will drop all
    452             // of the styling information. :(
    453             out.startTag(null, "string");
    454             if (name != null) {
    455                 out.attribute(null, "name", name);
    456             }
    457             out.text(v.toString());
    458             out.endTag(null, "string");
    459             return;
    460         } else {
    461             throw new RuntimeException("writeValueXml: unable to write value " + v);
    462         }
    463 
    464         out.startTag(null, typeStr);
    465         if (name != null) {
    466             out.attribute(null, "name", name);
    467         }
    468         out.attribute(null, "value", v.toString());
    469         out.endTag(null, typeStr);
    470     }
    471 
    472     /**
    473      * Read a HashMap from an InputStream containing XML.  The stream can
    474      * previously have been written by writeMapXml().
    475      *
    476      * @param in The InputStream from which to read.
    477      *
    478      * @return HashMap The resulting map.
    479      *
    480      * @see #readListXml
    481      * @see #readValueXml
    482      * @see #readThisMapXml
    483      * #see #writeMapXml
    484      */
    485     public static final HashMap readMapXml(InputStream in)
    486     throws XmlPullParserException, java.io.IOException
    487     {
    488         XmlPullParser   parser = Xml.newPullParser();
    489         parser.setInput(in, null);
    490         return (HashMap)readValueXml(parser, new String[1]);
    491     }
    492 
    493     /**
    494      * Read an ArrayList from an InputStream containing XML.  The stream can
    495      * previously have been written by writeListXml().
    496      *
    497      * @param in The InputStream from which to read.
    498      *
    499      * @return ArrayList The resulting list.
    500      *
    501      * @see #readMapXml
    502      * @see #readValueXml
    503      * @see #readThisListXml
    504      * @see #writeListXml
    505      */
    506     public static final ArrayList readListXml(InputStream in)
    507     throws XmlPullParserException, java.io.IOException
    508     {
    509         XmlPullParser   parser = Xml.newPullParser();
    510         parser.setInput(in, null);
    511         return (ArrayList)readValueXml(parser, new String[1]);
    512     }
    513 
    514 
    515     /**
    516      * Read a HashSet from an InputStream containing XML. The stream can
    517      * previously have been written by writeSetXml().
    518      *
    519      * @param in The InputStream from which to read.
    520      *
    521      * @return HashSet The resulting set.
    522      *
    523      * @throws XmlPullParserException
    524      * @throws java.io.IOException
    525      *
    526      * @see #readValueXml
    527      * @see #readThisSetXml
    528      * @see #writeSetXml
    529      */
    530     public static final HashSet readSetXml(InputStream in)
    531             throws XmlPullParserException, java.io.IOException {
    532         XmlPullParser parser = Xml.newPullParser();
    533         parser.setInput(in, null);
    534         return (HashSet) readValueXml(parser, new String[1]);
    535     }
    536 
    537     /**
    538      * Read a HashMap object from an XmlPullParser.  The XML data could
    539      * previously have been generated by writeMapXml().  The XmlPullParser
    540      * must be positioned <em>after</em> the tag that begins the map.
    541      *
    542      * @param parser The XmlPullParser from which to read the map data.
    543      * @param endTag Name of the tag that will end the map, usually "map".
    544      * @param name An array of one string, used to return the name attribute
    545      *             of the map's tag.
    546      *
    547      * @return HashMap The newly generated map.
    548      *
    549      * @see #readMapXml
    550      */
    551     public static final HashMap readThisMapXml(XmlPullParser parser, String endTag, String[] name)
    552     throws XmlPullParserException, java.io.IOException
    553     {
    554         HashMap map = new HashMap();
    555 
    556         int eventType = parser.getEventType();
    557         do {
    558             if (eventType == parser.START_TAG) {
    559                 Object val = readThisValueXml(parser, name);
    560                 if (name[0] != null) {
    561                     //System.out.println("Adding to map: " + name + " -> " + val);
    562                     map.put(name[0], val);
    563                 } else {
    564                     throw new XmlPullParserException(
    565                         "Map value without name attribute: " + parser.getName());
    566                 }
    567             } else if (eventType == parser.END_TAG) {
    568                 if (parser.getName().equals(endTag)) {
    569                     return map;
    570                 }
    571                 throw new XmlPullParserException(
    572                     "Expected " + endTag + " end tag at: " + parser.getName());
    573             }
    574             eventType = parser.next();
    575         } while (eventType != parser.END_DOCUMENT);
    576 
    577         throw new XmlPullParserException(
    578             "Document ended before " + endTag + " end tag");
    579     }
    580 
    581     /**
    582      * Read an ArrayList object from an XmlPullParser.  The XML data could
    583      * previously have been generated by writeListXml().  The XmlPullParser
    584      * must be positioned <em>after</em> the tag that begins the list.
    585      *
    586      * @param parser The XmlPullParser from which to read the list data.
    587      * @param endTag Name of the tag that will end the list, usually "list".
    588      * @param name An array of one string, used to return the name attribute
    589      *             of the list's tag.
    590      *
    591      * @return HashMap The newly generated list.
    592      *
    593      * @see #readListXml
    594      */
    595     public static final ArrayList readThisListXml(XmlPullParser parser, String endTag, String[] name)
    596     throws XmlPullParserException, java.io.IOException
    597     {
    598         ArrayList list = new ArrayList();
    599 
    600         int eventType = parser.getEventType();
    601         do {
    602             if (eventType == parser.START_TAG) {
    603                 Object val = readThisValueXml(parser, name);
    604                 list.add(val);
    605                 //System.out.println("Adding to list: " + val);
    606             } else if (eventType == parser.END_TAG) {
    607                 if (parser.getName().equals(endTag)) {
    608                     return list;
    609                 }
    610                 throw new XmlPullParserException(
    611                     "Expected " + endTag + " end tag at: " + parser.getName());
    612             }
    613             eventType = parser.next();
    614         } while (eventType != parser.END_DOCUMENT);
    615 
    616         throw new XmlPullParserException(
    617             "Document ended before " + endTag + " end tag");
    618     }
    619 
    620     /**
    621      * Read a HashSet object from an XmlPullParser. The XML data could previously
    622      * have been generated by writeSetXml(). The XmlPullParser must be positioned
    623      * <em>after</em> the tag that begins the set.
    624      *
    625      * @param parser The XmlPullParser from which to read the set data.
    626      * @param endTag Name of the tag that will end the set, usually "set".
    627      * @param name An array of one string, used to return the name attribute
    628      *             of the set's tag.
    629      *
    630      * @return HashSet The newly generated set.
    631      *
    632      * @throws XmlPullParserException
    633      * @throws java.io.IOException
    634      *
    635      * @see #readSetXml
    636      */
    637     public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name)
    638             throws XmlPullParserException, java.io.IOException {
    639         HashSet set = new HashSet();
    640 
    641         int eventType = parser.getEventType();
    642         do {
    643             if (eventType == parser.START_TAG) {
    644                 Object val = readThisValueXml(parser, name);
    645                 set.add(val);
    646                 //System.out.println("Adding to set: " + val);
    647             } else if (eventType == parser.END_TAG) {
    648                 if (parser.getName().equals(endTag)) {
    649                     return set;
    650                 }
    651                 throw new XmlPullParserException(
    652                         "Expected " + endTag + " end tag at: " + parser.getName());
    653             }
    654             eventType = parser.next();
    655         } while (eventType != parser.END_DOCUMENT);
    656 
    657         throw new XmlPullParserException(
    658                 "Document ended before " + endTag + " end tag");
    659     }
    660 
    661     /**
    662      * Read an int[] object from an XmlPullParser.  The XML data could
    663      * previously have been generated by writeIntArrayXml().  The XmlPullParser
    664      * must be positioned <em>after</em> the tag that begins the list.
    665      *
    666      * @param parser The XmlPullParser from which to read the list data.
    667      * @param endTag Name of the tag that will end the list, usually "list".
    668      * @param name An array of one string, used to return the name attribute
    669      *             of the list's tag.
    670      *
    671      * @return Returns a newly generated int[].
    672      *
    673      * @see #readListXml
    674      */
    675     public static final int[] readThisIntArrayXml(XmlPullParser parser,
    676             String endTag, String[] name)
    677             throws XmlPullParserException, java.io.IOException {
    678 
    679         int num;
    680         try {
    681             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
    682         } catch (NullPointerException e) {
    683             throw new XmlPullParserException(
    684                     "Need num attribute in byte-array");
    685         } catch (NumberFormatException e) {
    686             throw new XmlPullParserException(
    687                     "Not a number in num attribute in byte-array");
    688         }
    689 
    690         int[] array = new int[num];
    691         int i = 0;
    692 
    693         int eventType = parser.getEventType();
    694         do {
    695             if (eventType == parser.START_TAG) {
    696                 if (parser.getName().equals("item")) {
    697                     try {
    698                         array[i] = Integer.parseInt(
    699                                 parser.getAttributeValue(null, "value"));
    700                     } catch (NullPointerException e) {
    701                         throw new XmlPullParserException(
    702                                 "Need value attribute in item");
    703                     } catch (NumberFormatException e) {
    704                         throw new XmlPullParserException(
    705                                 "Not a number in value attribute in item");
    706                     }
    707                 } else {
    708                     throw new XmlPullParserException(
    709                             "Expected item tag at: " + parser.getName());
    710                 }
    711             } else if (eventType == parser.END_TAG) {
    712                 if (parser.getName().equals(endTag)) {
    713                     return array;
    714                 } else if (parser.getName().equals("item")) {
    715                     i++;
    716                 } else {
    717                     throw new XmlPullParserException(
    718                         "Expected " + endTag + " end tag at: "
    719                         + parser.getName());
    720                 }
    721             }
    722             eventType = parser.next();
    723         } while (eventType != parser.END_DOCUMENT);
    724 
    725         throw new XmlPullParserException(
    726             "Document ended before " + endTag + " end tag");
    727     }
    728 
    729     /**
    730      * Read a flattened object from an XmlPullParser.  The XML data could
    731      * previously have been written with writeMapXml(), writeListXml(), or
    732      * writeValueXml().  The XmlPullParser must be positioned <em>at</em> the
    733      * tag that defines the value.
    734      *
    735      * @param parser The XmlPullParser from which to read the object.
    736      * @param name An array of one string, used to return the name attribute
    737      *             of the value's tag.
    738      *
    739      * @return Object The newly generated value object.
    740      *
    741      * @see #readMapXml
    742      * @see #readListXml
    743      * @see #writeValueXml
    744      */
    745     public static final Object readValueXml(XmlPullParser parser, String[] name)
    746     throws XmlPullParserException, java.io.IOException
    747     {
    748         int eventType = parser.getEventType();
    749         do {
    750             if (eventType == parser.START_TAG) {
    751                 return readThisValueXml(parser, name);
    752             } else if (eventType == parser.END_TAG) {
    753                 throw new XmlPullParserException(
    754                     "Unexpected end tag at: " + parser.getName());
    755             } else if (eventType == parser.TEXT) {
    756                 throw new XmlPullParserException(
    757                     "Unexpected text: " + parser.getText());
    758             }
    759             eventType = parser.next();
    760         } while (eventType != parser.END_DOCUMENT);
    761 
    762         throw new XmlPullParserException(
    763             "Unexpected end of document");
    764     }
    765 
    766     private static final Object readThisValueXml(XmlPullParser parser, String[] name)
    767     throws XmlPullParserException, java.io.IOException
    768     {
    769         final String valueName = parser.getAttributeValue(null, "name");
    770         final String tagName = parser.getName();
    771 
    772         //System.out.println("Reading this value tag: " + tagName + ", name=" + valueName);
    773 
    774         Object res;
    775 
    776         if (tagName.equals("null")) {
    777             res = null;
    778         } else if (tagName.equals("string")) {
    779             String value = "";
    780             int eventType;
    781             while ((eventType = parser.next()) != parser.END_DOCUMENT) {
    782                 if (eventType == parser.END_TAG) {
    783                     if (parser.getName().equals("string")) {
    784                         name[0] = valueName;
    785                         //System.out.println("Returning value for " + valueName + ": " + value);
    786                         return value;
    787                     }
    788                     throw new XmlPullParserException(
    789                         "Unexpected end tag in <string>: " + parser.getName());
    790                 } else if (eventType == parser.TEXT) {
    791                     value += parser.getText();
    792                 } else if (eventType == parser.START_TAG) {
    793                     throw new XmlPullParserException(
    794                         "Unexpected start tag in <string>: " + parser.getName());
    795                 }
    796             }
    797             throw new XmlPullParserException(
    798                 "Unexpected end of document in <string>");
    799         } else if ((res = readThisPrimitiveValueXml(parser, tagName)) != null) {
    800             // all work already done by readThisPrimitiveValueXml
    801         } else if (tagName.equals("int-array")) {
    802             parser.next();
    803             res = readThisIntArrayXml(parser, "int-array", name);
    804             name[0] = valueName;
    805             //System.out.println("Returning value for " + valueName + ": " + res);
    806             return res;
    807         } else if (tagName.equals("map")) {
    808             parser.next();
    809             res = readThisMapXml(parser, "map", name);
    810             name[0] = valueName;
    811             //System.out.println("Returning value for " + valueName + ": " + res);
    812             return res;
    813         } else if (tagName.equals("list")) {
    814             parser.next();
    815             res = readThisListXml(parser, "list", name);
    816             name[0] = valueName;
    817             //System.out.println("Returning value for " + valueName + ": " + res);
    818             return res;
    819         } else if (tagName.equals("set")) {
    820             parser.next();
    821             res = readThisSetXml(parser, "set", name);
    822             name[0] = valueName;
    823             //System.out.println("Returning value for " + valueName + ": " + res);
    824             return res;
    825         } else {
    826             throw new XmlPullParserException(
    827                 "Unknown tag: " + tagName);
    828         }
    829 
    830         // Skip through to end tag.
    831         int eventType;
    832         while ((eventType = parser.next()) != parser.END_DOCUMENT) {
    833             if (eventType == parser.END_TAG) {
    834                 if (parser.getName().equals(tagName)) {
    835                     name[0] = valueName;
    836                     //System.out.println("Returning value for " + valueName + ": " + res);
    837                     return res;
    838                 }
    839                 throw new XmlPullParserException(
    840                     "Unexpected end tag in <" + tagName + ">: " + parser.getName());
    841             } else if (eventType == parser.TEXT) {
    842                 throw new XmlPullParserException(
    843                 "Unexpected text in <" + tagName + ">: " + parser.getName());
    844             } else if (eventType == parser.START_TAG) {
    845                 throw new XmlPullParserException(
    846                     "Unexpected start tag in <" + tagName + ">: " + parser.getName());
    847             }
    848         }
    849         throw new XmlPullParserException(
    850             "Unexpected end of document in <" + tagName + ">");
    851     }
    852 
    853     private static final Object readThisPrimitiveValueXml(XmlPullParser parser, String tagName)
    854     throws XmlPullParserException, java.io.IOException
    855     {
    856         try {
    857             if (tagName.equals("int")) {
    858                 return Integer.parseInt(parser.getAttributeValue(null, "value"));
    859             } else if (tagName.equals("long")) {
    860                 return Long.valueOf(parser.getAttributeValue(null, "value"));
    861             } else if (tagName.equals("float")) {
    862                 return new Float(parser.getAttributeValue(null, "value"));
    863             } else if (tagName.equals("double")) {
    864                 return new Double(parser.getAttributeValue(null, "value"));
    865             } else if (tagName.equals("boolean")) {
    866                 return Boolean.valueOf(parser.getAttributeValue(null, "value"));
    867             } else {
    868                 return null;
    869             }
    870         } catch (NullPointerException e) {
    871             throw new XmlPullParserException("Need value attribute in <" + tagName + ">");
    872         } catch (NumberFormatException e) {
    873             throw new XmlPullParserException(
    874                     "Not a number in value attribute in <" + tagName + ">");
    875         }
    876     }
    877 
    878     public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException
    879     {
    880         int type;
    881         while ((type=parser.next()) != parser.START_TAG
    882                    && type != parser.END_DOCUMENT) {
    883             ;
    884         }
    885 
    886         if (type != parser.START_TAG) {
    887             throw new XmlPullParserException("No start tag found");
    888         }
    889 
    890         if (!parser.getName().equals(firstElementName)) {
    891             throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
    892                     ", expected " + firstElementName);
    893         }
    894     }
    895 
    896     public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException
    897     {
    898         int type;
    899         while ((type=parser.next()) != parser.START_TAG
    900                    && type != parser.END_DOCUMENT) {
    901             ;
    902         }
    903     }
    904 
    905     public static boolean nextElementWithin(XmlPullParser parser, int outerDepth)
    906             throws IOException, XmlPullParserException {
    907         for (;;) {
    908             int type = parser.next();
    909             if (type == XmlPullParser.END_DOCUMENT
    910                     || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) {
    911                 return false;
    912             }
    913             if (type == XmlPullParser.START_TAG
    914                     && parser.getDepth() == outerDepth + 1) {
    915                 return true;
    916             }
    917         }
    918     }
    919 
    920     public static int readIntAttribute(XmlPullParser in, String name) throws IOException {
    921         final String value = in.getAttributeValue(null, name);
    922         try {
    923             return Integer.parseInt(value);
    924         } catch (NumberFormatException e) {
    925             throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
    926         }
    927     }
    928 
    929     public static void writeIntAttribute(XmlSerializer out, String name, int value)
    930             throws IOException {
    931         out.attribute(null, name, Integer.toString(value));
    932     }
    933 
    934     public static long readLongAttribute(XmlPullParser in, String name, long defaultValue) {
    935         final String value = in.getAttributeValue(null, name);
    936         try {
    937             return Long.parseLong(value);
    938         } catch (NumberFormatException e) {
    939             return defaultValue;
    940         }
    941     }
    942 
    943     public static long readLongAttribute(XmlPullParser in, String name) throws IOException {
    944         final String value = in.getAttributeValue(null, name);
    945         try {
    946             return Long.parseLong(value);
    947         } catch (NumberFormatException e) {
    948             throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
    949         }
    950     }
    951 
    952     public static void writeLongAttribute(XmlSerializer out, String name, long value)
    953             throws IOException {
    954         out.attribute(null, name, Long.toString(value));
    955     }
    956 
    957     public static boolean readBooleanAttribute(XmlPullParser in, String name) {
    958         final String value = in.getAttributeValue(null, name);
    959         return Boolean.parseBoolean(value);
    960     }
    961 
    962     public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
    963             throws IOException {
    964         out.attribute(null, name, Boolean.toString(value));
    965     }
    966 }
    967