/*
 * Copyright (C) 2017 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.
 */

// Convert objects from and to xml.

#define LOG_TAG "libvintf"
#include <android-base/logging.h>

#include "parse_xml.h"

#include <type_traits>

#include <tinyxml2.h>

#include "parse_string.h"

namespace android {
namespace vintf {

// --------------- tinyxml2 details

using NodeType = tinyxml2::XMLElement;
using DocType = tinyxml2::XMLDocument;

// caller is responsible for deleteDocument() call
inline DocType *createDocument() {
    return new tinyxml2::XMLDocument();
}

// caller is responsible for deleteDocument() call
inline DocType *createDocument(const std::string &xml) {
    DocType *doc = new tinyxml2::XMLDocument();
    if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
        return doc;
    }
    delete doc;
    return nullptr;
}

inline void deleteDocument(DocType *d) {
    delete d;
}

inline std::string printDocument(DocType *d) {
    tinyxml2::XMLPrinter p;
    d->Print(&p);
    return std::string{p.CStr()};
}

inline NodeType *createNode(const std::string &name, DocType *d) {
    return d->NewElement(name.c_str());
}

inline void appendChild(NodeType *parent, NodeType *child) {
    parent->InsertEndChild(child);
}

inline void appendChild(DocType *parent, NodeType *child) {
    parent->InsertEndChild(child);
}

inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
    e->SetAttribute(attrName.c_str(), attr.c_str());
}

// text -> text
inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
    parent->InsertEndChild(d->NewText(text.c_str()));
}

inline std::string nameOf(NodeType *root) {
    return root->Name() == NULL ? "" : root->Name();
}

inline std::string getText(NodeType *root) {
    return root->GetText() == NULL ? "" : root->GetText();
}

inline NodeType *getChild(NodeType *parent, const std::string &name) {
    return parent->FirstChildElement(name.c_str());
}

inline NodeType *getRootChild(DocType *parent) {
    return parent->FirstChildElement();
}

inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
    std::vector<NodeType *> v;
    for (NodeType *child = parent->FirstChildElement(name.c_str());
         child != nullptr;
         child = child->NextSiblingElement(name.c_str())) {
        v.push_back(child);
    }
    return v;
}

inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
    const char *c = root->Attribute(attrName.c_str());
    if (c == NULL)
        return false;
    *s = c;
    return true;
}

// --------------- tinyxml2 details end.

// Helper functions for XmlConverter
static bool parse(const std::string &attrText, bool *attr) {
    if (attrText == "true" || attrText == "1") {
        *attr = true;
        return true;
    }
    if (attrText == "false" || attrText == "0") {
        *attr = false;
        return true;
    }
    return false;
}

// ---------------------- XmlNodeConverter definitions

template<typename Object>
struct XmlNodeConverter : public XmlConverter<Object> {
    XmlNodeConverter() {}
    virtual ~XmlNodeConverter() {}

    // sub-types should implement these.
    virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
    virtual bool buildObject(Object *o, NodeType *n) const = 0;
    virtual std::string elementName() const = 0;

    // convenience methods for user
    inline const std::string &lastError() const { return mLastError; }
    inline NodeType *serialize(const Object &o, DocType *d) const {
        NodeType *root = createNode(this->elementName(), d);
        this->mutateNode(o, root, d);
        return root;
    }
    inline std::string serialize(const Object &o) const {
        DocType *doc = createDocument();
        appendChild(doc, serialize(o, doc));
        std::string s = printDocument(doc);
        deleteDocument(doc);
        return s;
    }
    inline bool deserialize(Object *object, NodeType *root) const {
        if (nameOf(root) != this->elementName()) {
            return false;
        }
        return this->buildObject(object, root);
    }
    inline bool deserialize(Object *o, const std::string &xml) const {
        DocType *doc = createDocument(xml);
        if (doc == nullptr) {
            this->mLastError = "Not a valid XML";
            return false;
        }
        bool ret = deserialize(o, getRootChild(doc));
        deleteDocument(doc);
        return ret;
    }
    inline NodeType *operator()(const Object &o, DocType *d) const {
        return serialize(o, d);
    }
    inline std::string operator()(const Object &o) const {
        return serialize(o);
    }
    inline bool operator()(Object *o, NodeType *node) const {
        return deserialize(o, node);
    }
    inline bool operator()(Object *o, const std::string &xml) const {
        return deserialize(o, xml);
    }

