19dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann/*
29dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Copyright (C) 2016 The Android Open Source Project
39dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *
49dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Licensed under the Apache License, Version 2.0 (the "License");
59dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * you may not use this file except in compliance with the License.
69dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * You may obtain a copy of the License at
79dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *
89dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *      http://www.apache.org/licenses/LICENSE-2.0
99dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *
109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Unless required by applicable law or agreed to in writing, software
119dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * distributed under the License is distributed on an "AS IS" BASIS,
129dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * See the License for the specific language governing permissions and
149dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * limitations under the License.
159dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */
169dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
179dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannpackage com.android.printservice.recommendation.plugin.mdnsFilter;
189dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
199dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.annotation.NonNull;
209dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.annotation.Nullable;
219dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.content.Context;
229dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.content.res.XmlResourceParser;
239dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.util.ArrayMap;
249dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport com.android.internal.annotations.Immutable;
259dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport com.android.internal.util.Preconditions;
269dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport com.android.printservice.recommendation.R;
279dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport org.xmlpull.v1.XmlPullParser;
289dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport org.xmlpull.v1.XmlPullParserException;
299dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
309dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport java.io.IOException;
319dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport java.util.ArrayList;
329dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport java.util.Collection;
339dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport java.util.Collections;
349dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport java.util.List;
359dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
369dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann/**
379dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Vendor configuration as read from {@link R.xml#vendorconfigs vendorconfigs.xml}. Configuration
389dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * can be read via {@link #getConfig(Context, String)}.
399dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */
409dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann@Immutable
419dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannpublic class VendorConfig {
429dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** Lock for {@link #sConfigs} */
439dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static final Object sLock = new Object();
449dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
459dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** Strings used as XML tags */
469dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static final String VENDORS_TAG = "vendors";
479dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static final String VENDOR_TAG = "vendor";
489dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static final String NAME_TAG = "name";
499dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static final String PACKAGE_TAG = "package";
509dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static final String MDNSNAMES_TAG = "mdns-names";
519dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static final String MDNSNAME_TAG = "mdns-name";
529dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
539dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** Map from vendor name to config. Initialized on first {@link #getConfig use}. */
549dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static @Nullable ArrayMap<String, VendorConfig> sConfigs;
559dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
569dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** Localized vendor name */
579dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public final @NonNull String name;
589dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
599dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** Package name containing the print service for this vendor */
609dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public final @NonNull String packageName;
619dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
629dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** mDNS names used by this vendor */
639dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public final @NonNull List<String> mDNSNames;
649dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
659dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
669dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Create an immutable configuration.
679dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
689dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private VendorConfig(@NonNull String name, @NonNull String packageName,
699dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            @NonNull List<String> mDNSNames) {
709dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        this.name = Preconditions.checkStringNotEmpty(name);
719dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        this.packageName = Preconditions.checkStringNotEmpty(packageName);
729dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        this.mDNSNames = Preconditions.checkCollectionElementsNotNull(mDNSNames, "mDNSName");
739dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
749dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
759dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
769dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Get the configuration for a vendor.
779dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
789dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param context Calling context
799dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param name    The name of the config to read
809dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
819dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @return the config for the vendor or null if not found
829dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
839dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws IOException
849dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws XmlPullParserException
859dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
869dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public static @Nullable VendorConfig getConfig(@NonNull Context context, @NonNull String name)
879dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throws IOException, XmlPullParserException {
889dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        synchronized (sLock) {
899dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            if (sConfigs == null) {
909dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                sConfigs = readVendorConfigs(context);
919dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
929dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
939dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            return sConfigs.get(name);
949dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
959dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
969dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
979dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
989dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Get all known vendor configurations.
999dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1009dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param context Calling context
1019dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1029dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @return The known configurations
1039dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1049dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws IOException
1059dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws XmlPullParserException
1069dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1079dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public static @NonNull Collection<VendorConfig> getAllConfigs(@NonNull Context context)
1089dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throws IOException, XmlPullParserException {
1099dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        synchronized (sLock) {
1109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            if (sConfigs == null) {
1119dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                sConfigs = readVendorConfigs(context);
1129dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
1139dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1149dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            return sConfigs.values();
1159dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1169dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1179dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1189dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
1199dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Read the text from a XML tag.
1209dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1219dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param parser XML parser to read from
1229dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1239dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @return The text or "" if no text was found
1249dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1259dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws IOException
1269dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws XmlPullParserException
1279dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1289dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static @NonNull String readText(XmlPullParser parser)
1299dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throws IOException, XmlPullParserException {
1309dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        String result = "";
1319dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1329dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        if (parser.next() == XmlPullParser.TEXT) {
1339dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            result = parser.getText();
1349dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            parser.nextTag();
1359dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1369dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1379dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        return result;
1389dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1399dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1409dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
1419dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Read a tag with a text content from the parser.
1429dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1439dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param parser  XML parser to read from
1449dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param tagName The name of the tag to read
1459dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1469dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @return The text content of the tag
1479dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1489dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws IOException
1499dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws XmlPullParserException
1509dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1519dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static @NonNull String readSimpleTag(@NonNull Context context,
1529dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            @NonNull XmlPullParser parser, @NonNull String tagName, boolean resolveReferences)
1539dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throws IOException, XmlPullParserException {
1549dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        parser.require(XmlPullParser.START_TAG, null, tagName);
1559dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        String text = readText(parser);
1569dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        parser.require(XmlPullParser.END_TAG, null, tagName);
1579dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1589dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        if (resolveReferences && text.startsWith("@")) {
1599dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            return context.getResources().getString(
1609dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    context.getResources().getIdentifier(text, null, context.getPackageName()));
1619dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        } else {
1629dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            return text;
1639dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1649dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1659dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1669dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
1679dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Read content of a list of tags.
1689dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1699dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param parser     XML parser to read from
1709dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param tagName    The name of the list tag
1719dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param subTagName The name of the list-element tags
1729dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param tagReader  The {@link TagReader reader} to use to read the tag content
1739dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param <T>        The type of the parsed tag content
1749dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1759dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @return A list of {@link T}
1769dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1779dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws XmlPullParserException
1789dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws IOException
1799dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1809dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static @NonNull <T> ArrayList<T> readTagList(@NonNull XmlPullParser parser,
1819dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            @NonNull String tagName, @NonNull String subTagName, @NonNull TagReader<T> tagReader)
1829dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throws XmlPullParserException, IOException {
1839dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        ArrayList<T> entries = new ArrayList<>();
1849dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1859dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        parser.require(XmlPullParser.START_TAG, null, tagName);
1869dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        while (parser.next() != XmlPullParser.END_TAG) {
1879dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            if (parser.getEventType() != XmlPullParser.START_TAG) {
1889dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                continue;
1899dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
1909dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1919dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            if (parser.getName().equals(subTagName)) {
1929dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                entries.add(tagReader.readTag(parser, subTagName));
1939dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            } else {
1949dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                throw new XmlPullParserException(
1959dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                        "Unexpected subtag of " + tagName + ": " + parser.getName());
1969dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
1979dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1989dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1999dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        return entries;
2009dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
2019dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2029dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
2039dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Read the vendor configuration file.
2049dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
2059dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param context The content issuing the read
2069dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
2079dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @return An map pointing from vendor name to config
2089dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
2099dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws IOException
2109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws XmlPullParserException
2119dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
2129dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static @NonNull ArrayMap<String, VendorConfig> readVendorConfigs(
2139dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            @NonNull final Context context) throws IOException, XmlPullParserException {
2149dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        try (XmlResourceParser parser = context.getResources().getXml(R.xml.vendorconfigs)) {
2159dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            // Skip header
2169dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            int parsingEvent;
2179dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            do {
2189dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                parsingEvent = parser.next();
2199dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            } while (parsingEvent != XmlResourceParser.START_TAG);
2209dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2219dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            ArrayList<VendorConfig> configs = readTagList(parser, VENDORS_TAG, VENDOR_TAG,
2229dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    new TagReader<VendorConfig>() {
2239dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                        public VendorConfig readTag(XmlPullParser parser, String tagName)
2249dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                throws XmlPullParserException, IOException {
2259dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                            return readVendorConfig(context, parser, tagName);
2269dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                        }
2279dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    });
2289dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2299dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            ArrayMap<String, VendorConfig> configMap = new ArrayMap<>(configs.size());
2309dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            final int numConfigs = configs.size();
2319dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            for (int i = 0; i < numConfigs; i++) {
2329dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                VendorConfig config = configs.get(i);
2339dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2349dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                configMap.put(config.name, config);
2359dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
2369dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2379dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            return configMap;
2389dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
2399dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
2409dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2419dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
2429dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Read a single vendor configuration.
2439dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
2449dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param parser  XML parser to read from
2459dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param tagName The vendor tag
2469dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param context Calling context
2479dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
2489dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @return A config
2499dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
2509dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws XmlPullParserException
2519dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws IOException
2529dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
2539dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private static VendorConfig readVendorConfig(@NonNull final Context context,
2549dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            @NonNull XmlPullParser parser, @NonNull String tagName) throws XmlPullParserException,
2559dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            IOException {
2569dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        parser.require(XmlPullParser.START_TAG, null, tagName);
2579dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2589dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        String name = null;
2599dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        String packageName = null;
2609dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        List<String> mDNSNames = null;
2619dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2629dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        while (parser.next() != XmlPullParser.END_TAG) {
2639dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            if (parser.getEventType() != XmlPullParser.START_TAG) {
2649dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                continue;
2659dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
2669dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2679dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            String subTagName = parser.getName();
2689dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2699dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            switch (subTagName) {
2709dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                case NAME_TAG:
2719dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    name = readSimpleTag(context, parser, NAME_TAG, false);
2729dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    break;
2739dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                case PACKAGE_TAG:
2749dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    packageName = readSimpleTag(context, parser, PACKAGE_TAG, true);
2759dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    break;
2769dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                case MDNSNAMES_TAG:
2779dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    mDNSNames = readTagList(parser, MDNSNAMES_TAG, MDNSNAME_TAG,
2789dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                            new TagReader<String>() {
2799dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                public String readTag(XmlPullParser parser, String tagName)
2809dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                        throws XmlPullParserException, IOException {
2819dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                    return readSimpleTag(context, parser, tagName, true);
2829dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                                }
2839dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                            }
2849dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    );
2859dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    break;
2869dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                default:
2879dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    throw new XmlPullParserException("Unexpected subtag of " + tagName + ": "
2889dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                            + subTagName);
2899dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2909dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
2919dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
2929dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2939dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        if (name == null) {
2949dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throw new XmlPullParserException("name is required");
2959dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
2969dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
2979dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        if (packageName == null) {
2989dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throw new XmlPullParserException("package is required");
2999dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
3009dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
3019dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        if (mDNSNames == null) {
3029dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            mDNSNames = Collections.emptyList();
3039dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
3049dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
3059dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        // A vendor config should be immutable
3069dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        mDNSNames = Collections.unmodifiableList(mDNSNames);
3079dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
3089dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        return new VendorConfig(name, packageName, mDNSNames);
3099dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
3109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
3119dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    @Override
3129dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public String toString() {
3139dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        return name + " -> " + packageName + ", " + mDNSNames;
3149dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
3159dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
3169dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
3179dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Used a a "function pointer" when reading a tag in {@link #readTagList(XmlPullParser, String,
3189dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * String, TagReader)}.
3199dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
3209dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param <T> The type of content to read
3219dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
3229dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private interface TagReader<T> {
3239dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        T readTag(XmlPullParser parser, String tagName) throws XmlPullParserException, IOException;
3249dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
3259dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann}
326