diff options
Diffstat (limited to 'java/com/android/voicemail/impl/utils/XmlUtils.java')
-rw-r--r-- | java/com/android/voicemail/impl/utils/XmlUtils.java | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/java/com/android/voicemail/impl/utils/XmlUtils.java b/java/com/android/voicemail/impl/utils/XmlUtils.java new file mode 100644 index 000000000..f5703f30f --- /dev/null +++ b/java/com/android/voicemail/impl/utils/XmlUtils.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.voicemail.impl.utils; + +import android.util.ArrayMap; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +public class XmlUtils { + + public static final ArrayMap<String, ?> readThisArrayMapXml( + XmlPullParser parser, String endTag, String[] name, ReadMapCallback callback) + throws XmlPullParserException, java.io.IOException { + ArrayMap<String, Object> map = new ArrayMap<>(); + + int eventType = parser.getEventType(); + do { + if (eventType == XmlPullParser.START_TAG) { + Object val = readThisValueXml(parser, name, callback, true); + map.put(name[0], val); + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals(endTag)) { + return map; + } + throw new XmlPullParserException("Expected " + endTag + " end tag at: " + parser.getName()); + } + eventType = parser.next(); + } while (eventType != XmlPullParser.END_DOCUMENT); + + throw new XmlPullParserException("Document ended before " + endTag + " end tag"); + } + + /** + * Read an ArrayList object from an XmlPullParser. The XML data could previously have been + * generated by writeListXml(). The XmlPullParser must be positioned <em>after</em> the tag that + * begins the list. + * + * @param parser The XmlPullParser from which to read the list data. + * @param endTag Name of the tag that will end the list, usually "list". + * @param name An array of one string, used to return the name attribute of the list's tag. + * @return HashMap The newly generated list. + */ + public static final ArrayList readThisListXml( + XmlPullParser parser, + String endTag, + String[] name, + ReadMapCallback callback, + boolean arrayMap) + throws XmlPullParserException, java.io.IOException { + ArrayList list = new ArrayList(); + + int eventType = parser.getEventType(); + do { + if (eventType == XmlPullParser.START_TAG) { + Object val = readThisValueXml(parser, name, callback, arrayMap); + list.add(val); + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals(endTag)) { + return list; + } + throw new XmlPullParserException("Expected " + endTag + " end tag at: " + parser.getName()); + } + eventType = parser.next(); + } while (eventType != XmlPullParser.END_DOCUMENT); + + throw new XmlPullParserException("Document ended before " + endTag + " end tag"); + } + + /** + * Read a String[] object from an XmlPullParser. The XML data could previously have been generated + * by writeStringArrayXml(). The XmlPullParser must be positioned <em>after</em> the tag that + * begins the list. + * + * @param parser The XmlPullParser from which to read the list data. + * @param endTag Name of the tag that will end the list, usually "string-array". + * @param name An array of one string, used to return the name attribute of the list's tag. + * @return Returns a newly generated String[]. + */ + public static String[] readThisStringArrayXml(XmlPullParser parser, String endTag, String[] name) + throws XmlPullParserException, java.io.IOException { + + parser.next(); + + List<String> array = new ArrayList<>(); + + int eventType = parser.getEventType(); + do { + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("item")) { + try { + array.add(parser.getAttributeValue(null, "value")); + } catch (NullPointerException e) { + throw new XmlPullParserException("Need value attribute in item"); + } catch (NumberFormatException e) { + throw new XmlPullParserException("Not a number in value attribute in item"); + } + } else { + throw new XmlPullParserException("Expected item tag at: " + parser.getName()); + } + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals(endTag)) { + return array.toArray(new String[0]); + } else if (parser.getName().equals("item")) { + + } else { + throw new XmlPullParserException( + "Expected " + endTag + " end tag at: " + parser.getName()); + } + } + eventType = parser.next(); + } while (eventType != XmlPullParser.END_DOCUMENT); + + throw new XmlPullParserException("Document ended before " + endTag + " end tag"); + } + + private static Object readThisValueXml( + XmlPullParser parser, String[] name, ReadMapCallback callback, boolean arrayMap) + throws XmlPullParserException, java.io.IOException { + final String valueName = parser.getAttributeValue(null, "name"); + final String tagName = parser.getName(); + + Object res; + + if (tagName.equals("null")) { + res = null; + } else if (tagName.equals("string")) { + String value = ""; + int eventType; + while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("string")) { + name[0] = valueName; + return value; + } + throw new XmlPullParserException("Unexpected end tag in <string>: " + parser.getName()); + } else if (eventType == XmlPullParser.TEXT) { + value += parser.getText(); + } else if (eventType == XmlPullParser.START_TAG) { + throw new XmlPullParserException("Unexpected start tag in <string>: " + parser.getName()); + } + } + throw new XmlPullParserException("Unexpected end of document in <string>"); + } else if ((res = readThisPrimitiveValueXml(parser, tagName)) != null) { + // all work already done by readThisPrimitiveValueXml + } else if (tagName.equals("string-array")) { + res = readThisStringArrayXml(parser, "string-array", name); + name[0] = valueName; + return res; + } else if (tagName.equals("list")) { + parser.next(); + res = readThisListXml(parser, "list", name, callback, arrayMap); + name[0] = valueName; + return res; + } else if (callback != null) { + res = callback.readThisUnknownObjectXml(parser, tagName); + name[0] = valueName; + return res; + } else { + throw new XmlPullParserException("Unknown tag: " + tagName); + } + + // Skip through to end tag. + int eventType; + while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals(tagName)) { + name[0] = valueName; + return res; + } + throw new XmlPullParserException( + "Unexpected end tag in <" + tagName + ">: " + parser.getName()); + } else if (eventType == XmlPullParser.TEXT) { + throw new XmlPullParserException( + "Unexpected text in <" + tagName + ">: " + parser.getName()); + } else if (eventType == XmlPullParser.START_TAG) { + throw new XmlPullParserException( + "Unexpected start tag in <" + tagName + ">: " + parser.getName()); + } + } + throw new XmlPullParserException("Unexpected end of document in <" + tagName + ">"); + } + + private static final Object readThisPrimitiveValueXml(XmlPullParser parser, String tagName) + throws XmlPullParserException, java.io.IOException { + try { + if (tagName.equals("int")) { + return Integer.parseInt(parser.getAttributeValue(null, "value")); + } else if (tagName.equals("long")) { + return Long.valueOf(parser.getAttributeValue(null, "value")); + } else if (tagName.equals("float")) { + return Float.valueOf(parser.getAttributeValue(null, "value")); + } else if (tagName.equals("double")) { + return Double.valueOf(parser.getAttributeValue(null, "value")); + } else if (tagName.equals("boolean")) { + return Boolean.valueOf(parser.getAttributeValue(null, "value")); + } else { + return null; + } + } catch (NullPointerException e) { + throw new XmlPullParserException("Need value attribute in <" + tagName + ">"); + } catch (NumberFormatException e) { + throw new XmlPullParserException("Not a number in value attribute in <" + tagName + ">"); + } + } + + public interface ReadMapCallback { + + /** + * Called from readThisMapXml when a START_TAG is not recognized. The input stream is positioned + * within the start tag so that attributes can be read using in.getAttribute. + * + * @param in the XML input stream + * @param tag the START_TAG that was not recognized. + * @return the Object parsed from the stream which will be put into the map. + * @throws XmlPullParserException if the START_TAG is not recognized. + * @throws IOException on XmlPullParser serialization errors. + */ + Object readThisUnknownObjectXml(XmlPullParser in, String tag) + throws XmlPullParserException, IOException; + } +} |