    // convenience methods for implementor.

    // All append* functions helps mutateNode() to serialize the object into XML.
    template <typename T>
    inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
        return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
    }

    inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
        return appendStrAttr(e, attrName, attr ? "true" : "false");
    }

    // text -> <name>text</name>
    inline void appendTextElement(NodeType *parent, const std::string &name,
                const std::string &text, DocType *d) const {
        NodeType *c = createNode(name, d);
        appendText(c, text, d);
        appendChild(parent, c);
    }

    // text -> <name>text</name>
    template<typename Array>
    inline void appendTextElements(NodeType *parent, const std::string &name,
                const Array &array, DocType *d) const {
        for (const std::string &text : array) {
            NodeType *c = createNode(name, d);
            appendText(c, text, d);
            appendChild(parent, c);
        }
    }

    template<typename T, typename Array>
    inline void appendChildren(NodeType *parent, const XmlNodeConverter<T> &conv,
            const Array &array, DocType *d) const {
        for (const T &t : array) {
            appendChild(parent, conv(t, d));
        }
    }

    // All parse* functions helps buildObject() to deserialize XML to the object. Returns
    // true if deserialization is successful, false if any error, and mLastError will be
    // set to error message.
    template <typename T>
    inline bool parseOptionalAttr(NodeType *root, const std::string &attrName,
            T &&defaultValue, T *attr) const {
        std::string attrText;
        bool success = getAttr(root, attrName, &attrText) &&
                       ::android::vintf::parse(attrText, attr);
        if (!success) {
            *attr = std::move(defaultValue);
        }
        return true;
    }

    template <typename T>
    inline bool parseAttr(NodeType *root, const std::string &attrName, T *attr) const {
        std::string attrText;
        bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
        if (!ret) {
            mLastError = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
                         attrText + "\" for element <" + elementName() + ">";
        }
        return ret;
    }

    inline bool parseAttr(NodeType *root, const std::string &attrName, std::string *attr) const {
        bool ret = getAttr(root, attrName, attr);
        if (!ret) {
            mLastError = "Could not find attr with name \"" + attrName + "\" for element <"
                    + elementName() + ">";
        }
        return ret;
    }

    inline bool parseTextElement(NodeType *root,
            const std::string &elementName, std::string *s) const {
        NodeType *child = getChild(root, elementName);
        if (child == nullptr) {
            mLastError = "Could not find element with name <" + elementName + "> in element <"
                    + this->elementName() + ">";
            return false;
        }
        *s = getText(child);
        return true;
    }

    inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
                                         std::string&& defaultValue, std::string* s) const {
        NodeType* child = getChild(root, elementName);
        *s = child == nullptr ? std::move(defaultValue) : getText(child);
        return true;
    }

    inline bool parseTextElements(NodeType *root, const std::string &elementName,
            std::vector<std::string> *v) const {
        auto nodes = getChildren(root, elementName);
        v->resize(nodes.size());
        for (size_t i = 0; i < nodes.size(); ++i) {
            v->at(i) = getText(nodes[i]);
        }
        return true;
    }

    template <typename T>
    inline bool parseChild(NodeType *root, const XmlNodeConverter<T> &conv, T *t) const {
        NodeType *child = getChild(root, conv.elementName());
        if (child == nullptr) {
            mLastError = "Could not find element with name <" + conv.elementName() + "> in element <"
                    + this->elementName() + ">";
            return false;
        }
        bool success = conv.deserialize(t, child);
        if (!success) {
            mLastError = conv.lastError();
        }
        return success;
    }

    template <typename T>
    inline bool parseOptionalChild(NodeType *root, const XmlNodeConverter<T> &conv,
            T &&defaultValue, T *t) const {
        NodeType *child = getChild(root, conv.elementName());
        if (child == nullptr) {
            *t = std::move(defaultValue);
            return true;
        }
        bool success = conv.deserialize(t, child);
        if (!success) {
            mLastError = conv.lastError();
        }
        return success;
    }

    template <typename T>
    inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::vector<T> *v) const {
        auto nodes = getChildren(root, conv.elementName());
        v->resize(nodes.size());
        for (size_t i = 0; i < nodes.size(); ++i) {
            if (!conv.deserialize(&v->at(i), nodes[i])) {
                mLastError = "Could not parse element with name <" + conv.elementName()
                        + "> in element <" + this->elementName() + ">: " + conv.lastError();
                return false;
            }
        }
        return true;
    }

    template <typename T>
    inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::set<T> *s) const {
        std::vector<T> vec;
        if (!parseChildren(root, conv, &vec)) {
            return false;
        }
        s->clear();
        s->insert(vec.begin(), vec.end());
        if (s->size() != vec.size()) {
            mLastError = "Duplicated elements <" + conv.elementName() + "> in element <"
                    + this->elementName() + ">";
            s->clear();
            return false;
        }
        return true;
    }

    inline bool parseText(NodeType *node, std::string *s) const {
        *s = getText(node);
        return true;
    }

    template <typename T>
    inline bool parseText(NodeType *node, T *s) const {
        std::string text = getText(node);
        bool ret = ::android::vintf::parse(text, s);
        if (!ret) {
            mLastError = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
        }
        return ret;
    }
