/*
 * 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 "Regex.h"
#include "constants.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 void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags) const {
        mutateNode(o, n, d);
    }
    virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
    virtual std::string elementName() const = 0;

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

        auto doc = createDocument(xml);
        if (doc == nullptr) {
            *error = "Not a valid XML";
            return false;
        }
        bool ret = deserialize(o, getRootChild(doc), error);
        deleteDocument(doc);
        return ret;
    }
    inline NodeType *operator()(const Object &o, DocType *d) const {
        return serialize(o, d);
    }
    inline std::string operator()(const Object& o, SerializeFlags flags) const override {
        return serialize(o, flags);
    }
    inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); }
    inline bool operator()(Object* o, const std::string& xml) override {
        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,
                               SerializeFlags flags = SerializeFlag::EVERYTHING) const {
        for (const T &t : array) {
            appendChild(parent, conv.serialize(t, d, flags));
        }
    }

    // All parse* functions helps buildObject() to deserialize XML to the object. Returns
    // true if deserialization is successful, false if any error, and "error" will be
    // set to error message.
    template <typename T>
    inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
                                  T* attr, std::string* /* error */) 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,
                          std::string* error) const {
        std::string attrText;
        bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
        if (!ret) {
            *error = "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,
                          std::string* error) const {
        bool ret = getAttr(root, attrName, attr);
        if (!ret) {
            *error = "Could not find attr with name \"" + attrName + "\" for element <" +
                     elementName() + ">";
        }
        return ret;
    }

    inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
                                 std::string* error) const {
        NodeType *child = getChild(root, elementName);
        if (child == nullptr) {
            *error = "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,
                                         std::string* /* error */) 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, std::string* /* error */) 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,
                           std::string* error) const {
        NodeType *child = getChild(root, conv.elementName());
        if (child == nullptr) {
            *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
                     this->elementName() + ">";
            return false;
        }
        return conv.deserialize(t, child, error);
    }

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

    template <typename T>
    inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
                              std::string* error) 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], error)) {
                *error = "Could not parse element with name <" + conv.elementName() +
                         "> in element <" + this->elementName() + ">: " + *error;
                return false;
            }
        }
        return true;
    }

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

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

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

   private:
    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, std::string* error) const override {
        return this->parseText(root, object, error);
    }
    virtual std::string elementName() const { return mElementName; };
private:
    std::string mElementName;
};

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

XmlTextConverter<Version> versionConverter{"version"};

XmlTextConverter<VersionRange> versionRangeConverter{"version"};

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, std::string* error) const override {
        if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
            !parseText(root, &object->transport, error)) {
            return false;
        }
        if (!object->isValid()) {
            *error = "transport == " + ::android::vintf::to_string(object->transport) +
                     " and arch == " + ::android::vintf::to_string(object->arch) +
                     " is not a valid combination.";
            return false;
        }
        return true;
    }
};

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,
                     std::string* error) const override {
        std::string stringValue;
        if (!parseAttr(root, "type", &object->mType, error) ||
            !parseText(root, &stringValue, error)) {
            return false;
        }
        if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
            *error = "Could not parse kernel config value \"" + stringValue + "\"";
            return false;
        }
        return true;
    }
};

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, std::string* error) const override {
        if (!parseChild(root, kernelConfigKeyConverter, &object->first, error) ||
            !parseChild(root, kernelConfigTypedValueConverter, &object->second, error)) {
            return false;
        }
        return true;
    }
};

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.mInstances, d);
        appendTextElements(root, "regex-instance", intf.mRegexes, d);
    }
    bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
        std::vector<std::string> instances;
        std::vector<std::string> regexes;
        if (!parseTextElement(root, "name", &intf->mName, error) ||
            !parseTextElements(root, "instance", &instances, error) ||
            !parseTextElements(root, "regex-instance", &regexes, error)) {
            return false;
        }
        bool success = true;
        for (const auto& e : instances) {
            if (!intf->insertInstance(e, false /* isRegex */)) {
                if (!error->empty()) *error += "\n";
                *error += "Duplicated instance '" + e + "' in " + intf->name();
                success = false;
            }
        }
        for (const auto& e : regexes) {
            details::Regex regex;
            if (!regex.compile(e)) {
                if (!error->empty()) *error += "\n";
                *error += "Invalid regular expression '" + e + "' in " + intf->name();
                success = false;
            }
            if (!intf->insertInstance(e, true /* isRegex */)) {
                if (!error->empty()) *error += "\n";
                *error += "Duplicated regex-instance '" + e + "' in " + intf->name();
                success = false;
            }
        }
        return success;
    }
};

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, std::string* error) const override {
        std::vector<HalInterface> interfaces;
        if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
            !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
                               error) ||
            !parseTextElement(root, "name", &object->name, error) ||
            !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
            !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
            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) {
                *error = "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.
#ifndef LIBVINTF_TARGET
        if (!checkAdditionalRestrictionsOnHal(*object, error)) {
            return false;
        }
#endif
        return true;
    }

