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