protected:
    mutable std::string mLastError;
};

template<typename Object>
struct XmlTextConverter : public XmlNodeConverter<Object> {
    XmlTextConverter(const std::string &elementName)
        : mElementName(elementName) {}

    virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
        appendText(root, ::android::vintf::to_string(object), d);
    }
    virtual bool buildObject(Object *object, NodeType *root) const override {
        return this->parseText(root, object);
    }
    virtual std::string elementName() const { return mElementName; };
private:
    std::string mElementName;
};

// ---------------------- XmlNodeConverter definitions end

const XmlTextConverter<Version> versionConverter{"version"};

const XmlTextConverter<VersionRange> versionRangeConverter{"version"};

const XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"};

struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
    std::string elementName() const override { return "transport"; }
    void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
        if (object.arch != Arch::ARCH_EMPTY) {
            appendAttr(root, "arch", object.arch);
        }
        appendText(root, ::android::vintf::to_string(object.transport), d);
    }
    bool buildObject(TransportArch *object, NodeType *root) const override {
        if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch) ||
            !parseText(root, &object->transport)) {
            return false;
        }
        if (!object->isValid()) {
            this->mLastError = "transport == " + ::android::vintf::to_string(object->transport) +
                    " and arch == " + ::android::vintf::to_string(object->arch) +
                    " is not a valid combination.";
            return false;
        }
        return true;
    }
};

const TransportArchConverter transportArchConverter{};

struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
    std::string elementName() const override { return "value"; }
    void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
        appendAttr(root, "type", object.mType);
        appendText(root, ::android::vintf::to_string(object), d);
    }
    bool buildObject(KernelConfigTypedValue *object, NodeType *root) const override {
        std::string stringValue;
        if (!parseAttr(root, "type", &object->mType) ||
            !parseText(root, &stringValue)) {
            return false;
        }
        if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
            this->mLastError = "Could not parse kernel config value \"" + stringValue + "\"";
            return false;
        }
        return true;
    }
};

const KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};

struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> {
    std::string elementName() const override { return "config"; }
    void mutateNode(const KernelConfig &object, NodeType *root, DocType *d) const override {
        appendChild(root, kernelConfigKeyConverter(object.first, d));
        appendChild(root, kernelConfigTypedValueConverter(object.second, d));
    }
    bool buildObject(KernelConfig *object, NodeType *root) const override {
        if (   !parseChild(root, kernelConfigKeyConverter, &object->first)
            || !parseChild(root, kernelConfigTypedValueConverter, &object->second)) {
            return false;
        }
        return true;
    }
};

