blob: a00f433aff511fdd5b8ec1a149a23af9f2ded92e [file] [log] [blame]
Jan Nordqvistee699a62016-02-05 15:30:26 -08001package com.android.hotspot2.omadm;
2
3import java.io.IOException;
4import java.io.InputStream;
5import java.io.OutputStream;
6import java.util.Collection;
7import java.util.HashMap;
8import java.util.Iterator;
9import java.util.LinkedList;
10import java.util.List;
11import java.util.Map;
12
13public abstract class OMANode {
14 private final OMAConstructed mParent;
15 private final String mName;
16 private final String mContext;
17 private final Map<String, String> mAttributes;
18
Jan Nordqvist0ff7a0a22016-02-08 11:01:43 -080019 protected OMANode(OMAConstructed parent, String name, String context, Map<String, String> avps) {
Jan Nordqvistee699a62016-02-05 15:30:26 -080020 mParent = parent;
21 mName = name;
22 mContext = context;
23 mAttributes = avps;
24 }
25
26 protected static Map<String, String> buildAttributes(String[] avps) {
27 if (avps == null) {
28 return null;
29 }
30 Map<String, String> attributes = new HashMap<>();
31 for (int n = 0; n < avps.length; n += 2) {
32 attributes.put(avps[n], avps[n + 1]);
33 }
34 return attributes;
35 }
36
37 protected Map<String, String> getAttributes() {
38 return mAttributes;
39 }
40
41 public OMAConstructed getParent() {
42 return mParent;
43 }
44
45 public String getName() {
46 return mName;
47 }
48
49 public String getContext() {
50 return mContext;
51 }
52
53 public List<String> getPath() {
54 LinkedList<String> path = new LinkedList<>();
55 for (OMANode node = this; node != null; node = node.getParent()) {
56 path.addFirst(node.getName());
57 }
58 return path;
59 }
60
61 public String getPathString() {
62 StringBuilder sb = new StringBuilder();
63 for (String element : getPath()) {
64 sb.append('/').append(element);
65 }
66 return sb.toString();
67 }
68
69 public abstract OMANode reparent(OMAConstructed parent);
70
71 public abstract String getScalarValue(Iterator<String> path) throws OMAException;
72
73 public abstract OMANode getListValue(Iterator<String> path) throws OMAException;
74
75 public abstract boolean isLeaf();
76
77 public abstract Collection<OMANode> getChildren();
78
79 public abstract OMANode getChild(String name) throws OMAException;
80
81 public abstract String getValue();
82
83 public abstract OMANode addChild(String name, String context, String value, String path)
84 throws IOException;
85
86 public abstract void marshal(OutputStream out, int level) throws IOException;
87
88 public abstract void toString(StringBuilder sb, int level);
89
90 public abstract void fillPayload(StringBuilder sb);
91
92 public void toXml(StringBuilder sb) {
93 sb.append('<').append(MOTree.NodeTag);
94 if (mAttributes != null && !mAttributes.isEmpty()) {
95 for (Map.Entry<String, String> avp : mAttributes.entrySet()) {
Jan Nordqvist0ff7a0a22016-02-08 11:01:43 -080096 sb.append(' ').append(avp.getKey()).append("=\"").append(avp.getValue()).append('"');
Jan Nordqvistee699a62016-02-05 15:30:26 -080097 }
98 }
99 sb.append(">\n");
100
101 sb.append('<').append(MOTree.NodeNameTag).append('>');
102 sb.append(getName());
103 sb.append("</").append(MOTree.NodeNameTag).append(">\n");
104
105 fillPayload(sb);
106
107 sb.append("</").append(MOTree.NodeTag).append(">\n");
108 }
109
110 @Override
111 public String toString() {
112 StringBuilder sb = new StringBuilder();
113 toString(sb, 0);
114 return sb.toString();
115 }
116
117 public static OMAConstructed unmarshal(InputStream in) throws IOException {
118 OMANode node = buildNode(in, null);
119 if (node == null || node.isLeaf()) {
120 throw new IOException("Bad OMA tree");
121 }
122 unmarshal(in, (OMAConstructed) node);
123 return (OMAConstructed) node;
124 }
125
126 private static void unmarshal(InputStream in, OMAConstructed parent) throws IOException {
127 for (; ; ) {
128 OMANode node = buildNode(in, parent);
129 if (node == null) {
130 return;
131 } else if (!node.isLeaf()) {
132 unmarshal(in, (OMAConstructed) node);
133 }
134 }
135 }
136
137 private static OMANode buildNode(InputStream in, OMAConstructed parent) throws IOException {
138 String name = OMAConstants.deserializeString(in);
139 if (name == null) {
140 return null;
141 }
142
143 String urn = null;
144 int next = in.read();
145 if (next == '(') {
146 urn = OMAConstants.readURN(in);
147 next = in.read();
148 }
149
150 if (next == '=') {
151 String value = OMAConstants.deserializeString(in);
152 return parent.addChild(name, urn, value, null);
153 } else if (next == '+') {
154 if (parent != null) {
155 return parent.addChild(name, urn, null, null);
156 } else {
157 return new OMAConstructed(null, name, urn);
158 }
159 } else {
160 throw new IOException("Parse error: expected = or + after node name");
161 }
162 }
163}