1bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu/*
2bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * Copyright (C) 2016 The Android Open Source Project
3bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *
4bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * Licensed under the Apache License, Version 2.0 (the "License");
5bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * you may not use this file except in compliance with the License.
6bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * You may obtain a copy of the License at
7bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *
8bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *      http://www.apache.org/licenses/LICENSE-2.0
9bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *
10bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * Unless required by applicable law or agreed to in writing, software
11bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * distributed under the License is distributed on an "AS IS" BASIS,
12bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * See the License for the specific language governing permissions and
14bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * limitations under the License.
15bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu */
16bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
17bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiupackage android.net.wifi.hotspot2.omadm;
18bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
19bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiuimport org.xml.sax.Attributes;
20bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiuimport org.xml.sax.InputSource;
21bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiuimport org.xml.sax.SAXException;
22bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiuimport org.xml.sax.helpers.DefaultHandler;
23bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
24bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiuimport android.text.TextUtils;
25bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
26bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiuimport java.io.IOException;
27bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiuimport java.io.StringReader;
28bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
29bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiuimport javax.xml.parsers.ParserConfigurationException;
30bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiuimport javax.xml.parsers.SAXParser;
31bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiuimport javax.xml.parsers.SAXParserFactory;
32bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
33bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu/**
34bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * Class for parsing an XML string to an XML tree represented by {@link XMLNode}.
35bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *
36bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * The original XML string:
37bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * <root>
38bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *   <tag1>text1</tag1>
39bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *   <tag2>
40bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *     <tag3>text3</tag3>
41bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *   </tag2>
42bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * </root>
43bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *
44bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * The XML tree representation:
45bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *                  [root]
46bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *                     |
47bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *                     |
48bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *   [tag1, text1]-----|-----[tag2]
49bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *                             |
50bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *                             |
51bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *                       [tag3, text3]
52bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu *
53bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu * @hide
54bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu */
55bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiupublic class XMLParser extends DefaultHandler {
56bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    private XMLNode mRoot = null;
57bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    private XMLNode mCurrent = null;
58bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
59bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    public XMLNode parse(String text) throws IOException, SAXException {
60bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        if (TextUtils.isEmpty(text)) {
61bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu            throw new IOException("XML string not provided");
62bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        }
63bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
64bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        // Reset pointers.
65bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        mRoot = null;
66bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        mCurrent = null;
67bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
68bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        try {
69bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
70bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu            parser.parse(new InputSource(new StringReader(text)), this);
71bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu            return mRoot;
72bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        } catch (ParserConfigurationException pce) {
73bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu            throw new SAXException(pce);
74bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        }
75bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    }
76bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
77bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    @Override
78bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    public void startElement(String uri, String localName, String qName, Attributes attributes)
79bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu            throws SAXException {
80bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        XMLNode parent = mCurrent;
81bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
82bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        mCurrent = new XMLNode(parent, qName);
83bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
84bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        if (mRoot == null) {
85bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu            mRoot = mCurrent;
86bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        } else if (parent == null) {
87bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu            throw new SAXException("More than one root nodes");
88bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        } else {
89bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu            parent.addChild(mCurrent);
90bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        }
91bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    }
92bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
93bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    @Override
94bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    public void endElement(String uri, String localName, String qName) throws SAXException {
95bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        if (!qName.equals(mCurrent.getTag())) {
96bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu            throw new SAXException("End tag '" + qName + "' doesn't match current node: " +
97bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu                    mCurrent);
98bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        }
99bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
100bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        mCurrent.close();
101bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        mCurrent = mCurrent.getParent();
102bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    }
103bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu
104bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    @Override
105bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    public void characters(char[] ch, int start, int length) throws SAXException {
106bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu        mCurrent.addText(new String(ch, start, length));
107bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu    }
108bae4becf6997843cddf0d0c1dfa1f63e4580e6f8Peter Qiu}
109