const KernelConfigConverter kernelConfigConverter{};

struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
    std::string elementName() const override { return "interface"; }
    void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
        appendTextElement(root, "name", intf.name, d);
        appendTextElements(root, "instance", intf.instances, d);
    }
    bool buildObject(HalInterface *intf, NodeType *root) const override {
        std::vector<std::string> instances;
        if (!parseTextElement(root, "name", &intf->name) ||
            !parseTextElements(root, "instance", &instances)) {
            return false;
        }
        intf->instances.clear();
        intf->instances.insert(instances.begin(), instances.end());
        if (intf->instances.size() != instances.size()) {
            this->mLastError = "Duplicated instances in " + intf->name;
            return false;
        }
        return true;
    }
};

const HalInterfaceConverter halInterfaceConverter{};

struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
    std::string elementName() const override { return "hal"; }
    void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
        appendAttr(root, "format", hal.format);
        appendAttr(root, "optional", hal.optional);
        appendTextElement(root, "name", hal.name, d);
        appendChildren(root, versionRangeConverter, hal.versionRanges, d);
        appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
    }
    bool buildObject(MatrixHal *object, NodeType *root) const override {
        std::vector<HalInterface> interfaces;
        if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) ||
            !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional) ||
            !parseTextElement(root, "name", &object->name) ||
            !parseChildren(root, versionRangeConverter, &object->versionRanges) ||
            !parseChildren(root, halInterfaceConverter, &interfaces)) {
            return false;
        }
        for (auto&& interface : interfaces) {
            std::string name{interface.name};
            auto res = object->interfaces.emplace(std::move(name), std::move(interface));
            if (!res.second) {
                this->mLastError = "Duplicated interface entry \"" + res.first->first +
                                   "\"; if additional instances are needed, add them to the "
                                   "existing <interface> node.";
                return false;
            }
        }
// Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
#ifdef LIBVINTF_HOST
        if (!checkAdditionalRestrictionsOnHal(*object)) {
            return false;
        }
#endif
        return true;
    }

#ifdef LIBVINTF_HOST
   private:
    bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal) const {
        if (hal.getName() == "netutils-wrapper") {
            if (hal.versionRanges.size() != 1) {
                this->mLastError =
                    "netutils-wrapper HAL must specify exactly one version x.0, "
                    "but multiple <version> element is specified.";
                return false;
            }
            const VersionRange& v = hal.versionRanges.at(0);
            if (!v.isSingleVersion()) {
                this->mLastError =
                    "netutils-wrapper HAL must specify exactly one version x.0, "
                    "but a range is provided. Perhaps you mean '" +
                    to_string(Version{v.majorVer, 0}) + "'?";
                return false;
            }
            if (v.minMinor != 0) {
                this->mLastError =
                    "netutils-wrapper HAL must specify exactly one version x.0, "
                    "but minor version is not 0. Perhaps you mean '" +
                    to_string(Version{v.majorVer, 0}) + "'?";
                return false;
            }
        }
        return true;
    }
#endif
};

const MatrixHalConverter matrixHalConverter{};

struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
    std::string elementName() const override { return "conditions"; }
    void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
                    DocType* d) const override {
        appendChildren(root, kernelConfigConverter, conds, d);
    }
    bool buildObject(std::vector<KernelConfig>* object, NodeType* root) const override {
        return parseChildren(root, kernelConfigConverter, object);
    }
};

const MatrixKernelConditionsConverter matrixKernelConditionsConverter{};

struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
    std::string elementName() const override { return "kernel"; }
    void mutateNode(const MatrixKernel &kernel, NodeType *root, DocType *d) const override {
        appendAttr(root, "version", kernel.mMinLts);
        if (!kernel.mConditions.empty()) {
            appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
        }
        appendChildren(root, kernelConfigConverter, kernel.mConfigs, d);
    }
    bool buildObject(MatrixKernel *object, NodeType *root) const override {
        if (!parseAttr(root, "version", &object->mMinLts) ||
            !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions) ||
            !parseChildren(root, kernelConfigConverter, &object->mConfigs)) {
            return false;
        }
        return true;
    }
};

