1d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian/*
2d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Copyright (C) 2016 The Android Open Source Project
3d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian *
4d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License");
5d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * you may not use this file except in compliance with the License.
6d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * You may obtain a copy of the License at
7d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian *
8d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian *      http://www.apache.org/licenses/LICENSE-2.0
9d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian *
10d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Unless required by applicable law or agreed to in writing, software
11d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS,
12d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * See the License for the specific language governing permissions and
14d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * limitations under the License.
15d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian */
16d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
17d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianpackage com.android.voicemail.impl.utils;
18d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
19d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.util.ArrayMap;
20d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport java.io.IOException;
21d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport java.util.ArrayList;
22d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport java.util.List;
23d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport org.xmlpull.v1.XmlPullParser;
24d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport org.xmlpull.v1.XmlPullParserException;
25d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
26d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianpublic class XmlUtils {
27d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
28d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  public static final ArrayMap<String, ?> readThisArrayMapXml(
29d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      XmlPullParser parser, String endTag, String[] name, ReadMapCallback callback)
30d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      throws XmlPullParserException, java.io.IOException {
31d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    ArrayMap<String, Object> map = new ArrayMap<>();
32d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
33d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    int eventType = parser.getEventType();
34d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    do {
35d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      if (eventType == XmlPullParser.START_TAG) {
36d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        Object val = readThisValueXml(parser, name, callback, true);
37d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        map.put(name[0], val);
38d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      } else if (eventType == XmlPullParser.END_TAG) {
39d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        if (parser.getName().equals(endTag)) {
40d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          return map;
41d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        }
42d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        throw new XmlPullParserException("Expected " + endTag + " end tag at: " + parser.getName());
43d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      }
44d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      eventType = parser.next();
45d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } while (eventType != XmlPullParser.END_DOCUMENT);
46d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
47d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    throw new XmlPullParserException("Document ended before " + endTag + " end tag");
48d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  }
49d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
50d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  /**
51d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * Read an ArrayList object from an XmlPullParser. The XML data could previously have been
52d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * generated by writeListXml(). The XmlPullParser must be positioned <em>after</em> the tag that
53d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * begins the list.
54d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   *
55d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * @param parser The XmlPullParser from which to read the list data.
56d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * @param endTag Name of the tag that will end the list, usually "list".
57d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * @param name An array of one string, used to return the name attribute of the list's tag.
58d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * @return HashMap The newly generated list.
59d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   */
60d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  public static final ArrayList readThisListXml(
61d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      XmlPullParser parser,
62d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      String endTag,
63d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      String[] name,
64d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      ReadMapCallback callback,
65d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      boolean arrayMap)
66d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      throws XmlPullParserException, java.io.IOException {
67d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    ArrayList list = new ArrayList();
68d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
69d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    int eventType = parser.getEventType();
70d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    do {
71d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      if (eventType == XmlPullParser.START_TAG) {
72d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        Object val = readThisValueXml(parser, name, callback, arrayMap);
73d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        list.add(val);
74d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      } else if (eventType == XmlPullParser.END_TAG) {
75d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        if (parser.getName().equals(endTag)) {
76d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          return list;
77d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        }
78d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        throw new XmlPullParserException("Expected " + endTag + " end tag at: " + parser.getName());
79d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      }
80d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      eventType = parser.next();
81d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } while (eventType != XmlPullParser.END_DOCUMENT);
82d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
83d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    throw new XmlPullParserException("Document ended before " + endTag + " end tag");
84d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  }
85d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
86d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  /**
87d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * Read a String[] object from an XmlPullParser. The XML data could previously have been generated
88d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * by writeStringArrayXml(). The XmlPullParser must be positioned <em>after</em> the tag that
89d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * begins the list.
90d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   *
91d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * @param parser The XmlPullParser from which to read the list data.
92d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * @param endTag Name of the tag that will end the list, usually "string-array".
93d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * @param name An array of one string, used to return the name attribute of the list's tag.
94d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   * @return Returns a newly generated String[].
95d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian   */
96d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  public static String[] readThisStringArrayXml(XmlPullParser parser, String endTag, String[] name)
97d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      throws XmlPullParserException, java.io.IOException {
98d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
99d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    parser.next();
100d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
101d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    List<String> array = new ArrayList<>();
102d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
103d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    int eventType = parser.getEventType();
104d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    do {
105d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      if (eventType == XmlPullParser.START_TAG) {
106d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        if (parser.getName().equals("item")) {
107d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          try {
108d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            array.add(parser.getAttributeValue(null, "value"));
109d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          } catch (NullPointerException e) {
110d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            throw new XmlPullParserException("Need value attribute in item");
111d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          } catch (NumberFormatException e) {
112d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            throw new XmlPullParserException("Not a number in value attribute in item");
113d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          }
114d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        } else {
115d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          throw new XmlPullParserException("Expected item tag at: " + parser.getName());
116d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        }
117d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      } else if (eventType == XmlPullParser.END_TAG) {
118d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        if (parser.getName().equals(endTag)) {
119d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          return array.toArray(new String[0]);
120d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        } else if (parser.getName().equals("item")) {
121d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
122d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        } else {
123d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          throw new XmlPullParserException(
124d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian              "Expected " + endTag + " end tag at: " + parser.getName());
125d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        }
126d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      }
127d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      eventType = parser.next();
128d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } while (eventType != XmlPullParser.END_DOCUMENT);
129d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
130d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    throw new XmlPullParserException("Document ended before " + endTag + " end tag");
131d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  }
132d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
133d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  private static Object readThisValueXml(
134d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      XmlPullParser parser, String[] name, ReadMapCallback callback, boolean arrayMap)
135d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      throws XmlPullParserException, java.io.IOException {
136d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    final String valueName = parser.getAttributeValue(null, "name");
137d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    final String tagName = parser.getName();
138d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
139d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    Object res;
140d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
141d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    if (tagName.equals("null")) {
142d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      res = null;
143d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } else if (tagName.equals("string")) {
144d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      String value = "";
145d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      int eventType;
146d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
147d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        if (eventType == XmlPullParser.END_TAG) {
148d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          if (parser.getName().equals("string")) {
149d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            name[0] = valueName;
150d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            return value;
151d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          }
152d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          throw new XmlPullParserException("Unexpected end tag in <string>: " + parser.getName());
153d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        } else if (eventType == XmlPullParser.TEXT) {
154d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          value += parser.getText();
155d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        } else if (eventType == XmlPullParser.START_TAG) {
156d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          throw new XmlPullParserException("Unexpected start tag in <string>: " + parser.getName());
157d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        }
158d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      }
159d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      throw new XmlPullParserException("Unexpected end of document in <string>");
160d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } else if ((res = readThisPrimitiveValueXml(parser, tagName)) != null) {
161d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      // all work already done by readThisPrimitiveValueXml
162d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } else if (tagName.equals("string-array")) {
163d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      res = readThisStringArrayXml(parser, "string-array", name);
164d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      name[0] = valueName;
165d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      return res;
166d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } else if (tagName.equals("list")) {
167d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      parser.next();
168d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      res = readThisListXml(parser, "list", name, callback, arrayMap);
169d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      name[0] = valueName;
170d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      return res;
171d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } else if (callback != null) {
172d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      res = callback.readThisUnknownObjectXml(parser, tagName);
173d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      name[0] = valueName;
174d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      return res;
175d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } else {
176d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      throw new XmlPullParserException("Unknown tag: " + tagName);
177d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    }
178d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
179d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    // Skip through to end tag.
180d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    int eventType;
181d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
182d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      if (eventType == XmlPullParser.END_TAG) {
183d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        if (parser.getName().equals(tagName)) {
184d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          name[0] = valueName;
185d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          return res;
186d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        }
187d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        throw new XmlPullParserException(
188d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            "Unexpected end tag in <" + tagName + ">: " + parser.getName());
189d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      } else if (eventType == XmlPullParser.TEXT) {
190d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        throw new XmlPullParserException(
191d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            "Unexpected text in <" + tagName + ">: " + parser.getName());
192d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      } else if (eventType == XmlPullParser.START_TAG) {
193d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        throw new XmlPullParserException(
194d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            "Unexpected start tag in <" + tagName + ">: " + parser.getName());
195d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      }
196d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    }
197d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    throw new XmlPullParserException("Unexpected end of document in <" + tagName + ">");
198d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  }
199d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
200d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  private static final Object readThisPrimitiveValueXml(XmlPullParser parser, String tagName)
201d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      throws XmlPullParserException, java.io.IOException {
202d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    try {
203d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      if (tagName.equals("int")) {
204d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        return Integer.parseInt(parser.getAttributeValue(null, "value"));
205d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      } else if (tagName.equals("long")) {
206d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        return Long.valueOf(parser.getAttributeValue(null, "value"));
207d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      } else if (tagName.equals("float")) {
208d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        return Float.valueOf(parser.getAttributeValue(null, "value"));
209d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      } else if (tagName.equals("double")) {
210d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        return Double.valueOf(parser.getAttributeValue(null, "value"));
211d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      } else if (tagName.equals("boolean")) {
212d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        return Boolean.valueOf(parser.getAttributeValue(null, "value"));
213d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      } else {
214d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        return null;
215d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      }
216d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } catch (NullPointerException e) {
217d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      throw new XmlPullParserException("Need value attribute in <" + tagName + ">");
218d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } catch (NumberFormatException e) {
219d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      throw new XmlPullParserException("Not a number in value attribute in <" + tagName + ">");
220d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    }
221d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  }
222d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
223d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  public interface ReadMapCallback {
224d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
225d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    /**
226d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian     * Called from readThisMapXml when a START_TAG is not recognized. The input stream is positioned
227d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian     * within the start tag so that attributes can be read using in.getAttribute.
228d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian     *
229d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian     * @param in the XML input stream
230d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian     * @param tag the START_TAG that was not recognized.
231d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian     * @return the Object parsed from the stream which will be put into the map.
232d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian     * @throws XmlPullParserException if the START_TAG is not recognized.
233d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian     * @throws IOException on XmlPullParser serialization errors.
234d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian     */
235d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    Object readThisUnknownObjectXml(XmlPullParser in, String tag)
236d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        throws XmlPullParserException, IOException;
237d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  }
238d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian}
239