/**
 * Copyright (c) 2016, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.wifi.hotspot2.omadm;

import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;

import org.xml.sax.SAXException;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Utility class for converting OMA-DM (Open Mobile Alliance's Device Management)
 * PPS-MO (PerProviderSubscription Management Object) XML tree to a
 * {@link PasspointConfiguration} object.
 *
 * Currently this only supports PerProviderSubscription/HomeSP and
 * PerProviderSubscription/Credential subtree for Hotspot 2.0 Release 1 support.
 *
 * For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
 * Release 2 Technical Specification.
 *
 * Below is a sample XML string for a Release 1 PPS MO tree:
 *
 * <MgmtTree xmlns="syncml:dmddf1.2">
 *   <VerDTD>1.2</VerDTD>
 *   <Node>
 *     <NodeName>PerProviderSubscription</NodeName>
 *     <RTProperties>
 *       <Type>
 *         <DDFName>urn:wfa:mo:hotspot2dot0­perprovidersubscription:1.0</DDFName>
 *       </Type>
 *     </RTProperties>
 *     <Node>
 *       <NodeName>i001</NodeName>
 *       <Node>
 *         <NodeName>HomeSP</NodeName>
 *         <Node>
 *           <NodeName>FriendlyName</NodeName>
 *           <Value>Century House</Value>
 *         </Node>
 *         <Node>
 *           <NodeName>FQDN</NodeName>
 *           <Value>mi6.co.uk</Value>
 *         </Node>
 *         <Node>
 *           <NodeName>RoamingConsortiumOI</NodeName>
 *           <Value>112233,445566</Value>
 *         </Node>
 *       </Node>
 *       <Node>
 *         <NodeName>Credential</NodeName>
 *         <Node>
 *           <NodeName>Realm</NodeName>
 *           <Value>shaken.stirred.com</Value>
 *         </Node>
 *         <Node>
 *           <NodeName>UsernamePassword</NodeName>
 *           <Node>
 *             <NodeName>Username</NodeName>
 *             <Value>james</Value>
 *           </Node>
 *           <Node>
 *             <NodeName>Password</NodeName>
 *             <Value>Ym9uZDAwNw==</Value>
 *           </Node>
 *           <Node>
 *             <NodeName>EAPMethod</NodeName>
 *             <Node>
 *               <NodeName>EAPType</NodeName>
 *               <Value>21</Value>
 *             </Node>
 *             <Node>
 *               <NodeName>InnerMethod</NodeName>
 *               <Value>MS-CHAP-V2</Value>
 *             </Node>
 *           </Node>
 *         </Node>
 *       </Node>
 *     </Node>
 *   </Node>
 * </MgmtTree>
 */
public final class PpsMoParser {
    private static final String TAG = "PpsMoParser";

    /**
     * XML tags expected in the PPS MO (PerProviderSubscription Management Object) XML tree.
     */
    private static final String TAG_MANAGEMENT_TREE = "MgmtTree";
    private static final String TAG_VER_DTD = "VerDTD";
    private static final String TAG_NODE = "Node";
    private static final String TAG_NODE_NAME = "NodeName";
    private static final String TAG_RT_PROPERTIES = "RTProperties";
    private static final String TAG_TYPE = "Type";
    private static final String TAG_DDF_NAME = "DDFName";
    private static final String TAG_VALUE = "Value";

    /**
     * Name for PerProviderSubscription node.
     */
    private static final String NODE_PER_PROVIDER_SUBSCRIPTION = "PerProviderSubscription";

    /**
     * Fields under PerProviderSubscription.
     */
    private static final String NODE_UPDATE_IDENTIFIER = "UpdateIdentifier";
    private static final String NODE_AAA_SERVER_TRUST_ROOT = "AAAServerTrustRoot";
    private static final String NODE_SUBSCRIPTION_UPDATE = "SubscriptionUpdate";
    private static final String NODE_SUBSCRIPTION_PARAMETER = "SubscriptionParameters";
    private static final String NODE_TYPE_OF_SUBSCRIPTION = "TypeOfSubscription";
    private static final String NODE_USAGE_LIMITS = "UsageLimits";
    private static final String NODE_DATA_LIMIT = "DataLimit";
    private static final String NODE_START_DATE = "StartDate";
    private static final String NODE_TIME_LIMIT = "TimeLimit";
    private static final String NODE_USAGE_TIME_PERIOD = "UsageTimePeriod";
    private static final String NODE_CREDENTIAL_PRIORITY = "CredentialPriority";
    private static final String NODE_EXTENSION = "Extension";

    /**
     * Fields under Extension/Android subtree.
     */
    /*
     * This node is used to put Android specific extension nodes and must be put
     * under "Extension" node. Nodes with unknown names are allowed under this subtree.
     * If there is any new node added in later release, it won't break older release parsing.
     * <p>
     * Ex:
     * <Node>
     *   <NodeName>Extension</NodeName>
     *   <Node>
     *     <NodeName>Android</NodeName>
     *     <Node>
     *       <NodeName>AndroidSpecificAttribute</NodeName>
     *       <Value>AndroidSpecificValue</Value>
     *     </Node>
     *     <Node>
     *       <NodeName>AndroidSpecificAttribute2</NodeName>
     *       <Value>AndroidSpecificValue2</Value>
     *     </Node>
     *   </Node>
     * </Node>
     */
    private static final String NODE_VENDOR_ANDROID = "Android";
    /*
     * This node describes AAA server trusted names. The trusted name must be put in
     * a leaf named "FQDN". More than one trusted names can be provided by using
     * semicolons to separate the strings (e.g., example.org;example.com).
     * <p>
     * Ex:
     * <Node>
     *   <NodeName>AAAServerTrustedNames</NodeName>
     *   <Node>
     *     <NodeName>FQDN</NodeName>
     *     <Value>trusted.com;auth.net</Value>
     *  </Node>
     * <Node>
     */
    private static final String NODE_AAA_SERVER_TRUSTED_NAMES = "AAAServerTrustedNames";

    /**
     * Fields under HomeSP subtree.
     */
    private static final String NODE_HOMESP = "HomeSP";
    private static final String NODE_FQDN = "FQDN";
    private static final String NODE_FRIENDLY_NAME = "FriendlyName";
    private static final String NODE_ROAMING_CONSORTIUM_OI = "RoamingConsortiumOI";
    private static final String NODE_NETWORK_ID = "NetworkID";
    private static final String NODE_SSID = "SSID";
    private static final String NODE_HESSID = "HESSID";
    private static final String NODE_ICON_URL = "IconURL";
    private static final String NODE_HOME_OI_LIST = "HomeOIList";
    private static final String NODE_HOME_OI = "HomeOI";
    private static final String NODE_HOME_OI_REQUIRED = "HomeOIRequired";
    private static final String NODE_OTHER_HOME_PARTNERS = "OtherHomePartners";

