Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85cae1da authored by Max Loh's avatar Max Loh Committed by Android (Google) Code Review
Browse files

Merge "Refactor with interface pattern, and throw exception for unsupported formats" into main

parents e852f143 9dd4e469
Loading
Loading
Loading
Loading
+38 −20
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -33,7 +34,7 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

public class AndroidSafetyLabel {
public class AndroidSafetyLabel implements AslMarshallable {

    public enum Format {
        NULL, HUMAN_READABLE, ON_DEVICE;
@@ -45,31 +46,55 @@ public class AndroidSafetyLabel {
        return mSafetyLabels;
    }

    private AndroidSafetyLabel(SafetyLabels safetyLabels) {
    public AndroidSafetyLabel(SafetyLabels safetyLabels) {
        this.mSafetyLabels = safetyLabels;
    }

    /** Reads a {@link AndroidSafetyLabel} from an {@link InputStream}. */
    // TODO(b/329902686): Support conversion in both directions, specified by format.
    // TODO(b/329902686): Support parsing from on-device.
    public static AndroidSafetyLabel readFromStream(InputStream in, Format format)
            throws IOException, ParserConfigurationException, SAXException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        Document document = factory.newDocumentBuilder().parse(in);

        switch (format) {
            case HUMAN_READABLE:
                Element appMetadataBundles =
                        XmlUtils.getSingleElement(document, XmlUtils.HR_TAG_APP_METADATA_BUNDLES);

        return AndroidSafetyLabel.createFromHrElement(appMetadataBundles);
                return new AndroidSafetyLabelFactory()
                        .createFromHrElements(
                                XmlUtils.asElementList(
                                        document.getElementsByTagName(
                                                XmlUtils.HR_TAG_APP_METADATA_BUNDLES)));
            case ON_DEVICE:
                throw new IllegalArgumentException(
                        "Parsing from on-device format is not supported at this time.");
            default:
                throw new IllegalStateException("Unrecognized input format.");
        }
    }

    /** Write the content of the {@link AndroidSafetyLabel} to a {@link OutputStream}. */
    // TODO(b/329902686): Support conversion in both directions, specified by format.
    // TODO(b/329902686): Support outputting human-readable format.
    public void writeToStream(OutputStream out, Format format)
            throws IOException, ParserConfigurationException, TransformerException {
        var docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        var document = docBuilder.newDocument();
        document.appendChild(this.toOdDomElement(document));

        switch (format) {
            case HUMAN_READABLE:
                throw new IllegalArgumentException(
                        "Outputting human-readable format is not supported at this time.");
            case ON_DEVICE:
                for (var child : this.toOdDomElements(document)) {
                    document.appendChild(child);
                }
                break;
            default:
                throw new IllegalStateException("Unrecognized input format.");
        }

        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
@@ -81,19 +106,12 @@ public class AndroidSafetyLabel {
        transformer.transform(domSource, streamResult);
    }

    /** Creates an {@link AndroidSafetyLabel} from human-readable DOM element */
    public static AndroidSafetyLabel createFromHrElement(Element appMetadataBundlesEle) {
        Element safetyLabelsEle =
                XmlUtils.getSingleElement(appMetadataBundlesEle, XmlUtils.HR_TAG_SAFETY_LABELS);
        SafetyLabels safetyLabels = SafetyLabels.createFromHrElement(safetyLabelsEle);
        return new AndroidSafetyLabel(safetyLabels);
    }

    /** Creates an on-device DOM element from an {@link AndroidSafetyLabel} */
    public Element toOdDomElement(Document doc) {
    @Override
    public List<Element> toOdDomElements(Document doc) {
        Element aslEle = doc.createElement(XmlUtils.OD_TAG_BUNDLE);
        aslEle.appendChild(mSafetyLabels.toOdDomElement(doc));
        return aslEle;
        XmlUtils.appendChildren(aslEle, mSafetyLabels.toOdDomElements(doc));
        return List.of(aslEle);
    }

    public static void test() {
+36 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 com.android.asllib;

import org.w3c.dom.Element;

import java.util.List;

public class AndroidSafetyLabelFactory implements AslMarshallableFactory<AndroidSafetyLabel> {

    /** Creates an {@link AndroidSafetyLabel} from human-readable DOM element */
    @Override
    public AndroidSafetyLabel createFromHrElements(List<Element> appMetadataBundles) {
        Element appMetadataBundlesEle = XmlUtils.getSingleElement(appMetadataBundles);
        Element safetyLabelsEle =
                XmlUtils.getSingleChildElement(
                        appMetadataBundlesEle, XmlUtils.HR_TAG_SAFETY_LABELS);
        SafetyLabels safetyLabels =
                new SafetyLabelsFactory().createFromHrElements(List.of(safetyLabelsEle));
        return new AndroidSafetyLabel(safetyLabels);
    }
}
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 com.android.asllib;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.util.List;

public interface AslMarshallable {

    /** Creates the on-device DOM element from the AslMarshallable Java Object. */
    List<Element> toOdDomElements(Document doc);
}
+27 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 com.android.asllib;

import org.w3c.dom.Element;

import java.util.List;

public interface AslMarshallableFactory<T extends AslMarshallable> {

    /** Creates an {@link AslMarshallableFactory} from human-readable DOM element */
    T createFromHrElements(List<Element> elements);
}
+20 −5
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package com.android.asllib;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.util.List;
import java.util.Map;

/**
@@ -23,21 +27,32 @@ import java.util.Map;
 * are defined in {@link DataCategoryConstants}, each category has a valid set of types {@link
 * DataType}, which are mapped in {@link DataTypeConstants}
 */
public class DataCategory {
public class DataCategory implements AslMarshallable {
    private final String mCategoryName;
    private final Map<String, DataType> mDataTypes;

    private DataCategory(Map<String, DataType> dataTypes) {
    public DataCategory(String categoryName, Map<String, DataType> dataTypes) {
        this.mCategoryName = categoryName;
        this.mDataTypes = dataTypes;
    }

    public String getCategoryName() {
        return mCategoryName;
    }

    /** Return the type {@link Map} of String type key to {@link DataType} */

    public Map<String, DataType> getDataTypes() {
        return mDataTypes;
    }

    /** Creates a {@link DataCategory} given map of {@param dataTypes}. */
    public static DataCategory create(Map<String, DataType> dataTypes) {
        return new DataCategory(dataTypes);
    /** Creates on-device DOM element(s) from the {@link DataCategory}. */
    @Override
    public List<Element> toOdDomElements(Document doc) {
        Element dataCategoryEle = XmlUtils.createPbundleEleWithName(doc, this.getCategoryName());
        for (DataType dataType : mDataTypes.values()) {
            XmlUtils.appendChildren(dataCategoryEle, dataType.toOdDomElements(doc));
        }
        return List.of(dataCategoryEle);
    }
}
Loading