1ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpackage com.android.hotspot2.omadm;
2ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
3ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.io.IOException;
4ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.io.OutputStream;
5ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.nio.charset.StandardCharsets;
6ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Collection;
7ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Collections;
8ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Iterator;
9ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Map;
10ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
11ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpublic class OMAConstructed extends OMANode {
12ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final MultiValueMap<OMANode> mChildren;
13ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
14ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public OMAConstructed(OMAConstructed parent, String name, String context, String... avps) {
15ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        this(parent, name, context, new MultiValueMap<OMANode>(), buildAttributes(avps));
16ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
17ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
18ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    protected OMAConstructed(OMAConstructed parent, String name, String context,
19ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                             MultiValueMap<OMANode> children, Map<String, String> avps) {
20ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        super(parent, name, context, avps);
21ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mChildren = children;
22ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
23ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
24ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
25ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public OMANode addChild(String name, String context, String value, String pathString)
26ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            throws IOException {
27ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (pathString == null) {
28ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            OMANode child = value != null ?
29ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    new OMAScalar(this, name, context, value) :
30ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    new OMAConstructed(this, name, context);
31ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            mChildren.put(name, child);
32ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return child;
33ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        } else {
34ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            OMANode target = this;
35ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            while (target.getParent() != null)
36ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                target = target.getParent();
37ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
38ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            for (String element : pathString.split("/")) {
39ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                target = target.getChild(element);
40ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                if (target == null)
41ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    throw new IOException("No child node '" + element + "' in " + getPathString());
42ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                else if (target.isLeaf())
43ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    throw new IOException("Cannot add child to leaf node: " + getPathString());
44ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
45ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return target.addChild(name, context, value, null);
46ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
47ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
48ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
49ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
50ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public OMAConstructed reparent(OMAConstructed parent) {
51ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return new OMAConstructed(parent, getName(), getContext(), mChildren, getAttributes());
52ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
53ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
54ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public void addChild(OMANode child) {
55ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mChildren.put(child.getName(), child.reparent(this));
56ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
57ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
58ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public String getScalarValue(Iterator<String> path) throws OMAException {
59ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (!path.hasNext()) {
60ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            throw new OMAException("Path too short for " + getPathString());
61ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
62ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        String tag = path.next();
63ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        OMANode child = mChildren.get(tag);
64ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (child != null) {
65ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return child.getScalarValue(path);
66ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        } else {
67ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return null;
68ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
69ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
70ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
71ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
72ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public OMANode getListValue(Iterator<String> path) throws OMAException {
73ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (!path.hasNext()) {
74ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return null;
75ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
76ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        String tag = path.next();
77ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        OMANode child;
78ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (tag.equals("?")) {
79ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            child = mChildren.getSingletonValue();
80ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        } else {
81ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            child = mChildren.get(tag);
82ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
83ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
84ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (child == null) {
85ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return null;
86ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        } else if (path.hasNext()) {
87ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return child.getListValue(path);
88ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        } else {
89ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return child;
90ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
91ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
92ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
93ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
94ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public boolean isLeaf() {
95ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return false;
96ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
97ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
98ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
99ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public Collection<OMANode> getChildren() {
100ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return Collections.unmodifiableCollection(mChildren.values());
101ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
102ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
103ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public OMANode getChild(String name) {
104ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return mChildren.get(name);
105ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
106ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
107ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public OMANode replaceNode(OMANode oldNode, OMANode newNode) {
108ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return mChildren.replace(oldNode.getName(), oldNode, newNode);
109ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
110ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
111ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public OMANode removeNode(String key, OMANode node) {
112ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (key.equals("?")) {
113ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return mChildren.remove(node);
114ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        } else {
115ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return mChildren.remove(key, node);
116ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
117ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
118ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
119ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
120ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public String getValue() {
121ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        throw new UnsupportedOperationException();
122ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
123ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
124ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
125ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public void toString(StringBuilder sb, int level) {
126ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sb.append(getPathString());
127ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (getContext() != null) {
128ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            sb.append(" (").append(getContext()).append(')');
129ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
130ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sb.append('\n');
131ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
132ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (OMANode node : mChildren.values()) {
133ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            node.toString(sb, level + 1);
134ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
135ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
136ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
137ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
138ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public void marshal(OutputStream out, int level) throws IOException {
139ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        OMAConstants.indent(level, out);
140ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        OMAConstants.serializeString(getName(), out);
141ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (getContext() != null) {
142ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            out.write(String.format("(%s)", getContext()).getBytes(StandardCharsets.UTF_8));
143ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
144ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        out.write(new byte[]{'+', '\n'});
145ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
146ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (OMANode child : mChildren.values()) {
147ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            child.marshal(out, level + 1);
148ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
149ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        OMAConstants.indent(level, out);
150ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        out.write(".\n".getBytes(StandardCharsets.UTF_8));
151ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
152ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
153ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
154ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public void fillPayload(StringBuilder sb) {
155ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (getContext() != null) {
156ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            sb.append('<').append(MOTree.RTPropTag).append(">\n");
157ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            sb.append('<').append(MOTree.TypeTag).append(">\n");
158ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            sb.append('<').append(MOTree.DDFNameTag).append(">");
159ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            sb.append(getContext());
160ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            sb.append("</").append(MOTree.DDFNameTag).append(">\n");
161ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            sb.append("</").append(MOTree.TypeTag).append(">\n");
162ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            sb.append("</").append(MOTree.RTPropTag).append(">\n");
163ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
164ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
165ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (OMANode child : getChildren()) {
166ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            child.toXml(sb);
167ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
168ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
169ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist}
170