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