#ifndef LIBVINTF_TARGET
   private:
    bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
        if (hal.getName() == "netutils-wrapper") {
            if (hal.versionRanges.size() != 1) {
                *error =
                    "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()) {
                *error =
                    "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) {
                *error =
                    "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
};

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,
                     std::string* error) const override {
        return parseChildren(root, kernelConfigConverter, object, error);
    }
};

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, std::string* error) const override {
        if (!parseAttr(root, "version", &object->mMinLts, error) ||
            !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
                                error) ||
            !parseChildren(root, kernelConfigConverter, &object->mConfigs, error)) {
            return false;
        }
        return true;
    }
};

MatrixKernelConverter matrixKernelConverter{};

XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};

struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
    std::string elementName() const override { return "hal"; }
    void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
        mutateNode(m, root, d, SerializeFlag::EVERYTHING);
    }
    void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
                    SerializeFlags flags) const override {
        appendAttr(root, "format", hal.format);
        appendTextElement(root, "name", hal.name, d);
        appendChild(root, transportArchConverter(hal.transportArch, d));
        appendChildren(root, versionConverter, hal.versions, d);
        appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
        if (hal.isOverride()) {
            appendAttr(root, "override", hal.isOverride());
        }

        if (!(flags & SerializeFlag::NO_FQNAME)) {
            std::set<FqInstance> fqInstances;
            hal.forEachInstance([&fqInstances](const auto& manifestInstance) {
                fqInstances.emplace(manifestInstance.getFqInstanceNoPackage());
                return true;
            });
            appendChildren(root, fqInstanceConverter, fqInstances, d);
        }
    }
    bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
        std::vector<HalInterface> interfaces;
        if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
            !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
            !parseTextElement(root, "name", &object->name, error) ||
            !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
            !parseChildren(root, versionConverter, &object->versions, error) ||
            !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
            return false;
        }

        switch (object->format) {
            case HalFormat::HIDL: {
                if (object->transportArch.empty()) {
                    *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
                    return false;
                }
            } break;
            case HalFormat::NATIVE: {
                if (!object->transportArch.empty()) {
                    *error =
                        "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) {
                *error = "Duplicated interface entry \"" + res.first->first +
                         "\"; if additional instances are needed, add them to the "
                         "existing <interface> node.";
                return false;
            }
        }
        if (!object->isValid()) {
            *error = "'" + object->name + "' is not a valid Manifest HAL.";
            return false;
        }
// Do not check for target-side libvintf to avoid restricting upgrade accidentally.
#ifndef LIBVINTF_TARGET
        if (!checkAdditionalRestrictionsOnHal(*object, error)) {
            return false;
        }
#endif

        std::set<FqInstance> fqInstances;
        if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
            return false;
        }
        if (!object->insertInstances(fqInstances, error)) {
            return false;
        }

        return true;
    }

