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.graphics.Bitmap;
     20 import android.graphics.BitmapFactory;
     21 import android.graphics.Bitmap.CompressFormat;
     22 import android.net.Uri;
     23 import android.util.Base64;
     24 import android.util.Xml;
     25 
     26 import org.xmlpull.v1.XmlPullParser;
     27 import org.xmlpull.v1.XmlPullParserException;
     28 import org.xmlpull.v1.XmlSerializer;
     29 
     30 import java.io.ByteArrayOutputStream;
     31 import java.io.IOException;
     32 import java.io.InputStream;
     33 import java.io.OutputStream;
     34 import java.net.ProtocolException;
     35 import java.util.ArrayList;
     36 import java.util.HashMap;
     37 import java.util.HashSet;
     38 import java.util.Iterator;
     39 import java.util.List;
     40 import java.util.Map;
     41 import java.util.Set;
     42 
     43 /** {@hide} */
     44 public class XmlUtils {
     45 
     46     public static void skipCurrentTag(XmlPullParser parser)
     47             throws XmlPullParserException, IOException {
     48         int outerDepth = parser.getDepth();
     49         int type;
     50         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
     51                && (type != XmlPullParser.END_TAG
     52                        || parser.getDepth() > outerDepth)) {
     53         }
     54     }
     55 
     56     public static final int
     57     convertValueToList(CharSequence value, String[] options, int defaultValue)
     58     {
     59         if (null != value) {
     60             for (int i = 0; i < options.length; i++) {
     61                 if (value.equals(options[i]))
     62                     return i;
     63             }
     64         }
     65 
     66         return defaultValue;
     67     }
     68 
     69     public static final boolean
     70     convertValueToBoolean(CharSequence value, boolean defaultValue)
     71     {
     72         boolean result = false;
     73 
     74         if (null == value)
     75             return defaultValue;
     76 
     77         if (value.equals("1")
     78         ||  value.equals("true")
     79         ||  value.equals("TRUE"))
     80             result = true;
     81 
     82         return result;
     83     }
     84 
     85     public static final int
     86     convertValueToInt(CharSequence charSeq, int defaultValue)
     87     {
     88         if (null == charSeq)
     89             return defaultValue;
     90 
     91         String nm = charSeq.toString();
     92 
     93         // XXX This code is copied from Integer.decode() so we don't
     94         // have to instantiate an Integer!
     95 
     96         int value;
     97         int sign = 1;
     98         int index = 0;
     99         int len = nm.length();
    100         int base = 10;
    101 
    102         if ('-' == nm.charAt(0)) {
    103             sign = -1;
    104             index++;
    105         }
    106 
    107         if ('0' == nm.charAt(index)) {
    108             //  Quick check for a zero by itself
    109             if (index == (len - 1))
    110                 return 0;
    111 
    112             char    c = nm.charAt(index + 1);
    113 
    114             if ('x' == c || 'X' == c) {
    115                 index += 2;
    116                 base = 16;
    117             } else {
    118                 index++;
    119                 base = 8;
    120             }
    121         }
    122         else if ('#' == nm.charAt(index))
    123         {
    124             index++;
    125             base = 16;
    126         }
    127 
    128         return Integer.parseInt(nm.substring(index), base) * sign;
    129     }
    130 
    131     public static int convertValueToUnsignedInt(String value, int defaultValue) {
    132         if (null == value) {
    133             return defaultValue;
    134         }
    135 
    136         return parseUnsignedIntAttribute(value);
    137     }
    138 
    139     public static int parseUnsignedIntAttribute(CharSequence charSeq) {
    140         String  value = charSeq.toString();
    141 
    142         long    bits;
    143         int     index = 0;
    144         int     len = value.length();
    145         int     base = 10;
    146 
    147         if ('0' == value.charAt(index)) {
    148             //  Quick check for zero by itself
    149             if (index == (len - 1))
    150                 return 0;
    151 
    152             char    c = value.charAt(index + 1);
    153 
    154             if ('x' == c || 'X' == c) {     //  check for hex
    155                 index += 2;
    156                 base = 16;
    157             } else {                        //  check for octal
    158                 index++;
    159                 base = 8;
    160             }
    161         } else if ('#' == value.charAt(index)) {
    162             index++;
    163             base = 16;
    164         }
    165 
    166         return (int) Long.parseLong(value.substring(index), base);
    167     }
    168 
    169     /**
    170      * Flatten a Map into an output stream as XML.  The map can later be
    171      * read back with readMapXml().
    172      *
    173      * @param val The map to be flattened.
    174      * @param out Where to write the XML data.
    175      *
    176      * @see #writeMapXml(Map, String, XmlSerializer)
    177      * @see #writeListXml
    178      * @see #writeValueXml
    179      * @see #readMapXml
    180      */
    181     public static final void writeMapXml(Map val, OutputStream out)
    182             throws XmlPullParserException, java.io.IOException {
    183         XmlSerializer serializer = new FastXmlSerializer();
    184         serializer.setOutput(out, "utf-8");
    185         serializer.startDocument(null, true);
    186         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
    187         writeMapXml(val, null, serializer);
    188         serializer.endDocument();
    189     }
    190 
    191     /**
    192      * Flatten a List into an output stream as XML.  The list can later be
    193      * read back with readListXml().
    194      *
    195      * @param val The list to be flattened.
    196      * @param out Where to write the XML data.
    197      *
    198      * @see #writeListXml(List, String, XmlSerializer)
    199      * @see #writeMapXml
    200      * @see #writeValueXml
    201      * @see #readListXml
    202      */
    203     public static final void writeListXml(List val, OutputStream out)
    204     throws XmlPullParserException, java.io.IOException
    205     {
    206         XmlSerializer serializer = Xml.newSerializer();
    207         serializer.setOutput(out, "utf-8");
    208         serializer.startDocument(null, true);
    209         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
    210         writeListXml(val, null, serializer);
    211         serializer.endDocument();
    212     }
    213 
    214     /**
    215      * Flatten a Map into an XmlSerializer.  The map can later be read back
    216      * with readThisMapXml().
    217      *
    218      * @param val The map to be flattened.
    219      * @param name Name attribute to include with this list's tag, or null for
    220      *             none.
    221      * @param out XmlSerializer to write the map into.
    222      *
    223      * @see #writeMapXml(Map, OutputStream)
    224      * @see #writeListXml
    225      * @see #writeValueXml
    226      * @see #readMapXml
    227      */
    228     public static final void writeMapXml(Map val, String name, XmlSerializer out)
    229             throws XmlPullParserException, java.io.IOException {
    230         writeMapXml(val, name, out, null);
    231     }
    232 
    233     /**
    234      * Flatten a Map into an XmlSerializer.  The map can later be read back
    235      * with readThisMapXml().
    236      *
    237      * @param val The map to be flattened.
    238      * @param name Name attribute to include with this list's tag, or null for
    239      *             none.
    240      * @param out XmlSerializer to write the map into.
    241      * @param callback Method to call when an Object type is not recognized.
    242      *
    243      * @see #writeMapXml(Map, OutputStream)
    244      * @see #writeListXml
    245      * @see #writeValueXml
    246      * @see #readMapXml
    247      *
    248      * @hide
    249      */
    250     public static final void writeMapXml(Map val, String name, XmlSerializer out,
    251             WriteMapCallback callback) throws XmlPullParserException, java.io.IOException {
    252 
    253         if (val == null) {
    254             out.startTag(null, "null");
    255             out.endTag(null, "null");
    256             return;
    257         }
    258 
    259         out.startTag(null, "map");
    260         if (name != null) {
    261             out.attribute(null, "name", name);
    262         }
    263 
    264         writeMapXml(val, out, callback);
    265 
    266         out.endTag(null, "map");
    267     }
    268 
    269     /**
    270      * Flatten a Map into an XmlSerializer.  The map can later be read back
    271      * with readThisMapXml(). This method presumes that the start tag and
    272      * name attribute have already been written and does not write an end tag.
    273      *
    274      * @param val The map to be flattened.
    275      * @param out XmlSerializer to write the map into.
    276      *
    277      * @see #writeMapXml(Map, OutputStream)
    278      * @see #writeListXml
    279      * @see #writeValueXml
    280      * @see #readMapXml
    281      *
    282      * @hide
    283      */
    284     public static final void writeMapXml(Map val, XmlSerializer out,
    285             WriteMapCallback callback) throws XmlPullParserException, java.io.IOException {
    286         if (val == null) {
    287             return;
    288         }
    289 
    290         Set s = val.entrySet();
    291         Iterator i = s.iterator();
    292 
    293         while (i.hasNext()) {
    294             Map.Entry e = (Map.Entry)i.next();
    295             writeValueXml(e.getValue(), (String)e.getKey(), out, callback);
    296         }
    297     }
    298 
    299     /**
    300      * Flatten a List into an XmlSerializer.  The list can later be read back
    301      * with readThisListXml().
    302      *
    303      * @param val The list to be flattened.
    304      * @param name Name attribute to include with this list's tag, or null for
    305      *             none.
    306      * @param out XmlSerializer to write the list into.
    307      *
    308      * @see #writeListXml(List, OutputStream)
    309      * @see #writeMapXml
    310      * @see #writeValueXml
    311      * @see #readListXml
    312      */
    313     public static final void writeListXml(List val, String name, XmlSerializer out)
    314     throws XmlPullParserException, java.io.IOException
    315     {
    316         if (val == null) {
    317             out.startTag(null, "null");
    318             out.endTag(null, "null");
    319             return;
    320         }
    321 
    322         out.startTag(null, "list");
    323         if (name != null) {
    324             out.attribute(null, "name", name);
    325         }
    326 
    327         int N = val.size();
    328         int i=0;
    329         while (i < N) {
    330             writeValueXml(val.get(i), null, out);
    331             i++;
    332         }
    333 
    334         out.endTag(null, "list");
    335     }
    336 
    337     public static final void writeSetXml(Set val, String name, XmlSerializer out)
    338             throws XmlPullParserException, java.io.IOException {
    339         if (val == null) {
    340             out.startTag(null, "null");
    341             out.endTag(null, "null");
    342             return;
    343         }
    344 
    345         out.startTag(null, "set");
    346         if (name != null) {
    347             out.attribute(null, "name", name);
    348         }
    349 
    350         for (Object v : val) {
    351             writeValueXml(v, null, out);
    352         }
    353 
    354         out.endTag(null, "set");
    355     }
    356 
    357     /**
    358      * Flatten a byte[] into an XmlSerializer.  The list can later be read back
    359      * with readThisByteArrayXml().
    360      *
    361      * @param val The byte array to be flattened.
    362      * @param name Name attribute to include with this array's tag, or null for
    363      *             none.
    364      * @param out XmlSerializer to write the array into.
    365      *
    366      * @see #writeMapXml
    367      * @see #writeValueXml
    368      */
    369     public static final void writeByteArrayXml(byte[] val, String name,
    370             XmlSerializer out)
    371             throws XmlPullParserException, java.io.IOException {
    372 
    373         if (val == null) {
    374             out.startTag(null, "null");
    375             out.endTag(null, "null");
    376             return;
    377         }
    378 
    379         out.startTag(null, "byte-array");
    380         if (name != null) {
    381             out.attribute(null, "name", name);
    382         }
    383 
    384         final int N = val.length;
    385         out.attribute(null, "num", Integer.toString(N));
    386 
    387         StringBuilder sb = new StringBuilder(val.length*2);
    388         for (int i=0; i<N; i++) {
    389             int b = val[i];
    390             int h = b>>4;
    391             sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
    392             h = b&0xff;
    393             sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
    394         }
    395 
    396         out.text(sb.toString());
    397 
    398         out.endTag(null, "byte-array");
    399     }
    400 
    401     /**
    402      * Flatten an int[] into an XmlSerializer.  The list can later be read back
    403      * with readThisIntArrayXml().
    404      *
    405      * @param val The int array to be flattened.
    406      * @param name Name attribute to include with this array's tag, or null for
    407      *             none.
    408      * @param out XmlSerializer to write the array into.
    409      *
    410      * @see #writeMapXml
    411      * @see #writeValueXml
    412      * @see #readThisIntArrayXml
    413      */
    414     public static final void writeIntArrayXml(int[] val, String name,
    415             XmlSerializer out)
    416             throws XmlPullParserException, java.io.IOException {
    417 
    418         if (val == null) {
    419             out.startTag(null, "null");
    420             out.endTag(null, "null");
    421             return;
    422         }
    423 
    424         out.startTag(null, "int-array");
    425         if (name != null) {
    426             out.attribute(null, "name", name);
    427         }
    428 
    429         final int N = val.length;
    430         out.attribute(null, "num", Integer.toString(N));
    431 
    432         for (int i=0; i<N; i++) {
    433             out.startTag(null, "item");
    434             out.attribute(null, "value", Integer.toString(val[i]));
    435             out.endTag(null, "item");
    436         }
    437 
    438         out.endTag(null, "int-array");
    439     }
    440 
    441     /**
    442      * Flatten a long[] into an XmlSerializer.  The list can later be read back
    443      * with readThisLongArrayXml().
    444      *
    445      * @param val The long array to be flattened.
    446      * @param name Name attribute to include with this array's tag, or null for
    447      *             none.
    448      * @param out XmlSerializer to write the array into.
    449      *
    450      * @see #writeMapXml
    451      * @see #writeValueXml
    452      * @see #readThisIntArrayXml
    453      */
    454     public static final void writeLongArrayXml(long[] val, String name, XmlSerializer out)
    455             throws XmlPullParserException, java.io.IOException {
    456 
    457         if (val == null) {
    458             out.startTag(null, "null");
    459             out.endTag(null, "null");
    460             return;
    461         }
    462 
    463         out.startTag(null, "long-array");
    464         if (name != null) {
    465             out.attribute(null, "name", name);
    466         }
    467 
    468         final int N = val.length;
    469         out.attribute(null, "num", Integer.toString(N));
    470 
    471         for (int i=0; i<N; i++) {
    472             out.startTag(null, "item");
    473             out.attribute(null, "value", Long.toString(val[i]));
    474             out.endTag(null, "item");
    475         }
    476 
    477         out.endTag(null, "long-array");
    478     }
    479 
    480     /**
    481      * Flatten a double[] into an XmlSerializer.  The list can later be read back
    482      * with readThisDoubleArrayXml().
    483      *
    484      * @param val The double array to be flattened.
    485      * @param name Name attribute to include with this array's tag, or null for
    486      *             none.
    487      * @param out XmlSerializer to write the array into.
    488      *
    489      * @see #writeMapXml
    490      * @see #writeValueXml
    491      * @see #readThisIntArrayXml
    492      */
    493     public static final void writeDoubleArrayXml(double[] val, String name, XmlSerializer out)
    494             throws XmlPullParserException, java.io.IOException {
    495 
    496         if (val == null) {
    497             out.startTag(null, "null");
    498             out.endTag(null, "null");
    499             return;
    500         }
    501 
    502         out.startTag(null, "double-array");
    503         if (name != null) {
    504             out.attribute(null, "name", name);
    505         }
    506 
    507         final int N = val.length;
    508         out.attribute(null, "num", Integer.toString(N));
    509 
    510         for (int i=0; i<N; i++) {
    511             out.startTag(null, "item");
    512             out.attribute(null, "value", Double.toString(val[i]));
    513             out.endTag(null, "item");
    514         }
    515 
    516         out.endTag(null, "double-array");
    517     }
    518 
    519     /**
    520      * Flatten a String[] into an XmlSerializer.  The list can later be read back
    521      * with readThisStringArrayXml().
    522      *
    523      * @param val The long array to be flattened.
    524      * @param name Name attribute to include with this array's tag, or null for
    525      *             none.
    526      * @param out XmlSerializer to write the array into.
    527      *
    528      * @see #writeMapXml
    529      * @see #writeValueXml
    530      * @see #readThisIntArrayXml
    531      */
    532     public static final void writeStringArrayXml(String[] val, String name, XmlSerializer out)
    533             throws XmlPullParserException, java.io.IOException {
    534 
    535         if (val == null) {
    536             out.startTag(null, "null");
    537             out.endTag(null, "null");
    538             return;
    539         }
    540 
    541         out.startTag(null, "string-array");
    542         if (name != null) {
    543             out.attribute(null, "name", name);
    544         }
    545 
    546         final int N = val.length;
    547         out.attribute(null, "num", Integer.toString(N));
    548 
    549         for (int i=0; i<N; i++) {
    550             out.startTag(null, "item");
    551             out.attribute(null, "value", val[i]);
    552             out.endTag(null, "item");
    553         }
    554 
    555         out.endTag(null, "string-array");
    556     }
    557 
    558     /**
    559      * Flatten an object's value into an XmlSerializer.  The value can later
    560      * be read back with readThisValueXml().
    561      *
    562      * Currently supported value types are: null, String, Integer, Long,
    563      * Float, Double Boolean, Map, List.
    564      *
    565      * @param v The object to be flattened.
    566      * @param name Name attribute to include with this value's tag, or null
    567      *             for none.
    568      * @param out XmlSerializer to write the object into.
    569      *
    570      * @see #writeMapXml
    571      * @see #writeListXml
    572      * @see #readValueXml
    573      */
    574     public static final void writeValueXml(Object v, String name, XmlSerializer out)
    575             throws XmlPullParserException, java.io.IOException {
    576         writeValueXml(v, name, out, null);
    577     }
    578 
    579     /**
    580      * Flatten an object's value into an XmlSerializer.  The value can later
    581      * be read back with readThisValueXml().
    582      *
    583      * Currently supported value types are: null, String, Integer, Long,
    584      * Float, Double Boolean, Map, List.
    585      *
    586      * @param v The object to be flattened.
    587      * @param name Name attribute to include with this value's tag, or null
    588      *             for none.
    589      * @param out XmlSerializer to write the object into.
    590      * @param callback Handler for Object types not recognized.
    591      *
    592      * @see #writeMapXml
    593      * @see #writeListXml
    594      * @see #readValueXml
    595      */
    596     private static final void writeValueXml(Object v, String name, XmlSerializer out,
    597             WriteMapCallback callback)  throws XmlPullParserException, java.io.IOException {
    598         String typeStr;
    599         if (v == null) {
    600             out.startTag(null, "null");
    601             if (name != null) {
    602                 out.attribute(null, "name", name);
    603             }
    604             out.endTag(null, "null");
    605             return;
    606         } else if (v instanceof String) {
    607             out.startTag(null, "string");
    608             if (name != null) {
    609                 out.attribute(null, "name", name);
    610             }
    611             out.text(v.toString());
    612             out.endTag(null, "string");
    613             return;
    614         } else if (v instanceof Integer) {
    615             typeStr = "int";
    616         } else if (v instanceof Long) {
    617             typeStr = "long";
    618         } else if (v instanceof Float) {
    619             typeStr = "float";
    620         } else if (v instanceof Double) {
    621             typeStr = "double";
    622         } else if (v instanceof Boolean) {
    623             typeStr = "boolean";
    624         } else if (v instanceof byte[]) {
    625             writeByteArrayXml((byte[])v, name, out);
    626             return;
    627         } else if (v instanceof int[]) {
    628             writeIntArrayXml((int[])v, name, out);
    629             return;
    630         } else if (v instanceof long[]) {
    631             writeLongArrayXml((long[])v, name, out);
    632             return;
    633         } else if (v instanceof double[]) {
    634             writeDoubleArrayXml((double[])v, name, out);
    635             return;
    636         } else if (v instanceof String[]) {
    637             writeStringArrayXml((String[])v, name, out);
    638             return;
    639         } else if (v instanceof Map) {
    640             writeMapXml((Map)v, name, out);
    641             return;
    642         } else if (v instanceof List) {
    643             writeListXml((List) v, name, out);
    644             return;
    645         } else if (v instanceof Set) {
    646             writeSetXml((Set) v, name, out);
    647             return;
    648         } else if (v instanceof CharSequence) {
    649             // XXX This is to allow us to at least write something if
    650             // we encounter styled text...  but it means we will drop all
    651             // of the styling information. :(
    652             out.startTag(null, "string");
    653             if (name != null) {
    654                 out.attribute(null, "name", name);
    655             }
    656             out.text(v.toString());
    657             out.endTag(null, "string");
    658             return;
    659         } else if (callback != null) {
    660             callback.writeUnknownObject(v, name, out);
    661             return;
    662         } else {
    663             throw new RuntimeException("writeValueXml: unable to write value " + v);
    664         }
    665 
    666         out.startTag(null, typeStr);
    667         if (name != null) {
    668             out.attribute(null, "name", name);
    669         }
    670         out.attribute(null, "value", v.toString());
    671         out.endTag(null, typeStr);
    672     }
    673 
    674     /**
    675      * Read a HashMap from an InputStream containing XML.  The stream can
    676      * previously have been written by writeMapXml().
    677      *
    678      * @param in The InputStream from which to read.
    679      *
    680      * @return HashMap The resulting map.
    681      *
    682      * @see #readListXml
    683      * @see #readValueXml
    684      * @see #readThisMapXml
    685      * #see #writeMapXml
    686      */
    687     @SuppressWarnings("unchecked")
    688     public static final HashMap<String, ?> readMapXml(InputStream in)
    689     throws XmlPullParserException, java.io.IOException
    690     {
    691         XmlPullParser   parser = Xml.newPullParser();
    692         parser.setInput(in, null);
    693         return (HashMap<String, ?>) readValueXml(parser, new String[1]);
    694     }
    695 
    696     /**
    697      * Read an ArrayList from an InputStream containing XML.  The stream can
    698      * previously have been written by writeListXml().
    699      *
    700      * @param in The InputStream from which to read.
    701      *
    702      * @return ArrayList The resulting list.
    703      *
    704      * @see #readMapXml
    705      * @see #readValueXml
    706      * @see #readThisListXml
    707      * @see #writeListXml
    708      */
    709     public static final ArrayList readListXml(InputStream in)
    710     throws XmlPullParserException, java.io.IOException
    711     {
    712         XmlPullParser   parser = Xml.newPullParser();
    713         parser.setInput(in, null);
    714         return (ArrayList)readValueXml(parser, new String[1]);
    715     }
    716 
    717 
    718     /**
    719      * Read a HashSet from an InputStream containing XML. The stream can
    720      * previously have been written by writeSetXml().
    721      *
    722      * @param in The InputStream from which to read.
    723      *
    724      * @return HashSet The resulting set.
    725      *
    726      * @throws XmlPullParserException
    727      * @throws java.io.IOException
    728      *
    729      * @see #readValueXml
    730      * @see #readThisSetXml
    731      * @see #writeSetXml
    732      */
    733     public static final HashSet readSetXml(InputStream in)
    734             throws XmlPullParserException, java.io.IOException {
    735         XmlPullParser parser = Xml.newPullParser();
    736         parser.setInput(in, null);
    737         return (HashSet) readValueXml(parser, new String[1]);
    738     }
    739 
    740     /**
    741      * Read a HashMap object from an XmlPullParser.  The XML data could
    742      * previously have been generated by writeMapXml().  The XmlPullParser
    743      * must be positioned <em>after</em> the tag that begins the map.
    744      *
    745      * @param parser The XmlPullParser from which to read the map data.
    746      * @param endTag Name of the tag that will end the map, usually "map".
    747      * @param name An array of one string, used to return the name attribute
    748      *             of the map's tag.
    749      *
    750      * @return HashMap The newly generated map.
    751      *
    752      * @see #readMapXml
    753      */
    754     public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag,
    755             String[] name) throws XmlPullParserException, java.io.IOException {
    756         return readThisMapXml(parser, endTag, name, null);
    757     }
    758 
    759     /**
    760      * Read a HashMap object from an XmlPullParser.  The XML data could
    761      * previously have been generated by writeMapXml().  The XmlPullParser
    762      * must be positioned <em>after</em> the tag that begins the map.
    763      *
    764      * @param parser The XmlPullParser from which to read the map data.
    765      * @param endTag Name of the tag that will end the map, usually "map".
    766      * @param name An array of one string, used to return the name attribute
    767      *             of the map's tag.
    768      *
    769      * @return HashMap The newly generated map.
    770      *
    771      * @see #readMapXml
    772      * @hide
    773      */
    774     public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag,
    775             String[] name, ReadMapCallback callback)
    776             throws XmlPullParserException, java.io.IOException
    777     {
    778         HashMap<String, Object> map = new HashMap<String, Object>();
    779 
    780         int eventType = parser.getEventType();
    781         do {
    782             if (eventType == parser.START_TAG) {
    783                 Object val = readThisValueXml(parser, name, callback);
    784                 map.put(name[0], val);
    785             } else if (eventType == parser.END_TAG) {
    786                 if (parser.getName().equals(endTag)) {
    787                     return map;
    788                 }
    789                 throw new XmlPullParserException(
    790                     "Expected " + endTag + " end tag at: " + parser.getName());
    791             }
    792             eventType = parser.next();
    793         } while (eventType != parser.END_DOCUMENT);
    794 
    795         throw new XmlPullParserException(
    796             "Document ended before " + endTag + " end tag");
    797     }
    798 
    799     /**
    800      * Read an ArrayList object from an XmlPullParser.  The XML data could
    801      * previously have been generated by writeListXml().  The XmlPullParser
    802      * must be positioned <em>after</em> the tag that begins the list.
    803      *
    804      * @param parser The XmlPullParser from which to read the list data.
    805      * @param endTag Name of the tag that will end the list, usually "list".
    806      * @param name An array of one string, used to return the name attribute
    807      *             of the list's tag.
    808      *
    809      * @return HashMap The newly generated list.
    810      *
    811      * @see #readListXml
    812      */
    813     public static final ArrayList readThisListXml(XmlPullParser parser, String endTag,
    814             String[] name) throws XmlPullParserException, java.io.IOException {
    815         return readThisListXml(parser, endTag, name, null);
    816     }
    817 
    818     /**
    819      * Read an ArrayList object from an XmlPullParser.  The XML data could
    820      * previously have been generated by writeListXml().  The XmlPullParser
    821      * must be positioned <em>after</em> the tag that begins the list.
    822      *
    823      * @param parser The XmlPullParser from which to read the list data.
    824      * @param endTag Name of the tag that will end the list, usually "list".
    825      * @param name An array of one string, used to return the name attribute
    826      *             of the list's tag.
    827      *
    828      * @return HashMap The newly generated list.
    829      *
    830      * @see #readListXml
    831      */
    832     private static final ArrayList readThisListXml(XmlPullParser parser, String endTag,
    833             String[] name, ReadMapCallback callback)
    834             throws XmlPullParserException, java.io.IOException {
    835         ArrayList list = new ArrayList();
    836 
    837         int eventType = parser.getEventType();
    838         do {
    839             if (eventType == parser.START_TAG) {
    840                 Object val = readThisValueXml(parser, name, callback);
    841                 list.add(val);
    842                 //System.out.println("Adding to list: " + val);
    843             } else if (eventType == parser.END_TAG) {
    844                 if (parser.getName().equals(endTag)) {
    845                     return list;
    846                 }
    847                 throw new XmlPullParserException(
    848                     "Expected " + endTag + " end tag at: " + parser.getName());
    849             }
    850             eventType = parser.next();
    851         } while (eventType != parser.END_DOCUMENT);
    852 
    853         throw new XmlPullParserException(
    854             "Document ended before " + endTag + " end tag");
    855     }
    856 
    857     /**
    858      * Read a HashSet object from an XmlPullParser. The XML data could previously
    859      * have been generated by writeSetXml(). The XmlPullParser must be positioned
    860      * <em>after</em> the tag that begins the set.
    861      *
    862      * @param parser The XmlPullParser from which to read the set data.
    863      * @param endTag Name of the tag that will end the set, usually "set".
    864      * @param name An array of one string, used to return the name attribute
    865      *             of the set's tag.
    866      *
    867      * @return HashSet The newly generated set.
    868      *
    869      * @throws XmlPullParserException
    870      * @throws java.io.IOException
    871      *
    872      * @see #readSetXml
    873      */
    874     public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name)
    875             throws XmlPullParserException, java.io.IOException {
    876         return readThisSetXml(parser, endTag, name, null);
    877     }
    878 
    879     /**
    880      * Read a HashSet object from an XmlPullParser. The XML data could previously
    881      * have been generated by writeSetXml(). The XmlPullParser must be positioned
    882      * <em>after</em> the tag that begins the set.
    883      *
    884      * @param parser The XmlPullParser from which to read the set data.
    885      * @param endTag Name of the tag that will end the set, usually "set".
    886      * @param name An array of one string, used to return the name attribute
    887      *             of the set's tag.
    888      *
    889      * @return HashSet The newly generated set.
    890      *
    891      * @throws XmlPullParserException
    892      * @throws java.io.IOException
    893      *
    894      * @see #readSetXml
    895      * @hide
    896      */
    897     private static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name,
    898             ReadMapCallback callback) throws XmlPullParserException, java.io.IOException {
    899         HashSet set = new HashSet();
    900 
    901         int eventType = parser.getEventType();
    902         do {
    903             if (eventType == parser.START_TAG) {
    904                 Object val = readThisValueXml(parser, name, callback);
    905                 set.add(val);
    906                 //System.out.println("Adding to set: " + val);
    907             } else if (eventType == parser.END_TAG) {
    908                 if (parser.getName().equals(endTag)) {
    909                     return set;
    910                 }
    911                 throw new XmlPullParserException(
    912                         "Expected " + endTag + " end tag at: " + parser.getName());
    913             }
    914             eventType = parser.next();
    915         } while (eventType != parser.END_DOCUMENT);
    916 
    917         throw new XmlPullParserException(
    918                 "Document ended before " + endTag + " end tag");
    919     }
    920 
    921     /**
    922      * Read an int[] object from an XmlPullParser.  The XML data could
    923      * previously have been generated by writeIntArrayXml().  The XmlPullParser
    924      * must be positioned <em>after</em> the tag that begins the list.
    925      *
    926      * @param parser The XmlPullParser from which to read the list data.
    927      * @param endTag Name of the tag that will end the list, usually "list".
    928      * @param name An array of one string, used to return the name attribute
    929      *             of the list's tag.
    930      *
    931      * @return Returns a newly generated int[].
    932      *
    933      * @see #readListXml
    934      */
    935     public static final int[] readThisIntArrayXml(XmlPullParser parser,
    936             String endTag, String[] name)
    937             throws XmlPullParserException, java.io.IOException {
    938 
    939         int num;
    940         try {
    941             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
    942         } catch (NullPointerException e) {
    943             throw new XmlPullParserException(
    944                     "Need num attribute in byte-array");
    945         } catch (NumberFormatException e) {
    946             throw new XmlPullParserException(
    947                     "Not a number in num attribute in byte-array");
    948         }
    949         parser.next();
    950 
    951         int[] array = new int[num];
    952         int i = 0;
    953 
    954         int eventType = parser.getEventType();
    955         do {
    956             if (eventType == parser.START_TAG) {
    957                 if (parser.getName().equals("item")) {
    958                     try {
    959                         array[i] = Integer.parseInt(
    960                                 parser.getAttributeValue(null, "value"));
    961                     } catch (NullPointerException e) {
    962                         throw new XmlPullParserException(
    963                                 "Need value attribute in item");
    964                     } catch (NumberFormatException e) {
    965                         throw new XmlPullParserException(
    966                                 "Not a number in value attribute in item");
    967                     }
    968                 } else {
    969                     throw new XmlPullParserException(
    970                             "Expected item tag at: " + parser.getName());
    971                 }
    972             } else if (eventType == parser.END_TAG) {
    973                 if (parser.getName().equals(endTag)) {
    974                     return array;
    975                 } else if (parser.getName().equals("item")) {
    976                     i++;
    977                 } else {
    978                     throw new XmlPullParserException(
    979                         "Expected " + endTag + " end tag at: "
    980                         + parser.getName());
    981                 }
    982             }
    983             eventType = parser.next();
    984         } while (eventType != parser.END_DOCUMENT);
    985 
    986         throw new XmlPullParserException(
    987             "Document ended before " + endTag + " end tag");
    988     }
    989 
    990     /**
    991      * Read a long[] object from an XmlPullParser.  The XML data could
    992      * previously have been generated by writeLongArrayXml().  The XmlPullParser
    993      * must be positioned <em>after</em> the tag that begins the list.
    994      *
    995      * @param parser The XmlPullParser from which to read the list data.
    996      * @param endTag Name of the tag that will end the list, usually "list".
    997      * @param name An array of one string, used to return the name attribute
    998      *             of the list's tag.
    999      *
   1000      * @return Returns a newly generated long[].
   1001      *
   1002      * @see #readListXml
   1003      */
   1004     public static final long[] readThisLongArrayXml(XmlPullParser parser,
   1005             String endTag, String[] name)
   1006             throws XmlPullParserException, java.io.IOException {
   1007 
   1008         int num;
   1009         try {
   1010             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
   1011         } catch (NullPointerException e) {
   1012             throw new XmlPullParserException("Need num attribute in long-array");
   1013         } catch (NumberFormatException e) {
   1014             throw new XmlPullParserException("Not a number in num attribute in long-array");
   1015         }
   1016         parser.next();
   1017 
   1018         long[] array = new long[num];
   1019         int i = 0;
   1020 
   1021         int eventType = parser.getEventType();
   1022         do {
   1023             if (eventType == parser.START_TAG) {
   1024                 if (parser.getName().equals("item")) {
   1025                     try {
   1026                         array[i] = Long.parseLong(parser.getAttributeValue(null, "value"));
   1027                     } catch (NullPointerException e) {
   1028                         throw new XmlPullParserException("Need value attribute in item");
   1029                     } catch (NumberFormatException e) {
   1030                         throw new XmlPullParserException("Not a number in value attribute in item");
   1031                     }
   1032                 } else {
   1033                     throw new XmlPullParserException("Expected item tag at: " + parser.getName());
   1034                 }
   1035             } else if (eventType == parser.END_TAG) {
   1036                 if (parser.getName().equals(endTag)) {
   1037                     return array;
   1038                 } else if (parser.getName().equals("item")) {
   1039                     i++;
   1040                 } else {
   1041                     throw new XmlPullParserException("Expected " + endTag + " end tag at: " +
   1042                             parser.getName());
   1043                 }
   1044             }
   1045             eventType = parser.next();
   1046         } while (eventType != parser.END_DOCUMENT);
   1047 
   1048         throw new XmlPullParserException("Document ended before " + endTag + " end tag");
   1049     }
   1050 
   1051     /**
   1052      * Read a double[] object from an XmlPullParser.  The XML data could
   1053      * previously have been generated by writeDoubleArrayXml().  The XmlPullParser
   1054      * must be positioned <em>after</em> the tag that begins the list.
   1055      *
   1056      * @param parser The XmlPullParser from which to read the list data.
   1057      * @param endTag Name of the tag that will end the list, usually "double-array".
   1058      * @param name An array of one string, used to return the name attribute
   1059      *             of the list's tag.
   1060      *
   1061      * @return Returns a newly generated double[].
   1062      *
   1063      * @see #readListXml
   1064      */
   1065     public static final double[] readThisDoubleArrayXml(XmlPullParser parser, String endTag,
   1066             String[] name) throws XmlPullParserException, java.io.IOException {
   1067 
   1068         int num;
   1069         try {
   1070             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
   1071         } catch (NullPointerException e) {
   1072             throw new XmlPullParserException("Need num attribute in double-array");
   1073         } catch (NumberFormatException e) {
   1074             throw new XmlPullParserException("Not a number in num attribute in double-array");
   1075         }
   1076         parser.next();
   1077 
   1078         double[] array = new double[num];
   1079         int i = 0;
   1080 
   1081         int eventType = parser.getEventType();
   1082         do {
   1083             if (eventType == parser.START_TAG) {
   1084                 if (parser.getName().equals("item")) {
   1085                     try {
   1086                         array[i] = Double.parseDouble(parser.getAttributeValue(null, "value"));
   1087                     } catch (NullPointerException e) {
   1088                         throw new XmlPullParserException("Need value attribute in item");
   1089                     } catch (NumberFormatException e) {
   1090                         throw new XmlPullParserException("Not a number in value attribute in item");
   1091                     }
   1092                 } else {
   1093                     throw new XmlPullParserException("Expected item tag at: " + parser.getName());
   1094                 }
   1095             } else if (eventType == parser.END_TAG) {
   1096                 if (parser.getName().equals(endTag)) {
   1097                     return array;
   1098                 } else if (parser.getName().equals("item")) {
   1099                     i++;
   1100                 } else {
   1101                     throw new XmlPullParserException("Expected " + endTag + " end tag at: " +
   1102                             parser.getName());
   1103                 }
   1104             }
   1105             eventType = parser.next();
   1106         } while (eventType != parser.END_DOCUMENT);
   1107 
   1108         throw new XmlPullParserException("Document ended before " + endTag + " end tag");
   1109     }
   1110 
   1111     /**
   1112      * Read a String[] object from an XmlPullParser.  The XML data could
   1113      * previously have been generated by writeStringArrayXml().  The XmlPullParser
   1114      * must be positioned <em>after</em> the tag that begins the list.
   1115      *
   1116      * @param parser The XmlPullParser from which to read the list data.
   1117      * @param endTag Name of the tag that will end the list, usually "string-array".
   1118      * @param name An array of one string, used to return the name attribute
   1119      *             of the list's tag.
   1120      *
   1121      * @return Returns a newly generated String[].
   1122      *
   1123      * @see #readListXml
   1124      */
   1125     public static final String[] readThisStringArrayXml(XmlPullParser parser, String endTag,
   1126             String[] name) throws XmlPullParserException, java.io.IOException {
   1127 
   1128         int num;
   1129         try {
   1130             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
   1131         } catch (NullPointerException e) {
   1132             throw new XmlPullParserException("Need num attribute in string-array");
   1133         } catch (NumberFormatException e) {
   1134             throw new XmlPullParserException("Not a number in num attribute in string-array");
   1135         }
   1136         parser.next();
   1137 
   1138         String[] array = new String[num];
   1139         int i = 0;
   1140 
   1141         int eventType = parser.getEventType();
   1142         do {
   1143             if (eventType == parser.START_TAG) {
   1144                 if (parser.getName().equals("item")) {
   1145                     try {
   1146                         array[i] = parser.getAttributeValue(null, "value");
   1147                     } catch (NullPointerException e) {
   1148                         throw new XmlPullParserException("Need value attribute in item");
   1149                     } catch (NumberFormatException e) {
   1150                         throw new XmlPullParserException("Not a number in value attribute in item");
   1151                     }
   1152                 } else {
   1153                     throw new XmlPullParserException("Expected item tag at: " + parser.getName());
   1154                 }
   1155             } else if (eventType == parser.END_TAG) {
   1156                 if (parser.getName().equals(endTag)) {
   1157                     return array;
   1158                 } else if (parser.getName().equals("item")) {
   1159                     i++;
   1160                 } else {
   1161                     throw new XmlPullParserException("Expected " + endTag + " end tag at: " +
   1162                             parser.getName());
   1163                 }
   1164             }
   1165             eventType = parser.next();
   1166         } while (eventType != parser.END_DOCUMENT);
   1167 
   1168         throw new XmlPullParserException("Document ended before " + endTag + " end tag");
   1169     }
   1170 
   1171     /**
   1172      * Read a flattened object from an XmlPullParser.  The XML data could
   1173      * previously have been written with writeMapXml(), writeListXml(), or
   1174      * writeValueXml().  The XmlPullParser must be positioned <em>at</em> the
   1175      * tag that defines the value.
   1176      *
   1177      * @param parser The XmlPullParser from which to read the object.
   1178      * @param name An array of one string, used to return the name attribute
   1179      *             of the value's tag.
   1180      *
   1181      * @return Object The newly generated value object.
   1182      *
   1183      * @see #readMapXml
   1184      * @see #readListXml
   1185      * @see #writeValueXml
   1186      */
   1187     public static final Object readValueXml(XmlPullParser parser, String[] name)
   1188     throws XmlPullParserException, java.io.IOException
   1189     {
   1190         int eventType = parser.getEventType();
   1191         do {
   1192             if (eventType == parser.START_TAG) {
   1193                 return readThisValueXml(parser, name, null);
   1194             } else if (eventType == parser.END_TAG) {
   1195                 throw new XmlPullParserException(
   1196                     "Unexpected end tag at: " + parser.getName());
   1197             } else if (eventType == parser.TEXT) {
   1198                 throw new XmlPullParserException(
   1199                     "Unexpected text: " + parser.getText());
   1200             }
   1201             eventType = parser.next();
   1202         } while (eventType != parser.END_DOCUMENT);
   1203 
   1204         throw new XmlPullParserException(
   1205             "Unexpected end of document");
   1206     }
   1207 
   1208     private static final Object readThisValueXml(XmlPullParser parser, String[] name,
   1209             ReadMapCallback callback)  throws XmlPullParserException, java.io.IOException {
   1210         final String valueName = parser.getAttributeValue(null, "name");
   1211         final String tagName = parser.getName();
   1212 
   1213         //System.out.println("Reading this value tag: " + tagName + ", name=" + valueName);
   1214 
   1215         Object res;
   1216 
   1217         if (tagName.equals("null")) {
   1218             res = null;
   1219         } else if (tagName.equals("string")) {
   1220             String value = "";
   1221             int eventType;
   1222             while ((eventType = parser.next()) != parser.END_DOCUMENT) {
   1223                 if (eventType == parser.END_TAG) {
   1224                     if (parser.getName().equals("string")) {
   1225                         name[0] = valueName;
   1226                         //System.out.println("Returning value for " + valueName + ": " + value);
   1227                         return value;
   1228                     }
   1229                     throw new XmlPullParserException(
   1230                         "Unexpected end tag in <string>: " + parser.getName());
   1231                 } else if (eventType == parser.TEXT) {
   1232                     value += parser.getText();
   1233                 } else if (eventType == parser.START_TAG) {
   1234                     throw new XmlPullParserException(
   1235                         "Unexpected start tag in <string>: " + parser.getName());
   1236                 }
   1237             }
   1238             throw new XmlPullParserException(
   1239                 "Unexpected end of document in <string>");
   1240         } else if ((res = readThisPrimitiveValueXml(parser, tagName)) != null) {
   1241             // all work already done by readThisPrimitiveValueXml
   1242         } else if (tagName.equals("int-array")) {
   1243             res = readThisIntArrayXml(parser, "int-array", name);
   1244             name[0] = valueName;
   1245             //System.out.println("Returning value for " + valueName + ": " + res);
   1246             return res;
   1247         } else if (tagName.equals("long-array")) {
   1248             res = readThisLongArrayXml(parser, "long-array", name);
   1249             name[0] = valueName;
   1250             //System.out.println("Returning value for " + valueName + ": " + res);
   1251             return res;
   1252         } else if (tagName.equals("double-array")) {
   1253             res = readThisDoubleArrayXml(parser, "double-array", name);
   1254             name[0] = valueName;
   1255             //System.out.println("Returning value for " + valueName + ": " + res);
   1256             return res;
   1257         } else if (tagName.equals("string-array")) {
   1258             res = readThisStringArrayXml(parser, "string-array", name);
   1259             name[0] = valueName;
   1260             //System.out.println("Returning value for " + valueName + ": " + res);
   1261             return res;
   1262         } else if (tagName.equals("map")) {
   1263             parser.next();
   1264             res = readThisMapXml(parser, "map", name);
   1265             name[0] = valueName;
   1266             //System.out.println("Returning value for " + valueName + ": " + res);
   1267             return res;
   1268         } else if (tagName.equals("list")) {
   1269             parser.next();
   1270             res = readThisListXml(parser, "list", name);
   1271             name[0] = valueName;
   1272             //System.out.println("Returning value for " + valueName + ": " + res);
   1273             return res;
   1274         } else if (tagName.equals("set")) {
   1275             parser.next();
   1276             res = readThisSetXml(parser, "set", name);
   1277             name[0] = valueName;
   1278             //System.out.println("Returning value for " + valueName + ": " + res);
   1279             return res;
   1280         } else if (callback != null) {
   1281             res = callback.readThisUnknownObjectXml(parser, tagName);
   1282             name[0] = valueName;
   1283             return res;
   1284         } else {
   1285             throw new XmlPullParserException("Unknown tag: " + tagName);
   1286         }
   1287 
   1288         // Skip through to end tag.
   1289         int eventType;
   1290         while ((eventType = parser.next()) != parser.END_DOCUMENT) {
   1291             if (eventType == parser.END_TAG) {
   1292                 if (parser.getName().equals(tagName)) {
   1293                     name[0] = valueName;
   1294                     //System.out.println("Returning value for " + valueName + ": " + res);
   1295                     return res;
   1296                 }
   1297                 throw new XmlPullParserException(
   1298                     "Unexpected end tag in <" + tagName + ">: " + parser.getName());
   1299             } else if (eventType == parser.TEXT) {
   1300                 throw new XmlPullParserException(
   1301                 "Unexpected text in <" + tagName + ">: " + parser.getName());
   1302             } else if (eventType == parser.START_TAG) {
   1303                 throw new XmlPullParserException(
   1304                     "Unexpected start tag in <" + tagName + ">: " + parser.getName());
   1305             }
   1306         }
   1307         throw new XmlPullParserException(
   1308             "Unexpected end of document in <" + tagName + ">");
   1309     }
   1310 
   1311     private static final Object readThisPrimitiveValueXml(XmlPullParser parser, String tagName)
   1312     throws XmlPullParserException, java.io.IOException
   1313     {
   1314         try {
   1315             if (tagName.equals("int")) {
   1316                 return Integer.parseInt(parser.getAttributeValue(null, "value"));
   1317             } else if (tagName.equals("long")) {
   1318                 return Long.valueOf(parser.getAttributeValue(null, "value"));
   1319             } else if (tagName.equals("float")) {
   1320                 return new Float(parser.getAttributeValue(null, "value"));
   1321             } else if (tagName.equals("double")) {
   1322                 return new Double(parser.getAttributeValue(null, "value"));
   1323             } else if (tagName.equals("boolean")) {
   1324                 return Boolean.valueOf(parser.getAttributeValue(null, "value"));
   1325             } else {
   1326                 return null;
   1327             }
   1328         } catch (NullPointerException e) {
   1329             throw new XmlPullParserException("Need value attribute in <" + tagName + ">");
   1330         } catch (NumberFormatException e) {
   1331             throw new XmlPullParserException(
   1332                     "Not a number in value attribute in <" + tagName + ">");
   1333         }
   1334     }
   1335 
   1336     public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException
   1337     {
   1338         int type;
   1339         while ((type=parser.next()) != parser.START_TAG
   1340                    && type != parser.END_DOCUMENT) {
   1341             ;
   1342         }
   1343 
   1344         if (type != parser.START_TAG) {
   1345             throw new XmlPullParserException("No start tag found");
   1346         }
   1347 
   1348         if (!parser.getName().equals(firstElementName)) {
   1349             throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
   1350                     ", expected " + firstElementName);
   1351         }
   1352     }
   1353 
   1354     public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException
   1355     {
   1356         int type;
   1357         while ((type=parser.next()) != parser.START_TAG
   1358                    && type != parser.END_DOCUMENT) {
   1359             ;
   1360         }
   1361     }
   1362 
   1363     public static boolean nextElementWithin(XmlPullParser parser, int outerDepth)
   1364             throws IOException, XmlPullParserException {
   1365         for (;;) {
   1366             int type = parser.next();
   1367             if (type == XmlPullParser.END_DOCUMENT
   1368                     || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) {
   1369                 return false;
   1370             }
   1371             if (type == XmlPullParser.START_TAG
   1372                     && parser.getDepth() == outerDepth + 1) {
   1373                 return true;
   1374             }
   1375         }
   1376     }
   1377 
   1378     public static int readIntAttribute(XmlPullParser in, String name, int defaultValue) {
   1379         final String value = in.getAttributeValue(null, name);
   1380         try {
   1381             return Integer.parseInt(value);
   1382         } catch (NumberFormatException e) {
   1383             return defaultValue;
   1384         }
   1385     }
   1386 
   1387     public static int readIntAttribute(XmlPullParser in, String name) throws IOException {
   1388         final String value = in.getAttributeValue(null, name);
   1389         try {
   1390             return Integer.parseInt(value);
   1391         } catch (NumberFormatException e) {
   1392             throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
   1393         }
   1394     }
   1395 
   1396     public static void writeIntAttribute(XmlSerializer out, String name, int value)
   1397             throws IOException {
   1398         out.attribute(null, name, Integer.toString(value));
   1399     }
   1400 
   1401     public static long readLongAttribute(XmlPullParser in, String name, long defaultValue) {
   1402         final String value = in.getAttributeValue(null, name);
   1403         try {
   1404             return Long.parseLong(value);
   1405         } catch (NumberFormatException e) {
   1406             return defaultValue;
   1407         }
   1408     }
   1409 
   1410     public static long readLongAttribute(XmlPullParser in, String name) throws IOException {
   1411         final String value = in.getAttributeValue(null, name);
   1412         try {
   1413             return Long.parseLong(value);
   1414         } catch (NumberFormatException e) {
   1415             throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
   1416         }
   1417     }
   1418 
   1419     public static void writeLongAttribute(XmlSerializer out, String name, long value)
   1420             throws IOException {
   1421         out.attribute(null, name, Long.toString(value));
   1422     }
   1423 
   1424     public static float readFloatAttribute(XmlPullParser in, String name) throws IOException {
   1425         final String value = in.getAttributeValue(null, name);
   1426         try {
   1427             return Float.parseFloat(value);
   1428         } catch (NumberFormatException e) {
   1429             throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
   1430         }
   1431     }
   1432 
   1433     public static void writeFloatAttribute(XmlSerializer out, String name, float value)
   1434             throws IOException {
   1435         out.attribute(null, name, Float.toString(value));
   1436     }
   1437 
   1438     public static boolean readBooleanAttribute(XmlPullParser in, String name) {
   1439         final String value = in.getAttributeValue(null, name);
   1440         return Boolean.parseBoolean(value);
   1441     }
   1442 
   1443     public static boolean readBooleanAttribute(XmlPullParser in, String name,
   1444             boolean defaultValue) {
   1445         final String value = in.getAttributeValue(null, name);
   1446         if (value == null) {
   1447             return defaultValue;
   1448         } else {
   1449             return Boolean.parseBoolean(value);
   1450         }
   1451     }
   1452 
   1453     public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
   1454             throws IOException {
   1455         out.attribute(null, name, Boolean.toString(value));
   1456     }
   1457 
   1458     public static Uri readUriAttribute(XmlPullParser in, String name) {
   1459         final String value = in.getAttributeValue(null, name);
   1460         return (value != null) ? Uri.parse(value) : null;
   1461     }
   1462 
   1463     public static void writeUriAttribute(XmlSerializer out, String name, Uri value)
   1464             throws IOException {
   1465         if (value != null) {
   1466             out.attribute(null, name, value.toString());
   1467         }
   1468     }
   1469 
   1470     public static String readStringAttribute(XmlPullParser in, String name) {
   1471         return in.getAttributeValue(null, name);
   1472     }
   1473 
   1474     public static void writeStringAttribute(XmlSerializer out, String name, String value)
   1475             throws IOException {
   1476         if (value != null) {
   1477             out.attribute(null, name, value);
   1478         }
   1479     }
   1480 
   1481     public static byte[] readByteArrayAttribute(XmlPullParser in, String name) {
   1482         final String value = in.getAttributeValue(null, name);
   1483         if (value != null) {
   1484             return Base64.decode(value, Base64.DEFAULT);
   1485         } else {
   1486             return null;
   1487         }
   1488     }
   1489 
   1490     public static void writeByteArrayAttribute(XmlSerializer out, String name, byte[] value)
   1491             throws IOException {
   1492         if (value != null) {
   1493             out.attribute(null, name, Base64.encodeToString(value, Base64.DEFAULT));
   1494         }
   1495     }
   1496 
   1497     public static Bitmap readBitmapAttribute(XmlPullParser in, String name) {
   1498         final byte[] value = readByteArrayAttribute(in, name);
   1499         if (value != null) {
   1500             return BitmapFactory.decodeByteArray(value, 0, value.length);
   1501         } else {
   1502             return null;
   1503         }
   1504     }
   1505 
   1506     @Deprecated
   1507     public static void writeBitmapAttribute(XmlSerializer out, String name, Bitmap value)
   1508             throws IOException {
   1509         if (value != null) {
   1510             final ByteArrayOutputStream os = new ByteArrayOutputStream();
   1511             value.compress(CompressFormat.PNG, 90, os);
   1512             writeByteArrayAttribute(out, name, os.toByteArray());
   1513         }
   1514     }
   1515 
   1516     /** @hide */
   1517     public interface WriteMapCallback {
   1518         /**
   1519          * Called from writeMapXml when an Object type is not recognized. The implementer
   1520          * must write out the entire element including start and end tags.
   1521          *
   1522          * @param v The object to be written out
   1523          * @param name The mapping key for v. Must be written into the "name" attribute of the
   1524          *             start tag.
   1525          * @param out The XML output stream.
   1526          * @throws XmlPullParserException on unrecognized Object type.
   1527          * @throws IOException on XmlSerializer serialization errors.
   1528          * @hide
   1529          */
   1530          public void writeUnknownObject(Object v, String name, XmlSerializer out)
   1531                  throws XmlPullParserException, IOException;
   1532     }
   1533 
   1534     /** @hide */
   1535     public interface ReadMapCallback {
   1536         /**
   1537          * Called from readThisMapXml when a START_TAG is not recognized. The input stream
   1538          * is positioned within the start tag so that attributes can be read using in.getAttribute.
   1539          *
   1540          * @param in the XML input stream
   1541          * @param tag the START_TAG that was not recognized.
   1542          * @return the Object parsed from the stream which will be put into the map.
   1543          * @throws XmlPullParserException if the START_TAG is not recognized.
   1544          * @throws IOException on XmlPullParser serialization errors.
   1545          * @hide
   1546          */
   1547         public Object readThisUnknownObjectXml(XmlPullParser in, String tag)
   1548                 throws XmlPullParserException, IOException;
   1549     }
   1550 }
   1551