    /**
     * Fields under Credential subtree.
     */
    private static final String NODE_CREDENTIAL = "Credential";
    private static final String NODE_CREATION_DATE = "CreationDate";
    private static final String NODE_EXPIRATION_DATE = "ExpirationDate";
    private static final String NODE_USERNAME_PASSWORD = "UsernamePassword";
    private static final String NODE_USERNAME = "Username";
    private static final String NODE_PASSWORD = "Password";
    private static final String NODE_MACHINE_MANAGED = "MachineManaged";
    private static final String NODE_SOFT_TOKEN_APP = "SoftTokenApp";
    private static final String NODE_ABLE_TO_SHARE = "AbleToShare";
    private static final String NODE_EAP_METHOD = "EAPMethod";
    private static final String NODE_EAP_TYPE = "EAPType";
    private static final String NODE_VENDOR_ID = "VendorId";
    private static final String NODE_VENDOR_TYPE = "VendorType";
    private static final String NODE_INNER_EAP_TYPE = "InnerEAPType";
    private static final String NODE_INNER_VENDOR_ID = "InnerVendorID";
    private static final String NODE_INNER_VENDOR_TYPE = "InnerVendorType";
    private static final String NODE_INNER_METHOD = "InnerMethod";
    private static final String NODE_DIGITAL_CERTIFICATE = "DigitalCertificate";
    private static final String NODE_CERTIFICATE_TYPE = "CertificateType";
    private static final String NODE_CERT_SHA256_FINGERPRINT = "CertSHA256Fingerprint";
    private static final String NODE_REALM = "Realm";
    private static final String NODE_SIM = "SIM";
    private static final String NODE_SIM_IMSI = "IMSI";
    private static final String NODE_CHECK_AAA_SERVER_CERT_STATUS = "CheckAAAServerCertStatus";

    /**
     * Fields under Policy subtree.
     */
    private static final String NODE_POLICY = "Policy";
    private static final String NODE_PREFERRED_ROAMING_PARTNER_LIST =
            "PreferredRoamingPartnerList";
    private static final String NODE_FQDN_MATCH = "FQDN_Match";
    private static final String NODE_PRIORITY = "Priority";
    private static final String NODE_COUNTRY = "Country";
    private static final String NODE_MIN_BACKHAUL_THRESHOLD = "MinBackhaulThreshold";
    private static final String NODE_NETWORK_TYPE = "NetworkType";
    private static final String NODE_DOWNLINK_BANDWIDTH = "DLBandwidth";
    private static final String NODE_UPLINK_BANDWIDTH = "ULBandwidth";
    private static final String NODE_POLICY_UPDATE = "PolicyUpdate";
    private static final String NODE_UPDATE_INTERVAL = "UpdateInterval";
    private static final String NODE_UPDATE_METHOD = "UpdateMethod";
    private static final String NODE_RESTRICTION = "Restriction";
    private static final String NODE_URI = "URI";
    private static final String NODE_TRUST_ROOT = "TrustRoot";
    private static final String NODE_CERT_URL = "CertURL";
    private static final String NODE_SP_EXCLUSION_LIST = "SPExclusionList";
    private static final String NODE_REQUIRED_PROTO_PORT_TUPLE = "RequiredProtoPortTuple";
    private static final String NODE_IP_PROTOCOL = "IPProtocol";
    private static final String NODE_PORT_NUMBER = "PortNumber";
    private static final String NODE_MAXIMUM_BSS_LOAD_VALUE = "MaximumBSSLoadValue";
    private static final String NODE_OTHER = "Other";

    /**
     * URN (Unique Resource Name) for PerProviderSubscription Management Object Tree.
     */
    private static final String PPS_MO_URN =
            "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0";

    /**
     * Exception for generic parsing errors.
     */
    private static class ParsingException extends Exception {
        public ParsingException(String message) {
            super(message);
        }
    }

    /**
     * Class representing a node within the PerProviderSubscription tree.
     * This is used to flatten out and eliminate the extra layering in the XMLNode tree,
     * to make the data parsing easier and cleaner.
     *
     * A PPSNode can be an internal or a leaf node, but not both.
     *
     */
    private static abstract class PPSNode {
        private final String mName;
        public PPSNode(String name) {
            mName = name;
        }

        /**
         * @return the name of the node
         */
        public String getName() {
            return mName;
        }

        /**
         * Applies for internal node only.
         *
         * @return the list of children nodes.
         */
        public abstract List<PPSNode> getChildren();

        /**
         * Applies for leaf node only.
         *
         * @return the string value of the node
         */
        public abstract String getValue();

        /**
         * @return a flag indicating if this is a leaf or an internal node
         */
        public abstract boolean isLeaf();
    }

    /**
     * Class representing a leaf node in a PPS (PerProviderSubscription) tree.
     */
    private static class LeafNode extends PPSNode {
        private final String mValue;
        public LeafNode(String nodeName, String value) {
            super(nodeName);
            mValue = value;
        }

        @Override
        public String getValue() {
            return mValue;
        }

        @Override
        public List<PPSNode> getChildren() {
            return null;
        }

        @Override
        public boolean isLeaf() {
            return true;
        }
    }

    /**
     * Class representing an internal node in a PPS (PerProviderSubscription) tree.
     */
    private static class InternalNode extends PPSNode {
        private final List<PPSNode> mChildren;
        public InternalNode(String nodeName, List<PPSNode> children) {
            super(nodeName);
            mChildren = children;
        }

        @Override
        public String getValue() {
            return null;
        }

        @Override
        public List<PPSNode> getChildren() {
            return mChildren;
        }

        @Override
        public boolean isLeaf() {
            return false;
        }
    }

    /**
     * @hide
     */
    public PpsMoParser() {}

    /**
     * Convert a XML string representation of a PPS MO (PerProviderSubscription
     * Management Object) tree to a {@link PasspointConfiguration} object.
     *
     * @param xmlString XML string representation of a PPS MO tree
     * @return {@link PasspointConfiguration} or null
     */
    public static PasspointConfiguration parseMoText(String xmlString) {
        // Convert the XML string to a XML tree.
        XMLParser xmlParser = new XMLParser();
        XMLNode root = null;
        try {
            root = xmlParser.parse(xmlString);
        } catch(IOException | SAXException e) {
            return null;
        }
        if (root == null) {
            return null;
        }

        // Verify root node is a "MgmtTree" node.
        if (root.getTag() != TAG_MANAGEMENT_TREE) {
            Log.e(TAG, "Root is not a MgmtTree");
            return null;
        }

        String verDtd = null;    // Used for detecting duplicate VerDTD element.
        PasspointConfiguration config = null;
        for (XMLNode child : root.getChildren()) {
            switch(child.getTag()) {
                case TAG_VER_DTD:
                    if (verDtd != null) {
                        Log.e(TAG, "Duplicate VerDTD element");
                        return null;
                    }
                    verDtd = child.getText();
                    break;
                case TAG_NODE:
                    if (config != null) {
                        Log.e(TAG, "Unexpected multiple Node element under MgmtTree");
                        return null;
                    }
                    try {
                        config = parsePpsNode(child);
                    } catch (ParsingException e) {
                        Log.e(TAG, e.getMessage());
                        return null;
                    }
                    break;
                default:
                    Log.e(TAG, "Unknown node: " + child.getTag());
                    return null;
            }
        }
        return config;
    }