const MatrixKernelConverter matrixKernelConverter{};

struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
    std::string elementName() const override { return "hal"; }
    void mutateNode(const ManifestHal &hal, NodeType *root, DocType *d) const override {
        appendAttr(root, "format", hal.format);
        appendTextElement(root, "name", hal.name, d);
        if (!hal.transportArch.empty()) {
            appendChild(root, transportArchConverter(hal.transportArch, d));
        }
        appendChildren(root, versionConverter, hal.versions, d);
        appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
    }
    bool buildObject(ManifestHal *object, NodeType *root) const override {
        std::vector<HalInterface> interfaces;
        if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) ||
            !parseTextElement(root, "name", &object->name) ||
            !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch) ||
            !parseChildren(root, versionConverter, &object->versions) ||
            !parseChildren(root, halInterfaceConverter, &interfaces)) {
            return false;
        }

        switch (object->format) {
            case HalFormat::HIDL: {
                if (object->transportArch.empty()) {
                    this->mLastError =
                        "HIDL HAL '" + object->name + "' should have <transport> defined.";
                    return false;
                }
            } break;
            case HalFormat::NATIVE: {
                if (!object->transportArch.empty()) {
                    this->mLastError =
                        "Native HAL '" + object->name + "' should not have <transport> defined.";
                    return false;
                }
            } break;
            default: {
                LOG(FATAL) << "Unhandled HalFormat "
                           << static_cast<typename std::underlying_type<HalFormat>::type>(
                                  object->format);
            } break;
        }
        if (!object->transportArch.isValid()) return false;

        object->interfaces.clear();
        for (auto &&interface : interfaces) {
            auto res = object->interfaces.emplace(interface.name,
                                                  std::move(interface));
            if (!res.second) {
                this->mLastError = "Duplicated interface entry \"" + res.first->first +
                                   "\"; if additional instances are needed, add them to the "
                                   "existing <interface> node.";
                return false;
            }
        }
        if (!object->isValid()) {
            this->mLastError = "'" + object->name + "' is not a valid Manifest HAL.";
            return false;
        }
// Do not check for target-side libvintf to avoid restricting upgrade accidentally.
#ifdef LIBVINTF_HOST
        if (!checkAdditionalRestrictionsOnHal(*object)) {
            return false;
        }
#endif
        return true;
    }

#ifdef LIBVINTF_HOST
   private:
    bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal) const {
        if (hal.getName() == "netutils-wrapper") {
            for (const Version& v : hal.versions) {
                if (v.minorVer != 0) {
                    this->mLastError =
                        "netutils-wrapper HAL must specify exactly one version x.0, "
                        "but minor version is not 0. Perhaps you mean '" +
                        to_string(Version{v.majorVer, 0}) + "'?";
                    return false;
                }
            }
        }
        return true;
    }
#endif
};

// Convert ManifestHal from and to XML. Returned object is guaranteed to have
// .isValid() == true.
const ManifestHalConverter manifestHalConverter{};

const XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
const XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};

struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
    std::string elementName() const override { return "sepolicy"; }
    void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
        appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
        appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
    }
    bool buildObject(Sepolicy *object, NodeType *root) const override {
        if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion) ||
            !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges)) {
            return false;
        }
        return true;
    }
};
const SepolicyConverter sepolicyConverter{};

const XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
const XmlTextConverter<std::string> vndkLibraryConverter{"library"};

struct VndkConverter : public XmlNodeConverter<Vndk> {
    std::string elementName() const override { return "vndk"; }
    void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
        appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
        appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
    }
    bool buildObject(Vndk *object, NodeType *root) const override {
        if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange) ||
            !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) {
            return false;
        }
        return true;
    }
};

