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