    /**
     * Parse a PerProviderSubscription node. Below is the format of the XML tree (with
     * each XML element represent a node in the tree):
     *
     * <Node>
     *   <NodeName>PerProviderSubscription</NodeName>
     *   <RTProperties>
     *     ...
     *   </RTPProperties>
     *   <Node>
     *     <NodeName>UpdateIdentifier</NodeName>
     *     <Value>...</Value>
     *   </Node>
     *   <Node>
     *     ...
     *   </Node>
     * </Node>
     *
     * @param node XMLNode that contains PerProviderSubscription node.
     * @return PasspointConfiguration or null
     * @throws ParsingException
     */
    private static PasspointConfiguration parsePpsNode(XMLNode node)
            throws ParsingException {
        PasspointConfiguration config = null;
        String nodeName = null;
        int updateIdentifier = Integer.MIN_VALUE;
        for (XMLNode child : node.getChildren()) {
            switch (child.getTag()) {
                case TAG_NODE_NAME:
                    if (nodeName != null) {
                        throw new ParsingException("Duplicate NodeName: " + child.getText());
                    }
                    nodeName = child.getText();
                    if (!TextUtils.equals(nodeName, NODE_PER_PROVIDER_SUBSCRIPTION)) {
                        throw new ParsingException("Unexpected NodeName: " + nodeName);
                    }
                    break;
                case TAG_NODE:
                    // A node can be either an UpdateIdentifier node or a PerProviderSubscription
                    // instance node.  Flatten out the XML tree first by converting it to a PPS
                    // tree to reduce the complexity of the parsing code.
                    PPSNode ppsNodeRoot = buildPpsNode(child);
                    if (TextUtils.equals(ppsNodeRoot.getName(), NODE_UPDATE_IDENTIFIER)) {
                        if (updateIdentifier != Integer.MIN_VALUE) {
                            throw new ParsingException("Multiple node for UpdateIdentifier");
                        }
                        updateIdentifier = parseInteger(getPpsNodeValue(ppsNodeRoot));
                    } else {
                        // Only one PerProviderSubscription instance is expected and allowed.
                        if (config != null) {
                            throw new ParsingException("Multiple PPS instance");
                        }
                        config = parsePpsInstance(ppsNodeRoot);
                    }
                    break;
                case TAG_RT_PROPERTIES:
                    // Parse and verify URN stored in the RT (Run Time) Properties.
                    String urn = parseUrn(child);
                    if (!TextUtils.equals(urn, PPS_MO_URN)) {
                        throw new ParsingException("Unknown URN: " + urn);
                    }
                    break;
                default:
                    throw new ParsingException("Unknown tag under PPS node: " + child.getTag());
            }
        }
        if (config != null && updateIdentifier != Integer.MIN_VALUE) {
            config.setUpdateIdentifier(updateIdentifier);
        }
        return config;
    }

    /**
     * Parse the URN stored in the RTProperties. Below is the format of the RTPProperties node:
     *
     * <RTProperties>
     *   <Type>
     *     <DDFName>urn:...</DDFName>
     *   </Type>
     * </RTProperties>
     *
     * @param node XMLNode that contains RTProperties node.
     * @return URN String of URN.
     * @throws ParsingException
     */
    private static String parseUrn(XMLNode node) throws ParsingException {
        if (node.getChildren().size() != 1)
            throw new ParsingException("Expect RTPProperties node to only have one child");

        XMLNode typeNode = node.getChildren().get(0);
        if (typeNode.getChildren().size() != 1) {
            throw new ParsingException("Expect Type node to only have one child");
        }
        if (!TextUtils.equals(typeNode.getTag(), TAG_TYPE)) {
            throw new ParsingException("Unexpected tag for Type: " + typeNode.getTag());
        }

        XMLNode ddfNameNode = typeNode.getChildren().get(0);
        if (!ddfNameNode.getChildren().isEmpty()) {
            throw new ParsingException("Expect DDFName node to have no child");
        }
        if (!TextUtils.equals(ddfNameNode.getTag(), TAG_DDF_NAME)) {
            throw new ParsingException("Unexpected tag for DDFName: " + ddfNameNode.getTag());
        }

        return ddfNameNode.getText();
    }

    /**
     * Convert a XML tree represented by XMLNode to a PPS (PerProviderSubscription) instance tree
     * represented by PPSNode.  This flattens out the XML tree to allow easier and cleaner parsing
     * of the PPS configuration data.  Only three types of XML tag are expected: "NodeName",
     * "Node", and "Value".
     *
     * The original XML tree (each XML element represent a node):
     *
     * <Node>
     *   <NodeName>root</NodeName>
     *   <Node>
     *     <NodeName>child1</NodeName>
     *     <Value>value1</Value>
     *   </Node>
     *   <Node>
     *     <NodeName>child2</NodeName>
     *     <Node>
     *       <NodeName>grandchild1</NodeName>
     *       ...
     *     </Node>
     *   </Node>
     *   ...
     * </Node>
     *
     * The converted PPS tree:
     *
     * [root] --- [child1, value1]
     *   |
     *   ---------[child2] --------[grandchild1] --- ...
     *
     * @param node XMLNode pointed to the root of a XML tree
     * @return PPSNode pointing to the root of a PPS tree
     * @throws ParsingException
     */
    private static PPSNode buildPpsNode(XMLNode node) throws ParsingException {
        String nodeName = null;
        String nodeValue = null;
        List<PPSNode> childNodes = new ArrayList<PPSNode>();
        // Names of parsed child nodes, use for detecting multiple child nodes with the same name.
        Set<String> parsedNodes = new HashSet<String>();

        for (XMLNode child : node.getChildren()) {
            String tag = child.getTag();
            if (TextUtils.equals(tag, TAG_NODE_NAME)) {
                if (nodeName != null) {
                    throw new ParsingException("Duplicate NodeName node");
                }
                nodeName = child.getText();
            } else if (TextUtils.equals(tag, TAG_NODE)) {
                PPSNode ppsNode = buildPpsNode(child);
                if (parsedNodes.contains(ppsNode.getName())) {
                    throw new ParsingException("Duplicate node: " + ppsNode.getName());
                }
                parsedNodes.add(ppsNode.getName());
                childNodes.add(ppsNode);
            } else if (TextUtils.equals(tag, TAG_VALUE)) {
               if (nodeValue != null) {
                   throw new ParsingException("Duplicate Value node");
               }
               nodeValue = child.getText();
            } else {
                throw new ParsingException("Unknown tag: " + tag);
            }
        }

        if (nodeName == null) {
            throw new ParsingException("Invalid node: missing NodeName");
        }
        if (nodeValue == null && childNodes.size() == 0) {
            throw new ParsingException("Invalid node: " + nodeName +
                    " missing both value and children");
        }
        if (nodeValue != null && childNodes.size() > 0) {
            throw new ParsingException("Invalid node: " + nodeName +
                    " contained both value and children");
        }

        if (nodeValue != null) {
            return new LeafNode(nodeName, nodeValue);
        }
        return new InternalNode(nodeName, childNodes);
    }

    /**
     * Return the value of a PPSNode.  An exception will be thrown if the given node
     * is not a leaf node.
     *
     * @param node PPSNode to retrieve the value from
     * @return String representing the value of the node
     * @throws ParsingException
     */
    private static String getPpsNodeValue(PPSNode node) throws ParsingException {
        if (!node.isLeaf()) {
            throw new ParsingException("Cannot get value from a non-leaf node: " + node.getName());
        }
        return node.getValue();
    }

