package com.android.server.wifi.hotspot2.omadm; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Map; public class OMAConstructed extends OMANode { private final MultiValueMap mChildren; public OMAConstructed(OMAConstructed parent, String name, String context, String ... avps) { this(parent, name, context, new MultiValueMap(), buildAttributes(avps)); } protected OMAConstructed(OMAConstructed parent, String name, String context, MultiValueMap children, Map avps) { super(parent, name, context, avps); mChildren = children; } @Override public OMANode addChild(String name, String context, String value, String pathString) throws IOException { if (pathString == null) { OMANode child = value != null ? new OMAScalar(this, name, context, value) : new OMAConstructed(this, name, context); mChildren.put(name, child); return child; } else { OMANode target = this; while (target.getParent() != null) target = target.getParent(); for (String element : pathString.split("/")) { target = target.getChild(element); if (target == null) throw new IOException("No child node '" + element + "' in " + getPathString()); else if (target.isLeaf()) throw new IOException("Cannot add child to leaf node: " + getPathString()); } return target.addChild(name, context, value, null); } } @Override public OMAConstructed reparent(OMAConstructed parent) { return new OMAConstructed(parent, getName(), getContext(), mChildren, getAttributes()); } public void addChild(OMANode child) { mChildren.put(child.getName(), child.reparent(this)); } public String getScalarValue(Iterator path) throws OMAException { if (!path.hasNext()) { throw new OMAException("Path too short for " + getPathString()); } String tag = path.next(); OMANode child = mChildren.get(tag); if (child != null) { return child.getScalarValue(path); } else { return null; } } @Override public OMANode getListValue(Iterator path) throws OMAException { if (!path.hasNext()) { return null; } String tag = path.next(); OMANode child; if (tag.equals("?")) { child = mChildren.getSingletonValue(); } else { child = mChildren.get(tag); } if (child == null) { return null; } else if (path.hasNext()) { return child.getListValue(path); } else { return child; } } @Override public boolean isLeaf() { return false; } @Override public Collection getChildren() { return Collections.unmodifiableCollection(mChildren.values()); } public OMANode getChild(String name) { return mChildren.get(name); } public OMANode replaceNode(OMANode oldNode, OMANode newNode) { return mChildren.replace(oldNode.getName(), oldNode, newNode); } public OMANode removeNode(String key, OMANode node) { if (key.equals("?")) { return mChildren.remove(node); } else { return mChildren.remove(key, node); } } @Override public String getValue() { throw new UnsupportedOperationException(); } @Override public void toString(StringBuilder sb, int level) { sb.append(getPathString()); if (getContext() != null) { sb.append(" (").append(getContext()).append(')'); } sb.append('\n'); for (OMANode node : mChildren.values()) { node.toString(sb, level + 1); } } @Override public void marshal(OutputStream out, int level) throws IOException { OMAConstants.indent(level, out); OMAConstants.serializeString(getName(), out); if (getContext() != null) { out.write(String.format("(%s)", getContext()).getBytes(StandardCharsets.UTF_8)); } out.write(new byte[] { '+', '\n' }); for (OMANode child : mChildren.values()) { child.marshal(out, level + 1); } OMAConstants.indent(level, out); out.write(".\n".getBytes(StandardCharsets.UTF_8)); } @Override public void fillPayload(StringBuilder sb) { if (getContext() != null) { sb.append('<').append(MOTree.RTPropTag).append(">\n"); sb.append('<').append(MOTree.TypeTag).append(">\n"); sb.append('<').append(MOTree.DDFNameTag).append(">"); sb.append(getContext()); sb.append("\n"); sb.append("\n"); sb.append("\n"); } for (OMANode child : getChildren()) { child.toXml(sb); } } }