#ifndef LIBVINTF_TARGET
   private:
    bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
        if (hal.getName() == "netutils-wrapper") {
            for (const Version& v : hal.versions) {
                if (v.minorVer != 0) {
                    *error =
                        "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.
ManifestHalConverter manifestHalConverter{};

XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
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, std::string* error) const override {
        if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
                        error) ||
            !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
                           error)) {
            return false;
        }
        return true;
    }
};
SepolicyConverter sepolicyConverter{};

[[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};

XmlTextConverter<std::string> vndkVersionConverter{"version"};
XmlTextConverter<std::string> vndkLibraryConverter{"library"};

struct [[deprecated]] 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, std::string* error) const override {
        if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
            !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
            return false;
        }
        return true;
    }
};

[[deprecated]] VndkConverter vndkConverter{};

struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
    std::string elementName() const override { return "vendor-ndk"; }
    void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
        appendChild(root, vndkVersionConverter(object.mVersion, d));
        appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
    }
    bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
        if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
            !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
            return false;
        }
        return true;
    }
};

VendorNdkConverter vendorNdkConverter{};

XmlTextConverter<std::string> systemSdkVersionConverter{"version"};

struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
    std::string elementName() const override { return "system-sdk"; }
    void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
        appendChildren(root, systemSdkVersionConverter, object.versions(), d);
    }
    bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
        return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
    }
};

SystemSdkConverter systemSdkConverter{};

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, std::string* error) const override {
        return parseChild(root, versionConverter, object, error);
    }
};
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, std::string* error) const override {
        if (!parseTextElement(root, "name", &object->mName, error) ||
            !parseChild(root, versionConverter, &object->mVersion, error) ||
            !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
            return false;
        }
        return true;
    }
};
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 {
        mutateNode(m, root, d, SerializeFlag::EVERYTHING);
    }
    void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
                    SerializeFlags flags) const override {
        appendAttr(root, "version", m.getMetaVersion());
        appendAttr(root, "type", m.mType);

        if (!(flags & SerializeFlag::NO_HALS)) {
            appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
        }
        if (m.mType == SchemaType::DEVICE) {
            if (!(flags & SerializeFlag::NO_SEPOLICY)) {
                appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
            }
            if (m.mLevel != Level::UNSPECIFIED) {
                this->appendAttr(root, "target-level", m.mLevel);
            }
        } else if (m.mType == SchemaType::FRAMEWORK) {
            if (!(flags & SerializeFlag::NO_VNDK)) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
                appendChildren(root, vndkConverter, m.framework.mVndks, d);
#pragma clang diagnostic pop

                appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
            }
            if (!(flags & SerializeFlag::NO_SSDK)) {
                if (!m.framework.mSystemSdk.empty()) {
                    appendChild(root, systemSdkConverter(m.framework.mSystemSdk, d));
                }
            }
        }

        if (!(flags & SerializeFlag::NO_XMLFILES)) {
            appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
        }
    }
    bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
        std::vector<ManifestHal> hals;
        if (!parseAttr(root, "version", &object->mMetaVersion, error) ||
            !parseAttr(root, "type", &object->mType, error) ||
            !parseChildren(root, manifestHalConverter, &hals, error)) {
            return false;
        }
        if (!kMetaVersion.minorAtLeast(object->mMetaVersion)) {
            *error = "Unrecognized manifest.version " + to_string(object->mMetaVersion) +
                     " (libvintf@" + to_string(kMetaVersion) + ")";
            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, error)) {
                return false;
            }

            if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
                                   error)) {
                return false;
            }
        } else if (object->mType == SchemaType::FRAMEWORK) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
                return false;
            }
            for (const auto &vndk : object->framework.mVndks) {
                if (!vndk.mVersionRange.isSingleVersion()) {
                    *error = "vndk.version " + to_string(vndk.mVersionRange) +
                             " cannot be a range for manifests";
                    return false;
                }
            }
#pragma clang diagnostic pop

            if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
                return false;
            }

            std::set<std::string> vendorNdkVersions;
            for (const auto& vendorNdk : object->framework.mVendorNdks) {
                if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
                    *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
                    return false;
                }
                vendorNdkVersions.insert(vendorNdk.version());
            }

            if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
                                    error)) {
                return false;
            }
        }
        for (auto &&hal : hals) {
            std::string description{hal.name};
            if (!object->add(std::move(hal))) {
                *error = "Duplicated manifest.hal entry " + description;
                return false;
            }
        }

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

        return true;
    }
};