    /**
     * Parse a PPS (PerProviderSubscription) configurations from a PPS tree.
     *
     * @param root PPSNode representing the root of the PPS tree
     * @return PasspointConfiguration
     * @throws ParsingException
     */
    private static PasspointConfiguration parsePpsInstance(PPSNode root)
            throws ParsingException {
        if (root.isLeaf()) {
            throw new ParsingException("Leaf node not expected for PPS instance");
        }

        PasspointConfiguration config = new PasspointConfiguration();
        for (PPSNode child : root.getChildren()) {
            switch(child.getName()) {
                case NODE_HOMESP:
                    config.setHomeSp(parseHomeSP(child));
                    break;
                case NODE_CREDENTIAL:
                    config.setCredential(parseCredential(child));
                    break;
                case NODE_POLICY:
                    config.setPolicy(parsePolicy(child));
                    break;
                case NODE_AAA_SERVER_TRUST_ROOT:
                    config.setTrustRootCertList(parseAAAServerTrustRootList(child));
                    break;
                case NODE_SUBSCRIPTION_UPDATE:
                    config.setSubscriptionUpdate(parseUpdateParameter(child));
                    break;
                case NODE_SUBSCRIPTION_PARAMETER:
                    parseSubscriptionParameter(child, config);
                    break;
                case NODE_CREDENTIAL_PRIORITY:
                    config.setCredentialPriority(parseInteger(getPpsNodeValue(child)));
                    break;
                case NODE_EXTENSION:
                    // All vendor specific information will be under this node.
                    parseExtension(child, config);
                    break;
                default:
                    throw new ParsingException("Unknown node: " + child.getName());
            }
        }
        return config;
    }

