package com.android.hotspot2.omadm; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; public abstract class OMANode { private final OMAConstructed mParent; private final String mName; private final String mContext; private final Map mAttributes; protected OMANode(OMAConstructed parent, String name, String context, Map avps) { mParent = parent; mName = name; mContext = context; mAttributes = avps; } protected static Map buildAttributes(String[] avps) { if (avps == null) { return null; } Map attributes = new HashMap<>(); for (int n = 0; n < avps.length; n += 2) { attributes.put(avps[n], avps[n + 1]); } return attributes; } protected Map getAttributes() { return mAttributes; } public OMAConstructed getParent() { return mParent; } public String getName() { return mName; } public String getContext() { return mContext; } public List getPath() { LinkedList path = new LinkedList<>(); for (OMANode node = this; node != null; node = node.getParent()) { path.addFirst(node.getName()); } return path; } public String getPathString() { StringBuilder sb = new StringBuilder(); for (String element : getPath()) { sb.append('/').append(element); } return sb.toString(); } public abstract OMANode reparent(OMAConstructed parent); public abstract String getScalarValue(Iterator path) throws OMAException; public abstract OMANode getListValue(Iterator path) throws OMAException; public abstract boolean isLeaf(); public abstract Collection getChildren(); public abstract OMANode getChild(String name) throws OMAException; public abstract String getValue(); public abstract OMANode addChild(String name, String context, String value, String path) throws IOException; public abstract void marshal(OutputStream out, int level) throws IOException; public abstract void toString(StringBuilder sb, int level); public abstract void fillPayload(StringBuilder sb); public void toXml(StringBuilder sb) { sb.append('<').append(MOTree.NodeTag); if (mAttributes != null && !mAttributes.isEmpty()) { for (Map.Entry avp : mAttributes.entrySet()) { sb.append(' ').append(avp.getKey()).append("=\"") .append(avp.getValue()).append('"'); } } sb.append(">\n"); sb.append('<').append(MOTree.NodeNameTag).append('>'); sb.append(getName()); sb.append("\n"); fillPayload(sb); sb.append("\n"); } @Override public String toString() { StringBuilder sb = new StringBuilder(); toString(sb, 0); return sb.toString(); } public static OMAConstructed unmarshal(InputStream in) throws IOException { OMANode node = buildNode(in, null); if (node == null || node.isLeaf()) { throw new IOException("Bad OMA tree"); } unmarshal(in, (OMAConstructed) node); return (OMAConstructed) node; } private static void unmarshal(InputStream in, OMAConstructed parent) throws IOException { for (; ; ) { OMANode node = buildNode(in, parent); if (node == null) { return; } else if (!node.isLeaf()) { unmarshal(in, (OMAConstructed) node); } } } private static OMANode buildNode(InputStream in, OMAConstructed parent) throws IOException { String name = OMAConstants.deserializeString(in); if (name == null) { return null; } String urn = null; int next = in.read(); if (next == '(') { urn = OMAConstants.readURN(in); next = in.read(); } if (next == '=') { String value = OMAConstants.deserializeString(in); return parent.addChild(name, urn, value, null); } else if (next == '+') { if (parent != null) { return parent.addChild(name, urn, null, null); } else { return new OMAConstructed(null, name, urn); } } else { throw new IOException("Parse error: expected = or + after node name"); } } }