HalManifestConverter halManifestConverter{};

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, std::string* error) const override {
        return parseChild(root, avbVersionConverter, object, error);
    }
};
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, std::string* error) const override {
        if (!parseTextElement(root, "name", &object->mName, error) ||
            !parseAttr(root, "format", &object->mFormat, error) ||
            !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
            !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
            !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
            return false;
        }
        return true;
    }
};
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 {
        mutateNode(m, root, d, SerializeFlag::EVERYTHING);
    }
    void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
                    SerializeFlags flags) const override {
        appendAttr(root, "version", m.getMinimumMetaVersion());
        appendAttr(root, "type", m.mType);

        if (!(flags & SerializeFlag::NO_HALS)) {
            appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
        }
        if (m.mType == SchemaType::FRAMEWORK) {
            if (!(flags & SerializeFlag::NO_KERNEL)) {
                appendChildren(root, matrixKernelConverter, m.framework.mKernels, d);
            }
            if (!(flags & SerializeFlag::NO_SEPOLICY)) {
                if (!(m.framework.mSepolicy == Sepolicy{})) {
                    appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
                }
            }
            if (!(flags & SerializeFlag::NO_AVB)) {
                if (!(m.framework.mAvbMetaVersion == Version{})) {
                    appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
                }
            }
            if (m.mLevel != Level::UNSPECIFIED) {
                this->appendAttr(root, "level", m.mLevel);
            }
        } else if (m.mType == SchemaType::DEVICE) {
            if (!(flags & SerializeFlag::NO_VNDK)) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
                if (!(m.device.mVndk == Vndk{})) {
                    appendChild(root, vndkConverter(m.device.mVndk, d));
                }
#pragma clang diagnostic pop

                if (!(m.device.mVendorNdk == VendorNdk{})) {
                    appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
                }
            }

            if (!(flags & SerializeFlag::NO_SSDK)) {
                if (!m.device.mSystemSdk.empty()) {
                    appendChild(root, systemSdkConverter(m.device.mSystemSdk, d));
                }
            }
        }

        if (!(flags & SerializeFlag::NO_XMLFILES)) {
            appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
        }
    }
    bool buildObject(CompatibilityMatrix* object, NodeType* root,
                     std::string* error) const override {
        Version version;
        std::vector<MatrixHal> hals;
        if (!parseAttr(root, "version", &version, error) ||
            !parseAttr(root, "type", &object->mType, error) ||
            !parseChildren(root, matrixHalConverter, &hals, error)) {
            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, error) ||
                !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
                                    error) ||
                !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
                                    error)) {
                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()) {
                    *error = "First <kernel> for version " + to_string(minLts) +
                             " must have empty <conditions> for backwards compatibility.";
                    return false;
                }
                seenKernelVersions.insert(minLts);
            }

            if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
                return false;
            }

        } 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.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
                return false;
            }
#pragma clang diagnostic pop

            if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
                                    error)) {
                return false;
            }

            if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
                                    error)) {
                return false;
            }
        }

        if (!kMetaVersion.minorAtLeast(version)) {
            *error = "Unrecognized compatibility-matrix.version " + to_string(version) +
                     " (libvintf@" + to_string(kMetaVersion) + ")";
            return false;
        }
        for (auto &&hal : hals) {
            if (!object->add(std::move(hal))) {
                *error = "Duplicated compatibility-matrix.hal entry";
                return false;
            }
        }

        std::vector<MatrixXmlFile> xmlFiles;
        if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
            return false;
        }
        for (auto&& xmlFile : xmlFiles) {
            if (!xmlFile.optional()) {
                *error = "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))) {
                *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
                return false;
            }
        }

        return true;
    }
};

CompatibilityMatrixConverter compatibilityMatrixConverter{};

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

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

} // namespace vintf
} // namespace android
