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