    /**
     * Parse configurations under PerProviderSubscription/HomeSP subtree.
     *
     * @param node PPSNode representing the root of the PerProviderSubscription/HomeSP subtree
     * @return HomeSP
     * @throws ParsingException
     */
    private static HomeSp parseHomeSP(PPSNode node) throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for HomeSP");
        }

        HomeSp homeSp = new HomeSp();
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_FQDN:
                    homeSp.setFqdn(getPpsNodeValue(child));
                    break;
                case NODE_FRIENDLY_NAME:
                    homeSp.setFriendlyName(getPpsNodeValue(child));
                    break;
                case NODE_ROAMING_CONSORTIUM_OI:
                    homeSp.setRoamingConsortiumOis(
                            parseRoamingConsortiumOI(getPpsNodeValue(child)));
                    break;
                case NODE_ICON_URL:
                    homeSp.setIconUrl(getPpsNodeValue(child));
                    break;
                case NODE_NETWORK_ID:
                    homeSp.setHomeNetworkIds(parseNetworkIds(child));
                    break;
                case NODE_HOME_OI_LIST:
                    Pair<List<Long>, List<Long>> homeOIs = parseHomeOIList(child);
                    homeSp.setMatchAllOis(convertFromLongList(homeOIs.first));
                    homeSp.setMatchAnyOis(convertFromLongList(homeOIs.second));
                    break;
                case NODE_OTHER_HOME_PARTNERS:
                    homeSp.setOtherHomePartners(parseOtherHomePartners(child));
                    break;
                default:
                    throw new ParsingException("Unknown node under HomeSP: " + child.getName());
            }
        }
        return homeSp;
    }

    /**
     * Parse the roaming consortium OI string, which contains a list of OIs separated by ",".
     *
     * @param oiStr string containing list of OIs (Organization Identifiers) separated by ","
     * @return long[]
     * @throws ParsingException
     */
    private static long[] parseRoamingConsortiumOI(String oiStr)
            throws ParsingException {
        String[] oiStrArray = oiStr.split(",");
        long[] oiArray = new long[oiStrArray.length];
        for (int i = 0; i < oiStrArray.length; i++) {
            oiArray[i] = parseLong(oiStrArray[i], 16);
        }
        return oiArray;
    }

    /**
     * Parse configurations under PerProviderSubscription/HomeSP/NetworkID subtree.
     *
     * @param node PPSNode representing the root of the PerProviderSubscription/HomeSP/NetworkID
     *             subtree
     * @return HashMap<String, Long> representing list of <SSID, HESSID> pair.
     * @throws ParsingException
     */
    static private Map<String, Long> parseNetworkIds(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for NetworkID");
        }

        Map<String, Long> networkIds = new HashMap<>();
        for (PPSNode child : node.getChildren()) {
            Pair<String, Long> networkId = parseNetworkIdInstance(child);
            networkIds.put(networkId.first, networkId.second);
        }
        return networkIds;
    }

    /**
     * Parse configurations under PerProviderSubscription/HomeSP/NetworkID/<X+> subtree.
     * The instance name (<X+>) is irrelevant and must be unique for each instance, which
     * is verified when the PPS tree is constructed {@link #buildPpsNode}.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/HomeSP/NetworkID/<X+> subtree
     * @return Pair<String, Long> representing <SSID, HESSID> pair.
     * @throws ParsingException
     */
    static private Pair<String, Long> parseNetworkIdInstance(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for NetworkID instance");
        }

        String ssid = null;
        Long hessid = null;
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_SSID:
                    ssid = getPpsNodeValue(child);
                    break;
                case NODE_HESSID:
                    hessid = parseLong(getPpsNodeValue(child), 16);
                    break;
                default:
                    throw new ParsingException("Unknown node under NetworkID instance: " +
                            child.getName());
            }
        }
        if (ssid == null)
            throw new ParsingException("NetworkID instance missing SSID");

        return new Pair<String, Long>(ssid, hessid);
    }

    /**
     * Parse configurations under PerProviderSubscription/HomeSP/HomeOIList subtree.
     *
     * @param node PPSNode representing the root of the PerProviderSubscription/HomeSP/HomeOIList
     *             subtree
     * @return Pair<List<Long>, List<Long>> containing both MatchAllOIs and MatchAnyOIs list.
     * @throws ParsingException
     */
    private static Pair<List<Long>, List<Long>> parseHomeOIList(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for HomeOIList");
        }

        List<Long> matchAllOIs = new ArrayList<Long>();
        List<Long> matchAnyOIs = new ArrayList<Long>();
        for (PPSNode child : node.getChildren()) {
            Pair<Long, Boolean> homeOI = parseHomeOIInstance(child);
            if (homeOI.second.booleanValue()) {
                matchAllOIs.add(homeOI.first);
            } else {
                matchAnyOIs.add(homeOI.first);
            }
        }
        return new Pair<List<Long>, List<Long>>(matchAllOIs, matchAnyOIs);
    }

    /**
     * Parse configurations under PerProviderSubscription/HomeSP/HomeOIList/<X+> subtree.
     * The instance name (<X+>) is irrelevant and must be unique for each instance, which
     * is verified when the PPS tree is constructed {@link #buildPpsNode}.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/HomeSP/HomeOIList/<X+> subtree
     * @return Pair<Long, Boolean> containing a HomeOI and a HomeOIRequired flag
     * @throws ParsingException
     */
    private static Pair<Long, Boolean> parseHomeOIInstance(PPSNode node) throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for HomeOI instance");
        }

        Long oi = null;
        Boolean required = null;
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_HOME_OI:
                    try {
                        oi = Long.valueOf(getPpsNodeValue(child), 16);
                    } catch (NumberFormatException e) {
                        throw new ParsingException("Invalid HomeOI: " + getPpsNodeValue(child));
                    }
                    break;
                case NODE_HOME_OI_REQUIRED:
                    required = Boolean.valueOf(getPpsNodeValue(child));
                    break;
                default:
                    throw new ParsingException("Unknown node under NetworkID instance: " +
                            child.getName());
            }
        }
        if (oi == null) {
            throw new ParsingException("HomeOI instance missing OI field");
        }
        if (required == null) {
            throw new ParsingException("HomeOI instance missing required field");
        }
        return new Pair<Long, Boolean>(oi, required);
    }

    /**
     * Parse configurations under PerProviderSubscription/HomeSP/OtherHomePartners subtree.
     * This contains a list of FQDN (Fully Qualified Domain Name) that are considered
     * home partners.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/HomeSP/OtherHomePartners subtree
     * @return String[] list of partner's FQDN
     * @throws ParsingException
     */
    private static String[] parseOtherHomePartners(PPSNode node) throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for OtherHomePartners");
        }
        List<String> otherHomePartners = new ArrayList<String>();
        for (PPSNode child : node.getChildren()) {
            String fqdn = parseOtherHomePartnerInstance(child);
            otherHomePartners.add(fqdn);
        }
        return otherHomePartners.toArray(new String[otherHomePartners.size()]);
    }

    /**
     * Parse configurations under PerProviderSubscription/HomeSP/OtherHomePartners/<X+> subtree.
     * The instance name (<X+>) is irrelevant and must be unique for each instance, which
     * is verified when the PPS tree is constructed {@link #buildPpsNode}.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/HomeSP/OtherHomePartners/<X+> subtree
     * @return String FQDN of the partner
     * @throws ParsingException
     */
    private static String parseOtherHomePartnerInstance(PPSNode node) throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for OtherHomePartner instance");
        }
        String fqdn = null;
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_FQDN:
                    fqdn = getPpsNodeValue(child);
                    break;
                default:
                    throw new ParsingException(
                            "Unknown node under OtherHomePartner instance: " + child.getName());
            }
        }
        if (fqdn == null) {
            throw new ParsingException("OtherHomePartner instance missing FQDN field");
        }
        return fqdn;
    }

    /**
     * Parse configurations under PerProviderSubscription/Credential subtree.
     *
     * @param node PPSNode representing the root of the PerProviderSubscription/Credential subtree
     * @return Credential
     * @throws ParsingException
     */
    private static Credential parseCredential(PPSNode node) throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for HomeSP");
        }

        Credential credential = new Credential();
        for (PPSNode child: node.getChildren()) {
            switch (child.getName()) {
                case NODE_CREATION_DATE:
                    credential.setCreationTimeInMillis(parseDate(getPpsNodeValue(child)));
                    break;
                case NODE_EXPIRATION_DATE:
                    credential.setExpirationTimeInMillis(parseDate(getPpsNodeValue(child)));
                    break;
                case NODE_USERNAME_PASSWORD:
                    credential.setUserCredential(parseUserCredential(child));
                    break;
                case NODE_DIGITAL_CERTIFICATE:
                    credential.setCertCredential(parseCertificateCredential(child));
                    break;
                case NODE_REALM:
                    credential.setRealm(getPpsNodeValue(child));
                    break;
                case NODE_CHECK_AAA_SERVER_CERT_STATUS:
                    credential.setCheckAaaServerCertStatus(
                            Boolean.parseBoolean(getPpsNodeValue(child)));
                    break;
                case NODE_SIM:
                    credential.setSimCredential(parseSimCredential(child));
                    break;
                default:
                    throw new ParsingException("Unknown node under Credential: " +
                            child.getName());
            }
        }
        return credential;
    }

    /**
     * Parse configurations under PerProviderSubscription/Credential/UsernamePassword subtree.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Credential/UsernamePassword subtree
     * @return Credential.UserCredential
     * @throws ParsingException
     */
    private static Credential.UserCredential parseUserCredential(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for UsernamePassword");
        }

        Credential.UserCredential userCred = new Credential.UserCredential();
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_USERNAME:
                    userCred.setUsername(getPpsNodeValue(child));
                    break;
                case NODE_PASSWORD:
                    userCred.setPassword(getPpsNodeValue(child));
                    break;
                case NODE_MACHINE_MANAGED:
                    userCred.setMachineManaged(Boolean.parseBoolean(getPpsNodeValue(child)));
                    break;
                case NODE_SOFT_TOKEN_APP:
                    userCred.setSoftTokenApp(getPpsNodeValue(child));
                    break;
                case NODE_ABLE_TO_SHARE:
                    userCred.setAbleToShare(Boolean.parseBoolean(getPpsNodeValue(child)));
                    break;
                case NODE_EAP_METHOD:
                    parseEAPMethod(child, userCred);
                    break;
                default:
                    throw new ParsingException("Unknown node under UsernamPassword: " +
                            child.getName());
            }
        }
        return userCred;
    }

    /**
     * Parse configurations under PerProviderSubscription/Credential/UsernamePassword/EAPMethod
     * subtree.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Credential/UsernamePassword/EAPMethod subtree
     * @param userCred UserCredential to be updated with EAP method values.
     * @throws ParsingException
     */
    private static void parseEAPMethod(PPSNode node, Credential.UserCredential userCred)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for EAPMethod");
        }

        for (PPSNode child : node.getChildren()) {
            switch(child.getName()) {
                case NODE_EAP_TYPE:
                    userCred.setEapType(parseInteger(getPpsNodeValue(child)));
                    break;
                case NODE_INNER_METHOD:
                    userCred.setNonEapInnerMethod(getPpsNodeValue(child));
                    break;
                case NODE_VENDOR_ID:
                case NODE_VENDOR_TYPE:
                case NODE_INNER_EAP_TYPE:
                case NODE_INNER_VENDOR_ID:
                case NODE_INNER_VENDOR_TYPE:
                    // Only EAP-TTLS is currently supported for user credential, which doesn't
                    // use any of these parameters.
                    Log.d(TAG, "Ignore unsupported EAP method parameter: " + child.getName());
                    break;
                default:
                    throw new ParsingException("Unknown node under EAPMethod: " + child.getName());
            }
        }
    }

    /**
     * Parse configurations under PerProviderSubscription/Credential/DigitalCertificate subtree.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Credential/DigitalCertificate subtree
     * @return Credential.CertificateCredential
     * @throws ParsingException
     */
    private static Credential.CertificateCredential parseCertificateCredential(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for DigitalCertificate");
        }

        Credential.CertificateCredential certCred = new Credential.CertificateCredential();
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_CERTIFICATE_TYPE:
                    certCred.setCertType(getPpsNodeValue(child));
                    break;
                case NODE_CERT_SHA256_FINGERPRINT:
                    certCred.setCertSha256Fingerprint(parseHexString(getPpsNodeValue(child)));
                    break;
                default:
                    throw new ParsingException("Unknown node under DigitalCertificate: " +
                            child.getName());
            }
        }
        return certCred;
    }

    /**
     * Parse configurations under PerProviderSubscription/Credential/SIM subtree.
     *
     * @param node PPSNode representing the root of the PerProviderSubscription/Credential/SIM
     *             subtree
     * @return Credential.SimCredential
     * @throws ParsingException
     */
    private static Credential.SimCredential parseSimCredential(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for SIM");
        }

        Credential.SimCredential simCred = new Credential.SimCredential();
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_SIM_IMSI:
                    simCred.setImsi(getPpsNodeValue(child));
                    break;
                case NODE_EAP_TYPE:
                    simCred.setEapType(parseInteger(getPpsNodeValue(child)));
                    break;
                default:
                    throw new ParsingException("Unknown node under SIM: " + child.getName());
            }
        }
        return simCred;
    }

    /**
     * Parse configurations under PerProviderSubscription/Policy subtree.
     *
     * @param node PPSNode representing the root of the PerProviderSubscription/Policy subtree
     * @return {@link Policy}
     * @throws ParsingException
     */
    private static Policy parsePolicy(PPSNode node) throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for Policy");
        }

        Policy policy = new Policy();
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_PREFERRED_ROAMING_PARTNER_LIST:
                    policy.setPreferredRoamingPartnerList(parsePreferredRoamingPartnerList(child));
                    break;
                case NODE_MIN_BACKHAUL_THRESHOLD:
                    parseMinBackhaulThreshold(child, policy);
                    break;
                case NODE_POLICY_UPDATE:
                    policy.setPolicyUpdate(parseUpdateParameter(child));
                    break;
                case NODE_SP_EXCLUSION_LIST:
                    policy.setExcludedSsidList(parseSpExclusionList(child));
                    break;
                case NODE_REQUIRED_PROTO_PORT_TUPLE:
                    policy.setRequiredProtoPortMap(parseRequiredProtoPortTuple(child));
                    break;
                case NODE_MAXIMUM_BSS_LOAD_VALUE:
                    policy.setMaximumBssLoadValue(parseInteger(getPpsNodeValue(child)));
                    break;
                default:
                    throw new ParsingException("Unknown node under Policy: " + child.getName());
            }
        }
        return policy;
    }

    /**
     * Parse configurations under PerProviderSubscription/Policy/PreferredRoamingPartnerList
     * subtree.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Policy/PreferredRoamingPartnerList subtree
     * @return List of {@link Policy#RoamingPartner}
     * @throws ParsingException
     */
    private static List<Policy.RoamingPartner> parsePreferredRoamingPartnerList(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for PreferredRoamingPartnerList");
        }
        List<Policy.RoamingPartner> partnerList = new ArrayList<>();
        for (PPSNode child : node.getChildren()) {
            partnerList.add(parsePreferredRoamingPartner(child));
        }
        return partnerList;
    }

    /**
     * Parse configurations under PerProviderSubscription/Policy/PreferredRoamingPartnerList/<X+>
     * subtree.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Policy/PreferredRoamingPartnerList/<X+> subtree
     * @return {@link Policy#RoamingPartner}
     * @throws ParsingException
     */
    private static Policy.RoamingPartner parsePreferredRoamingPartner(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for PreferredRoamingPartner "
                    + "instance");
        }

        Policy.RoamingPartner roamingPartner = new Policy.RoamingPartner();
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_FQDN_MATCH:
                    // FQDN_Match field is in the format of "[FQDN],[MatchInfo]", where [MatchInfo]
                    // is either "exactMatch" for exact match of FQDN or "includeSubdomains" for
                    // matching all FQDNs with the same sub-domain.
                    String fqdnMatch = getPpsNodeValue(child);
                    String[] fqdnMatchArray = fqdnMatch.split(",");
                    if (fqdnMatchArray.length != 2) {
                        throw new ParsingException("Invalid FQDN_Match: " + fqdnMatch);
                    }
                    roamingPartner.setFqdn(fqdnMatchArray[0]);
                    if (TextUtils.equals(fqdnMatchArray[1], "exactMatch")) {
                        roamingPartner.setFqdnExactMatch(true);
                    } else if (TextUtils.equals(fqdnMatchArray[1], "includeSubdomains")) {
                        roamingPartner.setFqdnExactMatch(false);
                    } else {
                        throw new ParsingException("Invalid FQDN_Match: " + fqdnMatch);
                    }
                    break;
                case NODE_PRIORITY:
                    roamingPartner.setPriority(parseInteger(getPpsNodeValue(child)));
                    break;
                case NODE_COUNTRY:
                    roamingPartner.setCountries(getPpsNodeValue(child));
                    break;
                default:
                    throw new ParsingException("Unknown node under PreferredRoamingPartnerList "
                            + "instance " + child.getName());
            }
        }
        return roamingPartner;
    }

    /**
     * Parse configurations under PerProviderSubscription/Policy/MinBackhaulThreshold subtree
     * into the given policy.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Policy/MinBackhaulThreshold subtree
     * @param policy The policy to store the MinBackhualThreshold configuration
     * @throws ParsingException
     */
    private static void parseMinBackhaulThreshold(PPSNode node, Policy policy)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for MinBackhaulThreshold");
        }
        for (PPSNode child : node.getChildren()) {
            parseMinBackhaulThresholdInstance(child, policy);
        }
    }

    /**
     * Parse configurations under PerProviderSubscription/Policy/MinBackhaulThreshold/<X+> subtree
     * into the given policy.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Policy/MinBackhaulThreshold/<X+> subtree
     * @param policy The policy to store the MinBackhaulThreshold configuration
     * @throws ParsingException
     */
    private static void parseMinBackhaulThresholdInstance(PPSNode node, Policy policy)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for MinBackhaulThreshold instance");
        }
        String networkType = null;
        long downlinkBandwidth = Long.MIN_VALUE;
        long uplinkBandwidth = Long.MIN_VALUE;
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_NETWORK_TYPE:
                    networkType = getPpsNodeValue(child);
                    break;
                case NODE_DOWNLINK_BANDWIDTH:
                    downlinkBandwidth = parseLong(getPpsNodeValue(child), 10);
                    break;
                case NODE_UPLINK_BANDWIDTH:
                    uplinkBandwidth = parseLong(getPpsNodeValue(child), 10);
                    break;
                default:
                    throw new ParsingException("Unknown node under MinBackhaulThreshold instance "
                            + child.getName());
            }
        }
        if (networkType == null) {
            throw new ParsingException("Missing NetworkType field");
        }

        if (TextUtils.equals(networkType, "home")) {
            policy.setMinHomeDownlinkBandwidth(downlinkBandwidth);
            policy.setMinHomeUplinkBandwidth(uplinkBandwidth);
        } else if (TextUtils.equals(networkType, "roaming")) {
            policy.setMinRoamingDownlinkBandwidth(downlinkBandwidth);
            policy.setMinRoamingUplinkBandwidth(uplinkBandwidth);
        } else {
            throw new ParsingException("Invalid network type: " + networkType);
        }
    }

    /**
     * Parse update parameters. This contained configurations from either
     * PerProviderSubscription/Policy/PolicyUpdate or PerProviderSubscription/SubscriptionUpdate
     * subtree.
     *
     * @param node PPSNode representing the root of the PerProviderSubscription/Policy/PolicyUpdate
     *             or PerProviderSubscription/SubscriptionUpdate subtree
     * @return {@link UpdateParameter}
     * @throws ParsingException
     */
    private static UpdateParameter parseUpdateParameter(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for Update Parameters");
        }

        UpdateParameter updateParam = new UpdateParameter();
        for (PPSNode child : node.getChildren()) {
            switch(child.getName()) {
                case NODE_UPDATE_INTERVAL:
                    updateParam.setUpdateIntervalInMinutes(parseLong(getPpsNodeValue(child), 10));
                    break;
                case NODE_UPDATE_METHOD:
                    updateParam.setUpdateMethod(getPpsNodeValue(child));
                    break;
                case NODE_RESTRICTION:
                    updateParam.setRestriction(getPpsNodeValue(child));
                    break;
                case NODE_URI:
                    updateParam.setServerUri(getPpsNodeValue(child));
                    break;
                case NODE_USERNAME_PASSWORD:
                    Pair<String, String> usernamePassword = parseUpdateUserCredential(child);
                    updateParam.setUsername(usernamePassword.first);
                    updateParam.setBase64EncodedPassword(usernamePassword.second);
                    break;
                case NODE_TRUST_ROOT:
                    Pair<String, byte[]> trustRoot = parseTrustRoot(child);
                    updateParam.setTrustRootCertUrl(trustRoot.first);
                    updateParam.setTrustRootCertSha256Fingerprint(trustRoot.second);
                    break;
                case NODE_OTHER:
                    Log.d(TAG, "Ignore unsupported paramter: " + child.getName());
                    break;
                default:
                    throw new ParsingException("Unknown node under Update Parameters: "
                            + child.getName());
            }
        }
        return updateParam;
    }

    /**
     * Parse username and password parameters associated with policy or subscription update.
     * This contained configurations under either
     * PerProviderSubscription/Policy/PolicyUpdate/UsernamePassword or
     * PerProviderSubscription/SubscriptionUpdate/UsernamePassword subtree.
     *
     * @param node PPSNode representing the root of the UsernamePassword subtree
     * @return Pair of username and password
     * @throws ParsingException
     */
    private static Pair<String, String> parseUpdateUserCredential(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for UsernamePassword");
        }

        String username = null;
        String password = null;
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_USERNAME:
                    username = getPpsNodeValue(child);
                    break;
                case NODE_PASSWORD:
                    password = getPpsNodeValue(child);
                    break;
                default:
                    throw new ParsingException("Unknown node under UsernamePassword: "
                            + child.getName());
            }
        }
        return Pair.create(username, password);
    }

    /**
     * Parse the trust root parameters associated with policy update, subscription update, or AAA
     * server trust root.
     *
     * This contained configurations under either
     * PerProviderSubscription/Policy/PolicyUpdate/TrustRoot or
     * PerProviderSubscription/SubscriptionUpdate/TrustRoot or
     * PerProviderSubscription/AAAServerTrustRoot/<X+> subtree.
     *
     * @param node PPSNode representing the root of the TrustRoot subtree
     * @return Pair of Certificate URL and fingerprint
     * @throws ParsingException
     */
    private static Pair<String, byte[]> parseTrustRoot(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for TrustRoot");
        }

        String certUrl = null;
        byte[] certFingerprint = null;
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_CERT_URL:
                    certUrl = getPpsNodeValue(child);
                    break;
                case NODE_CERT_SHA256_FINGERPRINT:
                    certFingerprint = parseHexString(getPpsNodeValue(child));
                    break;
                default:
                    throw new ParsingException("Unknown node under TrustRoot: "
                            + child.getName());
            }
        }
        return Pair.create(certUrl, certFingerprint);
    }

    /**
     * Parse configurations under PerProviderSubscription/Policy/SPExclusionList subtree.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Policy/SPExclusionList subtree
     * @return Array of excluded SSIDs
     * @throws ParsingException
     */
    private static String[] parseSpExclusionList(PPSNode node) throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for SPExclusionList");
        }
        List<String> ssidList = new ArrayList<>();
        for (PPSNode child : node.getChildren()) {
            ssidList.add(parseSpExclusionInstance(child));
        }
        return ssidList.toArray(new String[ssidList.size()]);
    }

    /**
     * Parse configurations under PerProviderSubscription/Policy/SPExclusionList/<X+> subtree.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Policy/SPExclusionList/<X+> subtree
     * @return String
     * @throws ParsingException
     */
    private static String parseSpExclusionInstance(PPSNode node) throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for SPExclusion instance");
        }
        String ssid = null;
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_SSID:
                    ssid = getPpsNodeValue(child);
                    break;
                default:
                    throw new ParsingException("Unknown node under SPExclusion instance");
            }
        }
        return ssid;
    }

    /**
     * Parse configurations under PerProviderSubscription/Policy/RequiredProtoPortTuple subtree.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Policy/RequiredProtoPortTuple subtree
     * @return Map of IP Protocol to Port Number tuples
     * @throws ParsingException
     */
    private static Map<Integer, String> parseRequiredProtoPortTuple(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for RequiredProtoPortTuple");
        }
        Map<Integer, String> protoPortTupleMap = new HashMap<>();
        for (PPSNode child : node.getChildren()) {
            Pair<Integer, String> protoPortTuple = parseProtoPortTuple(child);
            protoPortTupleMap.put(protoPortTuple.first, protoPortTuple.second);
        }
        return protoPortTupleMap;
    }

    /**
     * Parse configurations under PerProviderSubscription/Policy/RequiredProtoPortTuple/<X+>
     * subtree.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Policy/RequiredProtoPortTuple/<X+> subtree
     * @return Pair of IP Protocol to Port Number tuple
     * @throws ParsingException
     */
    private static Pair<Integer, String> parseProtoPortTuple(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for RequiredProtoPortTuple "
                    + "instance");
        }
        int proto = Integer.MIN_VALUE;
        String ports = null;
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_IP_PROTOCOL:
                    proto = parseInteger(getPpsNodeValue(child));
                    break;
                case NODE_PORT_NUMBER:
                    ports = getPpsNodeValue(child);
                    break;
                default:
                    throw new ParsingException("Unknown node under RequiredProtoPortTuple instance"
                            + child.getName());
            }
        }
        if (proto == Integer.MIN_VALUE) {
            throw new ParsingException("Missing IPProtocol field");
        }
        if (ports == null) {
            throw new ParsingException("Missing PortNumber field");
        }
        return Pair.create(proto, ports);
    }

    /**
     * Parse configurations under PerProviderSubscription/AAAServerTrustRoot subtree.
     *
     * @param node PPSNode representing the root of PerProviderSubscription/AAAServerTrustRoot
     *             subtree
     * @return Map of certificate URL with the corresponding certificate fingerprint
     * @throws ParsingException
     */
    private static Map<String, byte[]> parseAAAServerTrustRootList(PPSNode node)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for AAAServerTrustRoot");
        }
        Map<String, byte[]> certList = new HashMap<>();
        for (PPSNode child : node.getChildren()) {
            Pair<String, byte[]> certTuple = parseTrustRoot(child);
            certList.put(certTuple.first, certTuple.second);
        }
        return certList;
    }

    /**
     * Parse configurations under PerProviderSubscription/SubscriptionParameter subtree.
     *
     * @param node PPSNode representing the root of PerProviderSubscription/SubscriptionParameter
     *             subtree
     * @param config Instance of {@link PasspointConfiguration}
     * @throws ParsingException
     */
    private static void parseSubscriptionParameter(PPSNode node, PasspointConfiguration config)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for SubscriptionParameter");
        }
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_CREATION_DATE:
                    config.setSubscriptionCreationTimeInMillis(parseDate(getPpsNodeValue(child)));
                    break;
                case NODE_EXPIRATION_DATE:
                    config.setSubscriptionExpirationTimeInMillis(parseDate(getPpsNodeValue(child)));
                    break;
                case NODE_TYPE_OF_SUBSCRIPTION:
                    config.setSubscriptionType(getPpsNodeValue(child));
                    break;
                case NODE_USAGE_LIMITS:
                    parseUsageLimits(child, config);
                    break;
                default:
                    throw new ParsingException("Unknown node under SubscriptionParameter"
                            + child.getName());
            }
        }
    }

    /**
     * Parse configurations under PerProviderSubscription/SubscriptionParameter/UsageLimits
     * subtree.
     *
     * @param node PPSNode representing the root of
     *             PerProviderSubscription/SubscriptionParameter/UsageLimits subtree
     * @param config Instance of {@link PasspointConfiguration}
     * @throws ParsingException
     */
    private static void parseUsageLimits(PPSNode node, PasspointConfiguration config)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for UsageLimits");
        }
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_DATA_LIMIT:
                    config.setUsageLimitDataLimit(parseLong(getPpsNodeValue(child), 10));
                    break;
                case NODE_START_DATE:
                    config.setUsageLimitStartTimeInMillis(parseDate(getPpsNodeValue(child)));
                    break;
                case NODE_TIME_LIMIT:
                    config.setUsageLimitTimeLimitInMinutes(parseLong(getPpsNodeValue(child), 10));
                    break;
                case NODE_USAGE_TIME_PERIOD:
                    config.setUsageLimitUsageTimePeriodInMinutes(
                            parseLong(getPpsNodeValue(child), 10));
                    break;
                default:
                    throw new ParsingException("Unknown node under UsageLimits"
                            + child.getName());
            }
        }
    }

    /**
     * Parse configurations under PerProviderSubscription/Extension/Android/AAAServerTrustedNames
     * subtree.
     *
     * @param node PPSNode representing the root of the
     *             PerProviderSubscription/Extension/Android/AAAServerTrustedNames subtree
     * @return String[] list of trusted name
     * @throws ParsingException
     */
    private static String[] parseAaaServerTrustedNames(PPSNode node) throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for AAAServerTrustedNames instance");
        }
        String fqdnListStr = null;
        String[] fqdnListArray = null;
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_FQDN:
                    fqdnListStr = getPpsNodeValue(child);
                    fqdnListArray = fqdnListStr.split(";");
                    break;
                default:
                    throw new ParsingException(
                            "Unknown node under AAAServerTrustedNames instance: "
                            + child.getName());
            }
        }
        if (fqdnListArray == null) {
            throw new ParsingException("AAAServerTrustedNames instance missing FQDN field");
        }

        return fqdnListArray;
    }

    /**
     * Parse configurations under PerProviderSubscription/Extension/Android subtree.
     *
     * @param node PPSNode representing the root of PerProviderSubscription/Extension
     *             subtree
     * @param config Instance of {@link PasspointConfiguration}
     * @throws ParsingException
     */
    private static void parseVendorAndroidExtension(PPSNode node, PasspointConfiguration config)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for Extension");
        }
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_AAA_SERVER_TRUSTED_NAMES:
                    config.setAaaServerTrustedNames(parseAaaServerTrustedNames(child));
                    break;
                default:
                    // Don't raise an exception for unknown nodes to avoid breaking old release
                    Log.w(TAG, "Unknown node under Android Extension: " + child.getName());
            }
        }
    }

    /**
     * Parse configurations under PerProviderSubscription/Extension subtree.
     *
     * @param node PPSNode representing the root of PerProviderSubscription/Extension
     *             subtree
     * @param config Instance of {@link PasspointConfiguration}
     * @throws ParsingException
     */
    private static void parseExtension(PPSNode node, PasspointConfiguration config)
            throws ParsingException {
        if (node.isLeaf()) {
            throw new ParsingException("Leaf node not expected for Extension");
        }
        for (PPSNode child : node.getChildren()) {
            switch (child.getName()) {
                case NODE_VENDOR_ANDROID:
                    parseVendorAndroidExtension(child, config);
                    break;
                default:
                    // Unknown nodes under Extension won't raise exception.
                    // This allows adding new nodes in the future and
                    // won't break older release.
                    Log.w(TAG, "Unknown node under Extension: " + child.getName());
            }
        }
    }

    /**
     * Convert a hex string to a byte array.
     *
     * @param str String containing hex values
     * @return byte[]
     * @throws ParsingException
     */
    private static byte[] parseHexString(String str) throws ParsingException {
        if ((str.length() & 1) == 1) {
            throw new ParsingException("Odd length hex string: " + str.length());
        }

        byte[] result = new byte[str.length() / 2];
        for (int i = 0; i < result.length; i++) {
          int index = i * 2;
          try {
              result[i] = (byte) Integer.parseInt(str.substring(index, index + 2), 16);
          } catch (NumberFormatException e) {
              throw new ParsingException("Invalid hex string: " + str);
          }
        }
        return result;
    }

    /**
     * Convert a date string to the number of milliseconds since January 1, 1970, 00:00:00 GMT.
     *
     * @param dateStr String in the format of yyyy-MM-dd'T'HH:mm:ss'Z'
     * @return number of milliseconds
     * @throws ParsingException
     */
    private static long parseDate(String dateStr) throws ParsingException {
        try {
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            return format.parse(dateStr).getTime();
        } catch (ParseException pe) {
            throw new ParsingException("Badly formatted time: " + dateStr);
        }
    }

    /**
     * Parse an integer string.
     *
     * @param value String of integer value
     * @return int
     * @throws ParsingException
     */
    private static int parseInteger(String value) throws ParsingException {
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new ParsingException("Invalid integer value: " + value);
        }
    }

    /**
     * Parse a string representing a long integer.
     *
     * @param value String of long integer value
     * @return long
     * @throws ParsingException
     */
    private static long parseLong(String value, int radix) throws ParsingException {
        try {
            return Long.parseLong(value, radix);
        } catch (NumberFormatException e) {
            throw new ParsingException("Invalid long integer value: " + value);
        }
    }

    /**
     * Convert a List<Long> to a primitive long array long[].
     *
     * @param list List to be converted
     * @return long[]
     */
    private static long[] convertFromLongList(List<Long> list) {
        Long[] objectArray = list.toArray(new Long[list.size()]);
        long[] primitiveArray = new long[objectArray.length];
        for (int i = 0; i < objectArray.length; i++) {
            primitiveArray[i] = objectArray[i].longValue();
        }
        return primitiveArray;
    }
}