const VndkConverter vndkConverter{};

struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
    std::string elementName() const override { return "sepolicy"; }
    void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
        appendChild(root, versionConverter(m, d));
    }
    bool buildObject(Version *object, NodeType *root) const override {
        return parseChild(root, versionConverter, object);
    }
};
const HalManifestSepolicyConverter halManifestSepolicyConverter{};

struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
    std::string elementName() const override { return "xmlfile"; }
    void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
        appendTextElement(root, "name", f.name(), d);
        appendChild(root, versionConverter(f.version(), d));
        if (!f.overriddenPath().empty()) {
            appendTextElement(root, "path", f.overriddenPath(), d);
        }
    }
    bool buildObject(ManifestXmlFile* object, NodeType* root) const override {
        if (!parseTextElement(root, "name", &object->mName) ||
            !parseChild(root, versionConverter, &object->mVersion) ||
            !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) {
            return false;
        }
        return true;
    }
};
const ManifestXmlFileConverter manifestXmlFileConverter{};

struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
    std::string elementName() const override { return "manifest"; }
    void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
        appendAttr(root, "version", HalManifest::kVersion);
        appendAttr(root, "type", m.mType);

        appendChildren(root, manifestHalConverter, m.getHals(), d);
        if (m.mType == SchemaType::DEVICE) {
            appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
        } else if (m.mType == SchemaType::FRAMEWORK) {
            appendChildren(root, vndkConverter, m.framework.mVndks, d);
        }

        appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
    }
    bool buildObject(HalManifest *object, NodeType *root) const override {
        Version version;
        std::vector<ManifestHal> hals;
        if (!parseAttr(root, "version", &version) ||
            !parseAttr(root, "type", &object->mType) ||
            !parseChildren(root, manifestHalConverter, &hals)) {
            return false;
        }
        if (version != HalManifest::kVersion) {
            this->mLastError = "Unrecognized manifest.version";
            return false;
        }
        if (object->mType == SchemaType::DEVICE) {
            // tags for device hal manifest only.
            // <sepolicy> can be missing because it can be determined at build time, not hard-coded
            // in the XML file.
            if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
                    &object->device.mSepolicyVersion)) {
                return false;
            }
        } else if (object->mType == SchemaType::FRAMEWORK) {
            if (!parseChildren(root, vndkConverter, &object->framework.mVndks)) {
                return false;
            }
            for (const auto &vndk : object->framework.mVndks) {
                if (!vndk.mVersionRange.isSingleVersion()) {
                    this->mLastError = "vndk.version " + to_string(vndk.mVersionRange)
                            + " cannot be a range for manifests";
                    return false;
                }
            }
        }
        for (auto &&hal : hals) {
            std::string description{hal.name};
            if (!object->add(std::move(hal))) {
                this->mLastError = "Duplicated manifest.hal entry " + description;
                return false;
            }
        }

        std::vector<ManifestXmlFile> xmlFiles;
        if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles)) {
            return false;
        }
        for (auto&& xmlFile : xmlFiles) {
            std::string description{xmlFile.name()};
            if (!object->addXmlFile(std::move(xmlFile))) {
                this->mLastError = "Duplicated manifest.xmlfile entry " + description +
                                   "; entries cannot have duplicated name and version";
                return false;
            }
        }

        return true;
    }
};

const HalManifestConverter halManifestConverter{};

const XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
struct AvbConverter : public XmlNodeConverter<Version> {
    std::string elementName() const override { return "avb"; }
    void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
        appendChild(root, avbVersionConverter(m, d));
    }
    bool buildObject(Version *object, NodeType *root) const override {
        return parseChild(root, avbVersionConverter, object);
    }
};
const AvbConverter avbConverter{};

struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
    std::string elementName() const override { return "xmlfile"; }
    void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
        appendTextElement(root, "name", f.name(), d);
        appendAttr(root, "format", f.format());
        appendAttr(root, "optional", f.optional());
        appendChild(root, versionRangeConverter(f.versionRange(), d));
        if (!f.overriddenPath().empty()) {
            appendTextElement(root, "path", f.overriddenPath(), d);
        }
    }
    bool buildObject(MatrixXmlFile* object, NodeType* root) const override {
        if (!parseTextElement(root, "name", &object->mName) ||
            !parseAttr(root, "format", &object->mFormat) ||
            !parseOptionalAttr(root, "optional", false, &object->mOptional) ||
            !parseChild(root, versionRangeConverter, &object->mVersionRange) ||
            !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) {
            return false;
        }
        return true;
    }
};
const MatrixXmlFileConverter matrixXmlFileConverter{};

struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
    std::string elementName() const override { return "compatibility-matrix"; }
    void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
        appendAttr(root, "version", CompatibilityMatrix::kVersion);
        appendAttr(root, "type", m.mType);
        appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
        if (m.mType == SchemaType::FRAMEWORK) {
            appendChildren(root, matrixKernelConverter, m.framework.mKernels, d);
            appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
            appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
        } else if (m.mType == SchemaType::DEVICE) {
            appendChild(root, vndkConverter(m.device.mVndk, d));
        }

        appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
    }
    bool buildObject(CompatibilityMatrix *object, NodeType *root) const override {
        Version version;
        std::vector<MatrixHal> hals;
        if (!parseAttr(root, "version", &version) ||
            !parseAttr(root, "type", &object->mType) ||
            !parseChildren(root, matrixHalConverter, &hals)) {
            return false;
        }

        if (object->mType == SchemaType::FRAMEWORK) {
            // <avb> and <sepolicy> can be missing because it can be determined at build time, not
            // hard-coded in the XML file.
            if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels) ||
                !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy) ||
                !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion)) {
                return false;
            }

            std::set<Version> seenKernelVersions;
            for (const auto& kernel : object->framework.mKernels) {
                Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
                if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
                    continue;
                }
                if (!kernel.conditions().empty()) {
                    this->mLastError = "First <kernel> for version " + to_string(minLts) +
                                       " must have empty <conditions> for backwards compatibility.";
                    return false;
                }
                seenKernelVersions.insert(minLts);
            }

        } else if (object->mType == SchemaType::DEVICE) {
            // <vndk> can be missing because it can be determined at build time, not hard-coded
            // in the XML file.
            if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk)) {
                return false;
            }
        }

        if (version != CompatibilityMatrix::kVersion) {
            this->mLastError = "Unrecognized compatibility-matrix.version";
            return false;
        }
        for (auto &&hal : hals) {
            if (!object->add(std::move(hal))) {
                this->mLastError = "Duplicated compatibility-matrix.hal entry";
                return false;
            }
        }

        std::vector<MatrixXmlFile> xmlFiles;
        if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles)) {
            return false;
        }
        for (auto&& xmlFile : xmlFiles) {
            if (!xmlFile.optional()) {
                this->mLastError = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
                                   " has to be optional for compatibility matrix version 1.0";
                return false;
            }
            std::string description{xmlFile.name()};
            if (!object->addXmlFile(std::move(xmlFile))) {
                this->mLastError = "Duplicated compatibility-matrix.xmlfile entry " + description;
                return false;
            }
        }

        return true;
    }
};

const CompatibilityMatrixConverter compatibilityMatrixConverter{};

// Publicly available as in parse_xml.h
const XmlConverter<HalManifest> &gHalManifestConverter = halManifestConverter;
const XmlConverter<CompatibilityMatrix> &gCompatibilityMatrixConverter
        = compatibilityMatrixConverter;

// For testing in LibVintfTest
const XmlConverter<Version> &gVersionConverter = versionConverter;
const XmlConverter<KernelConfigTypedValue> &gKernelConfigTypedValueConverter
        = kernelConfigTypedValueConverter;
const XmlConverter<MatrixHal> &gMatrixHalConverter = matrixHalConverter;
const XmlConverter<ManifestHal> &gManifestHalConverter = manifestHalConverter;

} // namespace vintf
} // namespace android
