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