1package com.android.server.wifi.hotspot2.omadm;
2
3import org.xml.sax.Attributes;
4import org.xml.sax.SAXException;
5
6import java.io.IOException;
7import java.util.ArrayList;
8import java.util.Arrays;
9import java.util.Collections;
10import java.util.HashMap;
11import java.util.List;
12import java.util.Map;
13
14public class XMLNode {
15    private final String mTag;
16    private final Map<String, NodeAttribute> mAttributes;
17    private final List<XMLNode> mChildren;
18    private final XMLNode mParent;
19    private MOTree mMO;
20    private StringBuilder mTextBuilder;
21    private String mText;
22
23    public XMLNode(XMLNode parent, String tag, Attributes attributes) throws SAXException {
24        mTag = tag;
25
26        mAttributes = new HashMap<String, NodeAttribute>();
27
28        if (attributes.getLength() > 0) {
29            for (int n = 0; n < attributes.getLength(); n++)
30                mAttributes.put(attributes.getQName(n), new NodeAttribute(attributes.getQName(n),
31                        attributes.getType(n), attributes.getValue(n)));
32        }
33
34        mParent = parent;
35        mChildren = new ArrayList<XMLNode>();
36
37        mTextBuilder = new StringBuilder();
38    }
39
40    public void addText(char[] chs, int start, int length) {
41        String s = new String(chs, start, length);
42        String trimmed = s.trim();
43        if (trimmed.isEmpty())
44            return;
45
46        if (s.charAt(0) != trimmed.charAt(0))
47            mTextBuilder.append(' ');
48        mTextBuilder.append(trimmed);
49        if (s.charAt(s.length() - 1) != trimmed.charAt(trimmed.length() - 1))
50            mTextBuilder.append(' ');
51    }
52
53    public void addChild(XMLNode child) {
54        mChildren.add(child);
55    }
56
57    public void close() throws IOException, SAXException {
58        String text = mTextBuilder.toString().trim();
59        StringBuilder filtered = new StringBuilder(text.length());
60        for (int n = 0; n < text.length(); n++) {
61            char ch = text.charAt(n);
62            if (ch >= ' ')
63                filtered.append(ch);
64        }
65
66        mText = filtered.toString();
67        mTextBuilder = null;
68
69        if (OMAConstants.isMOContainer(mTag)) {
70            NodeAttribute urn = mAttributes.get(OMAConstants.ATTR_URN);
71            OMAParser omaParser = new OMAParser();
72            mMO = omaParser.parse(mText, urn.getValue());
73        }
74    }
75
76    public String getTag() {
77        return mTag;
78    }
79
80    public XMLNode getParent() {
81        return mParent;
82    }
83
84    public String getText() {
85        return mText;
86    }
87
88    public Map<String, NodeAttribute> getAttributes() {
89        return Collections.unmodifiableMap(mAttributes);
90    }
91
92    public String getAttributeValue(String name) {
93        NodeAttribute nodeAttribute = mAttributes.get(name);
94        return nodeAttribute != null ? nodeAttribute.getValue() : null;
95    }
96
97    public List<XMLNode> getChildren() {
98        return mChildren;
99    }
100
101    public MOTree getMOTree() {
102        return mMO;
103    }
104
105    private void toString(char[] indent, StringBuilder sb) {
106        Arrays.fill(indent, ' ');
107
108        sb.append(indent).append('<').append(mTag).append("> ").append(mAttributes.values());
109
110        if (mMO != null)
111            sb.append('\n').append(mMO);
112        else if (!mText.isEmpty())
113            sb.append(", text: ").append(mText);
114
115        sb.append('\n');
116
117        char[] subIndent = Arrays.copyOf(indent, indent.length + 2);
118        for (XMLNode child : mChildren)
119            child.toString(subIndent, sb);
120    }
121
122    @Override
123    public String toString() {
124        StringBuilder sb = new StringBuilder();
125        toString(new char[0], sb);
126        return sb.toString();
127    }
128}
129