/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtXmlPatterns module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qxsdvalidatinginstancereader_p.h"

#include "qabstractdatetime_p.h"
#include "qacceltreeresourceloader_p.h"
#include "qbase64binary_p.h"
#include "qboolean_p.h"
#include "qcommonnamespaces_p.h"
#include "qderivedinteger_p.h"
#include "qduration_p.h"
#include "qgenericstaticcontext_p.h"
#include "qhexbinary_p.h"
#include "qnamespaceresolver_p.h"
#include "qpatternplatform_p.h"
#include "qqnamevalue_p.h"
#include "qsourcelocationreflection_p.h"
#include "qvaluefactory_p.h"
#include "qxmlnamepool.h"
#include "qxmlquery_p.h"
#include "qxmlschema_p.h"
#include "qxsdschemahelper_p.h"
#include "qxsdschemamerger_p.h"
#include "qxsdstatemachine_p.h"
#include "qxsdstatemachinebuilder_p.h"
#include "qxsdtypechecker_p.h"

#include "qxsdschemadebugger_p.h"

#include <QtCore/QFile>
#include <QtXmlPatterns/QXmlQuery>
#include <QtXmlPatterns/QXmlResultItems>

QT_BEGIN_NAMESPACE

using namespace QPatternist;

namespace QPatternist
{
    template <>
    template <>
    bool XsdStateMachine<XsdTerm::Ptr>::inputEqualsTransition<QXmlName>(QXmlName name, XsdTerm::Ptr term) const
    {
        if (term->isElement()) {
            return (XsdElement::Ptr(term)->name(m_namePool) == name);
        } else if (term->isWildcard()) {
            // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
            if (name.namespaceURI() == StandardNamespaces::empty) {
                name.setNamespaceURI(m_namePool->allocateNamespace(XsdWildcard::absentNamespace()));
            }

            return XsdSchemaHelper::wildcardAllowsExpandedName(name, XsdWildcard::Ptr(term), m_namePool);
        }

        return false;
    }
}

XsdValidatingInstanceReader::XsdValidatingInstanceReader(XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context)
    : XsdInstanceReader(model, context)
    , m_model(model)
    , m_namePool(m_context->namePool())
    , m_xsiNilName(m_namePool->allocateQName(CommonNamespaces::XSI, QLatin1String("nil")))
    , m_xsiTypeName(m_namePool->allocateQName(CommonNamespaces::XSI, QLatin1String("type")))
    , m_xsiSchemaLocationName(m_namePool->allocateQName(CommonNamespaces::XSI, QLatin1String("schemaLocation")))
    , m_xsiNoNamespaceSchemaLocationName(m_namePool->allocateQName(CommonNamespaces::XSI, QLatin1String("noNamespaceSchemaLocation")))
    , m_documentUri(documentUri)
{
    m_idRefsType = m_context->schemaTypeFactory()->createSchemaType(m_namePool->allocateQName(CommonNamespaces::WXS, QLatin1String("IDREFS")));
}

void XsdValidatingInstanceReader::addSchema(const XsdSchema::Ptr &schema, const QUrl &locationUrl)
{
    if (!m_mergedSchemas.contains(locationUrl)) {
        m_mergedSchemas.insert(locationUrl, QStringList() << schema->targetNamespace());
    } else {
        QStringList &targetNamespaces = m_mergedSchemas[locationUrl];
        if (targetNamespaces.contains(schema->targetNamespace()))
            return;

        targetNamespaces.append(schema->targetNamespace());
    }

    const XsdSchemaMerger merger(m_schema, schema);
    m_schema = merger.mergedSchema();
/*
    XsdSchemaDebugger dbg(m_namePool);
    dbg.dumpSchema(m_schema);
*/
}

bool XsdValidatingInstanceReader::read()
{
    while (!atEnd()) {
        readNext();

        if (isEndElement())
            return true;

        if (isStartElement()) {
            const QXmlName elementName = name();
            const QXmlItem currentItem = item();
            bool hasStateMachine = false;
            XsdElement::Ptr processedElement;

            if (!validate(hasStateMachine, processedElement))
                return false;

            read();

            if (processedElement) { // for wildcard with 'skip' we have no element
                m_model->setAssignedElement(currentItem.toNodeModelIndex(), processedElement);

                // check identity constraints after all child nodes have been
                // validated, so that we know there assigned types
                validateIdentityConstraint(processedElement, currentItem);
            }

            if (!m_stateMachines.isEmpty() && hasStateMachine) {
                if (!m_stateMachines.top().inEndState()) {
                    error(QtXmlPatterns::tr("Element %1 is missing child element.").arg(formatKeyword(m_namePool->displayName(elementName))));
                    return false;
                }
                m_stateMachines.pop();
            }
        }
    }

    // final validations

    // check IDREF occurrences
    const QStringList ids = m_model->idIdRefBindingIds();
    for (const QString &id : qAsConst(m_idRefs)) {
        if (!ids.contains(id)) {
            error(QtXmlPatterns::tr("There is one IDREF value with no corresponding ID: %1.").arg(formatKeyword(id)));
            return false;
        }
    }

    return true;
}

void XsdValidatingInstanceReader::error(const QString &msg) const
{
    m_context.data()->error(msg, XsdSchemaContext::XSDError, sourceLocation());
}

bool XsdValidatingInstanceReader::loadSchema(const QString &targetNamespace, const QUrl &location)
{
    const AutoPtr<QNetworkReply> reply(AccelTreeResourceLoader::load(location, m_context->networkAccessManager(),
                                                                     m_context, AccelTreeResourceLoader::ContinueOnError));
    if (!reply)
        return true;

    // we have to create a separated schema context here, that however shares the type factory
    XsdSchemaContext::Ptr context(new XsdSchemaContext(m_namePool));
    context->m_schemaTypeFactory = m_context->m_schemaTypeFactory;

    QXmlSchemaPrivate schema(context);
    schema.load(reply.data(), location, targetNamespace);
    if (!schema.isValid()) {
        error(QtXmlPatterns::tr("Loaded schema file is invalid."));
        return false;
    }

    addSchema(schema.m_schemaParserContext->schema(), location);

    return true;
}

bool XsdValidatingInstanceReader::validate(bool &hasStateMachine, XsdElement::Ptr &processedElement)
{
    // first check if a custom schema is defined
    if (hasAttribute(m_xsiSchemaLocationName)) {
        const QString schemaLocation = attribute(m_xsiSchemaLocationName);
        const QStringList parts = schemaLocation.split(QLatin1Char(' '), Qt::SkipEmptyParts);
        if ((parts.count()%2) == 1) {
            error(QtXmlPatterns::tr("%1 contains invalid data.").arg(formatKeyword(m_namePool, m_xsiSchemaLocationName)));
            return false;
        }

        for (int i = 0; i < parts.count(); i += 2) {
            const QString identifier = QString::fromLatin1("%1 %2").arg(parts.at(i)).arg(parts.at(i + 1));
            if (m_processedSchemaLocations.contains(identifier))
                continue;
            else
                m_processedSchemaLocations.insert(identifier);

            // check constraint 4) from http://www.w3.org/TR/xmlschema-1/#schema-loc (only valid for XML Schema 1.0?)
            if (m_processedNamespaces.contains(parts.at(i))) {
                error(QtXmlPatterns::tr("xsi:schemaLocation namespace %1 has already appeared earlier in the instance document.").arg(formatKeyword(parts.at(i))));
                return false;
            }

            QUrl url(parts.at(i + 1));
            if (url.isRelative()) {
                Q_ASSERT(m_documentUri.isValid());

                url = m_documentUri.resolved(url);
            }

            loadSchema(parts.at(i), url);
        }
    }

    if (hasAttribute(m_xsiNoNamespaceSchemaLocationName)) {
        const QString schemaLocation = attribute(m_xsiNoNamespaceSchemaLocationName);

        if (!m_processedSchemaLocations.contains(schemaLocation)) {
            m_processedSchemaLocations.insert(schemaLocation);

            if (m_processedNamespaces.contains(QString())) {
                error(QtXmlPatterns::tr("xsi:noNamespaceSchemaLocation cannot appear after the first no-namespace element or attribute."));
                return false;
            }

            QUrl url(schemaLocation);
            if (url.isRelative()) {
                Q_ASSERT(m_documentUri.isValid());

                url = m_documentUri.resolved(url);
            }

            loadSchema(QString(), url);
        }
    }

    m_processedNamespaces.insert(m_namePool->stringForNamespace(name().namespaceURI()));

    if (!m_schema) {
        error(QtXmlPatterns::tr("No schema defined for validation."));
        return false;
    }

    // check if we are 'inside' a type definition
    if (m_stateMachines.isEmpty()) {
        // find out the type of the top-level element
        XsdElement::Ptr element = elementByName(name());
        if (!element) {
            if (!hasAttribute(m_xsiTypeName)) {
                error(QtXmlPatterns::tr("No definition for element %1 available.").arg(formatKeyword(m_namePool, name())));
                return false;
            }

            // This instance document has an element with no definition in the schema
            // but an explicitly given type, that is fine according to the spec.
            // We will create an element definition manually here and continue the
            // normal validation process
            element = XsdElement::Ptr(new XsdElement());
            element->setName(name());
            element->setIsAbstract(false);
            element->setIsNillable(hasAttribute(m_xsiNilName));

            const QString type = qNameAttribute(m_xsiTypeName);
            const QXmlName typeName = convertToQName(type);

            const SchemaType::Ptr elementType = typeByName(typeName);
            if (!elementType) {
                error(QtXmlPatterns::tr("Specified type %1 is not known to the schema.").arg(formatType(m_namePool, typeName)));
                return false;
            }
            element->setType(elementType);
        }

        // rememeber the element we process
        processedElement = element;

        if (!validateElement(element, hasStateMachine)) {
            return false;
        }

    } else {
        if (!m_stateMachines.top().proceed<QXmlName>(name())) {
            error(QtXmlPatterns::tr("Element %1 is not defined in this scope.").arg(formatKeyword(m_namePool, name())));
            return false;
        }

        const XsdTerm::Ptr term = m_stateMachines.top().lastTransition();
        if (term->isElement()) {
            const XsdElement::Ptr element(term);

            // rememeber the element we process
            processedElement = element;

            if (!validateElement(element, hasStateMachine))
                return false;

        } else {
            const XsdWildcard::Ptr wildcard(term);
            if (wildcard->processContents() != XsdWildcard::Skip) {
                XsdElement::Ptr elementDeclaration = elementByName(name());
                if (!elementDeclaration) {
                    if (hasAttribute(m_xsiTypeName)) {
                        // This instance document has an element with no definition in the schema
                        // but an explicitly given type, that is fine according to the spec.
                        // We will create an element definition manually here and continue the
                        // normal validation process
                        elementDeclaration = XsdElement::Ptr(new XsdElement());
                        elementDeclaration->setName(name());
                        elementDeclaration->setIsAbstract(false);
                        elementDeclaration->setIsNillable(hasAttribute(m_xsiNilName));

                        const QString type = qNameAttribute(m_xsiTypeName);
                        const QXmlName typeName = convertToQName(type);

                        const SchemaType::Ptr elementType = typeByName(typeName);
                        if (!elementType) {
                            error(QtXmlPatterns::tr("Specified type %1 is not known to the schema.").arg(formatType(m_namePool, typeName)));
                            return false;
                        }
                        elementDeclaration->setType(elementType);
                    }
                }

                if (!elementDeclaration) {
                    if (wildcard->processContents() == XsdWildcard::Strict) {
                        error(QtXmlPatterns::tr("Declaration for element %1 does not exist.").arg(formatKeyword(m_namePool->displayName(name()))));
                        return false;
                    } else {
                        // in this case we put a state machine for the xs:anyType on the statemachine stack,
                        // so we accept every content of this element

                        createAndPushStateMachine(anyType()->contentType()->particle());
                        hasStateMachine = true;
                    }
                } else {
                    if (!validateElement(elementDeclaration, hasStateMachine)) {
                        if (wildcard->processContents() == XsdWildcard::Strict) {
                            error(QtXmlPatterns::tr("Element %1 contains invalid content.").arg(formatKeyword(m_namePool->displayName(name()))));
                            return false;
                        }
                    }

                    // rememeber the type of that element node
                    m_model->setAssignedType(item().toNodeModelIndex(), elementDeclaration->type());
                }
            } else { // wildcard process contents type is Skip
                // in this case we put a state machine for the xs:anyType on the statemachine stack,
                // so we accept every content of this element

                const XsdWildcard::Ptr wildcard(new XsdWildcard());
                wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
                wildcard->setProcessContents(XsdWildcard::Skip);

                const XsdParticle::Ptr outerParticle(new XsdParticle());
                outerParticle->setMinimumOccurs(1);
                outerParticle->setMaximumOccurs(1);

                const XsdParticle::Ptr innerParticle(new XsdParticle());
                innerParticle->setMinimumOccurs(0);
                innerParticle->setMaximumOccursUnbounded(true);
                innerParticle->setTerm(wildcard);

                const XsdModelGroup::Ptr outerModelGroup(new XsdModelGroup());
                outerModelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
                outerModelGroup->setParticles(XsdParticle::List() << innerParticle);
                outerParticle->setTerm(outerModelGroup);

                createAndPushStateMachine(outerParticle);
                hasStateMachine = true;
            }
        }
    }

    return true;
}

void XsdValidatingInstanceReader::createAndPushStateMachine(const XsdParticle::Ptr &particle)
{
    XsdStateMachine<XsdTerm::Ptr> stateMachine(m_namePool);

    XsdStateMachineBuilder builder(&stateMachine, m_namePool, XsdStateMachineBuilder::ValidatingMode);
    const XsdStateMachine<XsdTerm::Ptr>::StateId endState = builder.reset();
    const XsdStateMachine<XsdTerm::Ptr>::StateId startState = builder.buildParticle(particle, endState);
    builder.addStartState(startState);

/*
    QString fileName = QString("/tmp/foo_%1.dot").arg(m_namePool->displayName(complexType->name(m_namePool)));
    QString pngFileName = QString("/tmp/foo_%1.png").arg(m_namePool->displayName(complexType->name(m_namePool)));
    QFile file(fileName);
    file.open(QIODevice::WriteOnly);
    stateMachine.outputGraph(&file, "Hello");
    file.close();
    ::system(QString("dot -Tpng %1 -o%2").arg(fileName).arg(pngFileName).toLatin1().data());
*/

    stateMachine = stateMachine.toDFA();

    m_stateMachines.push(stateMachine);
}

bool XsdValidatingInstanceReader::validateElement(const XsdElement::Ptr &declaration, bool &hasStateMachine)
{
    // http://www.w3.org/TR/xmlschema11-1/#d0e10998

    bool isNilled = false;

    // 1 tested already, 'declaration' corresponds D

    // 2
    if (declaration->isAbstract()) {
        error(QtXmlPatterns::tr("Element %1 is declared as abstract.").arg(formatKeyword(declaration->displayName(m_namePool))));
        return false;
    }

    // 3
    if (!declaration->isNillable()) {
        if (hasAttribute(m_xsiNilName)) {
            error(QtXmlPatterns::tr("Element %1 is not nillable.").arg(formatKeyword(declaration->displayName(m_namePool))));
            return false; // 3.1
        }
    } else {
        if (hasAttribute(m_xsiNilName)) {
            const QString value = attribute(m_xsiNilName);
            const Boolean::Ptr nil = Boolean::fromLexical(value);
            if (nil->hasError()) {
                error(QtXmlPatterns::tr("Attribute %1 contains invalid data: %2").arg(formatKeyword(QLatin1String("nil."))).arg(formatData(value)));
                return false;
            }

            // 3.2.3
            if (nil->as<Boolean>()->value() == true) {
                // 3.2.3.1
                if (hasChildElement() || hasChildText()) {
                    error(QtXmlPatterns::tr("Element contains content although it is nillable."));
                    return false;
                }

                // 3.2.3.2
                if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) {
                    error(QtXmlPatterns::tr("Fixed value constraint not allowed if element is nillable."));
                    return false;
                }
            }

            isNilled = nil->as<Boolean>()->value();
        }
    }

    SchemaType::Ptr finalElementType = declaration->type();

    // 4
    if (hasAttribute(m_xsiTypeName)) {
        const QString type = qNameAttribute(m_xsiTypeName);
        const QXmlName typeName = convertToQName(type);

        const SchemaType::Ptr elementType = typeByName(typeName);
        // 4.1
        if (!elementType) {
            error(QtXmlPatterns::tr("Specified type %1 is not known to the schema.").arg(formatType(m_namePool, typeName)));
            return false;
        }

        // 4.2
        SchemaType::DerivationConstraints constraints;
        if (declaration->disallowedSubstitutions() & NamedSchemaComponent::ExtensionConstraint)
            constraints |= SchemaType::ExtensionConstraint;
        if (declaration->disallowedSubstitutions() & NamedSchemaComponent::RestrictionConstraint)
            constraints |= SchemaType::RestrictionConstraint;

        if (!XsdSchemaHelper::isValidlySubstitutable(elementType, declaration->type(), constraints)) {
            if (declaration->type()->name(m_namePool) != BuiltinTypes::xsAnyType->name(m_namePool)) { // xs:anyType is a valid substitutable type here
                error(QtXmlPatterns::tr("Specified type %1 is not validly substitutable with element type %2.").arg(formatType(m_namePool, elementType)).arg(formatType(m_namePool, declaration->type())));
                return false;
            }
        }

        finalElementType = elementType;
    }

    if (!validateElementType(declaration, finalElementType, isNilled, hasStateMachine))
        return false;

    return true;
}

bool XsdValidatingInstanceReader::validateElementType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine)
{
    // @see http://www.w3.org/TR/xmlschema11-1/#d0e11749

    // 1 checked already

    // 2
    if (type->isComplexType() && type->isDefinedBySchema()) {
        if (XsdComplexType::Ptr(type)->isAbstract()) {
            error(QtXmlPatterns::tr("Complex type %1 is not allowed to be abstract.").arg(formatType(m_namePool, type)));
            return false;
        }
    }

    // 3
    if (type->isSimpleType())
        return validateElementSimpleType(declaration, type, isNilled); // 3.1
    else
        return validateElementComplexType(declaration, type, isNilled, hasStateMachine); // 3.2
}

bool XsdValidatingInstanceReader::validateElementSimpleType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled)
{
    // @see http://www.w3.org/TR/xmlschema11-1/#d0e11749

    // 3.1.1
    const QSet<QXmlName> allowedAttributes(QSet<QXmlName>() << m_xsiNilName << m_xsiTypeName << m_xsiSchemaLocationName << m_xsiNoNamespaceSchemaLocationName);
    QSet<QXmlName> elementAttributes = attributeNames();
    elementAttributes.subtract(allowedAttributes);
    if (!elementAttributes.isEmpty()) {
        error(QtXmlPatterns::tr("Element %1 contains not allowed attributes.").arg(formatKeyword(declaration->displayName(m_namePool))));
        return false;
    }

    // 3.1.2
    if (hasChildElement()) {
        error(QtXmlPatterns::tr("Element %1 contains not allowed child element.").arg(formatKeyword(declaration->displayName(m_namePool))));
        return false;
    }

    // 3.1.3
    if (!isNilled) {
        const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(type, m_context);

        QString actualValue;
        if (hasChildText()) {
            actualValue = XsdTypeChecker::normalizedValue(text(), facets);
        } else {
            if (declaration->valueConstraint())
                actualValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
        }

        QString errorMsg;
        AnySimpleType::Ptr boundType;

        const XsdTypeChecker checker(m_context, namespaceBindings(item().toNodeModelIndex()), sourceLocation());
        if (!checker.isValidString(actualValue, type, errorMsg, &boundType)) {
            error(QtXmlPatterns::tr("Content of element %1 does not match its type definition: %2.").arg(formatKeyword(declaration->displayName(m_namePool))).arg(errorMsg));
            return false;
        }

        // additional check
        if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) {
            const QString actualConstraintValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
            if (!text().isEmpty() && !checker.valuesAreEqual(actualValue, actualConstraintValue, type)) {
                error(QtXmlPatterns::tr("Content of element %1 does not match defined value constraint.").arg(formatKeyword(declaration->displayName(m_namePool))));
                return false;
            }
        }
    }

    // 4  checked in validateElement already

    // rememeber the type of that element node
    m_model->setAssignedType(item().toNodeModelIndex(), type);

    const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(type, m_context);
    const QString actualValue = XsdTypeChecker::normalizedValue(text(), facets);

    if (BuiltinTypes::xsID->wxsTypeMatches(type)) {
        addIdIdRefBinding(actualValue, declaration);
    }

    if (m_idRefsType->wxsTypeMatches(type)) {
        const QStringList idRefs = actualValue.split(QLatin1Char(' '), Qt::SkipEmptyParts);
        for (int i = 0; i < idRefs.count(); ++i) {
            m_idRefs.insert(idRefs.at(i));
        }
    } else if (BuiltinTypes::xsIDREF->wxsTypeMatches(type)) {
        m_idRefs.insert(actualValue);
    }

    return true;
}

static bool hasIDAttributeUse(const XsdAttributeUse::List &uses)
{
    const int count = uses.count();
    for (int i = 0; i < count; ++i) {
        if (BuiltinTypes::xsID->wxsTypeMatches(uses.at(i)->attribute()->type()))
            return true;
    }

    return false;
}

bool XsdValidatingInstanceReader::validateElementComplexType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine)
{
    // @see http://www.w3.org/TR/xmlschema11-1/#cvc-complex-type

    // 1
    if (!isNilled) {
        XsdComplexType::Ptr complexType;

        if (type->isDefinedBySchema()) {
            complexType = XsdComplexType::Ptr(type);
        } else {
            if (type->name(m_namePool) == BuiltinTypes::xsAnyType->name(m_namePool))
                complexType = anyType();
        }

        if (complexType) {
            // 1.1
            if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty) {
                if (hasChildText() || hasChildElement()) {
                    error(QtXmlPatterns::tr("Element %1 contains not allowed child content.").arg(formatKeyword(declaration->displayName(m_namePool))));
                    return false;
                }
            }

            // 1.2
            if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
                if (hasChildElement()) {
                    error(QtXmlPatterns::tr("Element %1 contains not allowed child element.").arg(formatKeyword(declaration->displayName(m_namePool))));
                    return false;
                }

                const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(complexType->contentType()->simpleType(), m_context);
                QString actualValue;
                if (hasChildText()) {
                    actualValue = XsdTypeChecker::normalizedValue(text(), facets);
                } else {
                    if (declaration->valueConstraint())
                        actualValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
                }

                QString errorMsg;
                AnySimpleType::Ptr boundType;
                const XsdTypeChecker checker(m_context, namespaceBindings(item().toNodeModelIndex()), sourceLocation());
                if (!checker.isValidString(actualValue, complexType->contentType()->simpleType(), errorMsg, &boundType)) {
                    error(QtXmlPatterns::tr("Content of element %1 does not match its type definition: %2.").arg(formatKeyword(declaration->displayName(m_namePool))).arg(errorMsg));
                    return false;
                }

                // additional check
                if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) {
                    if (!checker.valuesAreEqual(actualValue, declaration->valueConstraint()->value(), boundType)) {
                        error(QtXmlPatterns::tr("Content of element %1 does not match defined value constraint.").arg(formatKeyword(declaration->displayName(m_namePool))));
                        return false;
                    }
                }
            }

            // 1.3
            if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) {
                if (!text().simplified().isEmpty()) {
                    error(QtXmlPatterns::tr("Element %1 contains not allowed text content.").arg(formatKeyword(declaration->displayName(m_namePool))));
                    return false;
                }
            }

            // 1.4
            if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly ||
                complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed) {

                if (complexType->contentType()->particle()) {
                    createAndPushStateMachine(complexType->contentType()->particle());
                    hasStateMachine = true;
                }

                // additional check
                if (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed) {
                    if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) {
                        if (hasChildElement()) {
                            error(QtXmlPatterns::tr("Element %1 cannot contain other elements, as it has a fixed content.").arg(formatKeyword(declaration->displayName(m_namePool))));
                            return false;
                        }

                        const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(complexType->contentType()->simpleType(), m_context);
                        QString actualValue;
                        if (hasChildText()) {
                            actualValue = XsdTypeChecker::normalizedValue(text(), facets);
                        } else {
                            if (declaration->valueConstraint())
                                actualValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
                        }

                        if (actualValue != declaration->valueConstraint()->value()) {
                            error(QtXmlPatterns::tr("Content of element %1 does not match defined value constraint.").arg(formatKeyword(declaration->displayName(m_namePool))));
                            return false;
                        }
                    }
                }
            }
        }
    }

    if (type->isDefinedBySchema()) {
        const XsdComplexType::Ptr complexType(type);

        // create a lookup hash for faster access
        QHash<QXmlName, XsdAttributeUse::Ptr> attributeUseHash;
        {
            const XsdAttributeUse::List attributeUses = complexType->attributeUses();
            for (int i = 0; i < attributeUses.count(); ++i)
                attributeUseHash.insert(attributeUses.at(i)->attribute()->name(m_namePool), attributeUses.at(i));
        }

        const QSet<QXmlName> attributes(attributeNames());

        // 3
        for (auto it = attributeUseHash.cbegin(), end = attributeUseHash.cend(); it != end; ++it) {
            if (it.value()->isRequired()) {
                if (!attributes.contains(it.key())) {
                    error(QtXmlPatterns::tr("Element %1 is missing required attribute %2.").arg(formatKeyword(declaration->displayName(m_namePool)))
                                                                                          .arg(formatKeyword(m_namePool->displayName(it.key()))));
                    return false;
                }
            }
        }

        bool hasIDAttribute = hasIDAttributeUse(complexType->attributeUses());

        // 2
        for (const QXmlName &attributeName : attributes) {

            // skip builtin attributes
            if (attributeName == m_xsiNilName ||
                attributeName == m_xsiTypeName ||
                attributeName == m_xsiSchemaLocationName ||
                attributeName == m_xsiNoNamespaceSchemaLocationName)
                continue;

            // 2.1
            if (attributeUseHash.contains(attributeName) && (attributeUseHash.value(attributeName)->useType() != XsdAttributeUse::ProhibitedUse)) {
                if (!validateAttribute(attributeUseHash.value(attributeName), attribute(attributeName)))
                    return false;
            } else { // 2.2
                if (complexType->attributeWildcard()) {
                    const XsdWildcard::Ptr wildcard(complexType->attributeWildcard());
                    if (!validateAttributeWildcard(attributeName, wildcard)) {
                        error(QtXmlPatterns::tr("Attribute %1 does not match the attribute wildcard.").arg(formatKeyword(m_namePool->displayName(attributeName))));
                        return false;
                    }

                    if (wildcard->processContents() != XsdWildcard::Skip) {
                        const XsdAttribute::Ptr attributeDeclaration = attributeByName(attributeName);

                        if (!attributeDeclaration) {
                            if (wildcard->processContents() == XsdWildcard::Strict) {
                                error(QtXmlPatterns::tr("Declaration for attribute %1 does not exist.").arg(formatKeyword(m_namePool->displayName(attributeName))));
                                return false;
                            }
                        } else {
                            if (BuiltinTypes::xsID->wxsTypeMatches(attributeDeclaration->type())) {
                                if (hasIDAttribute) {
                                    error(QtXmlPatterns::tr("Element %1 contains two attributes of type %2.")
                                                           .arg(formatKeyword(declaration->displayName(m_namePool)))
                                                           .arg(formatKeyword("ID")));
                                    return false;
                                }

                                hasIDAttribute = true;
                            }

                            if (!validateAttribute(attributeDeclaration, attribute(attributeName))) {
                                if (wildcard->processContents() == XsdWildcard::Strict) {
                                    error(QtXmlPatterns::tr("Attribute %1 contains invalid content.").arg(formatKeyword(m_namePool->displayName(attributeName))));
                                    return false;
                                }
                            }
                        }
                    }
                } else {
                    error(QtXmlPatterns::tr("Element %1 contains unknown attribute %2.").arg(formatKeyword(declaration->displayName(m_namePool)))
                                                                                       .arg(formatKeyword(m_namePool->displayName(attributeName))));
                    return false;
                }
            }
        }
    }

    // 4
    // so what?...

    // 5
    // hmm...

    // 6
    // TODO: check assertions

    // 7
    // TODO: check type table restrictions

    // rememeber the type of that element node
    m_model->setAssignedType(item().toNodeModelIndex(), type);

    return true;
}

bool XsdValidatingInstanceReader::validateAttribute(const XsdAttributeUse::Ptr &declaration, const QString &value)
{
    const AnySimpleType::Ptr attributeType = declaration->attribute()->type();
    const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(attributeType, m_context);

    const QString actualValue = XsdTypeChecker::normalizedValue(value, facets);

    QString errorMsg;
    AnySimpleType::Ptr boundType;

    const QXmlNodeModelIndex index = attributeItem(declaration->attribute()->name(m_namePool)).toNodeModelIndex();

    const XsdTypeChecker checker(m_context, namespaceBindings(index), sourceLocation());
    if (!checker.isValidString(actualValue, attributeType, errorMsg, &boundType)) {
        error(QtXmlPatterns::tr("Content of attribute %1 does not match its type definition: %2.").arg(formatKeyword(declaration->attribute()->displayName(m_namePool))).arg(errorMsg));
        return false;
    }

    // @see http://www.w3.org/TR/xmlschema11-1/#cvc-au
    if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Fixed) {
        const QString actualConstraintValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
        if (!checker.valuesAreEqual(actualValue, actualConstraintValue, attributeType)) {
            error(QtXmlPatterns::tr("Content of attribute %1 does not match defined value constraint.").arg(formatKeyword(declaration->attribute()->displayName(m_namePool))));
            return false;
        }
    }

    if (BuiltinTypes::xsID->wxsTypeMatches(declaration->attribute()->type())) {
        addIdIdRefBinding(actualValue, declaration->attribute());
    }

    if (m_idRefsType->wxsTypeMatches(declaration->attribute()->type())) {
        const QStringList idRefs = actualValue.split(QLatin1Char(' '), Qt::SkipEmptyParts);
        for (int i = 0; i < idRefs.count(); ++i)
            m_idRefs.insert(idRefs.at(i));
    } else if (BuiltinTypes::xsIDREF->wxsTypeMatches(declaration->attribute()->type())) {
        m_idRefs.insert(actualValue);
    }

    m_model->setAssignedType(index, declaration->attribute()->type());
    m_model->setAssignedAttribute(index, declaration->attribute());

    return true;
}

//TODO: merge that with the method above
bool XsdValidatingInstanceReader::validateAttribute(const XsdAttribute::Ptr &declaration, const QString &value)
{
    const AnySimpleType::Ptr attributeType = declaration->type();
    const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(attributeType, m_context);

    const QString actualValue = XsdTypeChecker::normalizedValue(value, facets);

    QString errorMsg;
    AnySimpleType::Ptr boundType;

    const QXmlNodeModelIndex index = attributeItem(declaration->name(m_namePool)).toNodeModelIndex();

    const XsdTypeChecker checker(m_context, namespaceBindings(index), sourceLocation());
    if (!checker.isValidString(actualValue, attributeType, errorMsg, &boundType)) {
        error(QtXmlPatterns::tr("Content of attribute %1 does not match its type definition: %2.").arg(formatKeyword(declaration->displayName(m_namePool))).arg(errorMsg));
        return false;
    }

    // @see http://www.w3.org/TR/xmlschema11-1/#cvc-au
    if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdAttribute::ValueConstraint::Fixed) {
        const QString actualConstraintValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
        if (!checker.valuesAreEqual(actualValue, actualConstraintValue, attributeType)) {
            error(QtXmlPatterns::tr("Content of attribute %1 does not match defined value constraint.").arg(formatKeyword(declaration->displayName(m_namePool))));
            return false;
        }
    }

    if (BuiltinTypes::xsID->wxsTypeMatches(declaration->type())) {
        addIdIdRefBinding(actualValue, declaration);
    }

    if (m_idRefsType->wxsTypeMatches(declaration->type())) {
        const QStringList idRefs = actualValue.split(QLatin1Char(' '), Qt::SkipEmptyParts);
        for (int i = 0; i < idRefs.count(); ++i)
            m_idRefs.insert(idRefs.at(i));
    } else if (BuiltinTypes::xsIDREF->wxsTypeMatches(declaration->type())) {
        m_idRefs.insert(actualValue);
    }

    m_model->setAssignedType(index, declaration->type());
    m_model->setAssignedAttribute(index, declaration);

    return true;
}

bool XsdValidatingInstanceReader::validateAttributeWildcard(const QXmlName &attributeName, const XsdWildcard::Ptr &wildcard)
{
    // @see http://www.w3.org/TR/xmlschema11-1/#cvc-wildcard

    // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
    QXmlName name(attributeName);
    if (name.namespaceURI() == StandardNamespaces::empty) {
        name.setNamespaceURI(m_namePool->allocateNamespace(XsdWildcard::absentNamespace()));
    }

    return XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, m_namePool);
}

bool XsdValidatingInstanceReader::validateIdentityConstraint(const XsdElement::Ptr &element, const QXmlItem &currentItem)
{
    const XsdIdentityConstraint::List constraints = element->identityConstraints();

    for (int i = 0; i < constraints.count(); ++i) {
        const XsdIdentityConstraint::Ptr constraint = constraints.at(i);

        TargetNode::Set targetNodeSet, qualifiedNodeSet;
        selectNodeSets(element, currentItem, constraint, targetNodeSet, qualifiedNodeSet);

        if (constraint->category() == XsdIdentityConstraint::Unique) {
            if (!validateUniqueIdentityConstraint(element, constraint, qualifiedNodeSet))
                return false;
        } else if (constraint->category() == XsdIdentityConstraint::Key) {
            if (!validateKeyIdentityConstraint(element, constraint, targetNodeSet, qualifiedNodeSet))
                return false;
        }
    }

    // we do the keyref check in a separated run to make sure that all keys are available
    for (int i = 0; i < constraints.count(); ++i) {
        const XsdIdentityConstraint::Ptr constraint = constraints.at(i);
        if (constraint->category() == XsdIdentityConstraint::KeyReference) {
            TargetNode::Set targetNodeSet, qualifiedNodeSet;
            selectNodeSets(element, currentItem, constraint, targetNodeSet, qualifiedNodeSet);

            if (!validateKeyRefIdentityConstraint(element, constraint, qualifiedNodeSet))
                return false;
        }
    }

    return true;
}

bool XsdValidatingInstanceReader::validateUniqueIdentityConstraint(const XsdElement::Ptr&, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet)
{
    // @see http://www.w3.org/TR/xmlschema11-1/#d0e32243

    // 4.1
    const XsdSchemaSourceLocationReflection reflection(sourceLocation());

    for (auto it = qualifiedNodeSet.cbegin(), end = qualifiedNodeSet.cend(); it != end; ++it) {
        for (auto jt = qualifiedNodeSet.cbegin(); jt != it; ++jt) {
            if (it->fieldsAreEqual(*jt, m_namePool, m_context, &reflection)) {
                error(QtXmlPatterns::tr("Non-unique value found for constraint %1.").arg(formatKeyword(constraint->displayName(m_namePool))));
                return false;
            }
        }
    }

    m_idcKeys.insert(constraint->name(m_namePool), qualifiedNodeSet);

    return true;
}

bool XsdValidatingInstanceReader::validateKeyIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &targetNodeSet, const TargetNode::Set &qualifiedNodeSet)
{
    // @see http://www.w3.org/TR/xmlschema11-1/#d0e32243

    // 4.2
    const XsdSchemaSourceLocationReflection reflection(sourceLocation());

    // 4.2.1
    if (targetNodeSet.count() != qualifiedNodeSet.count()) {
        error(QtXmlPatterns::tr("Key constraint %1 contains absent fields.").arg(formatKeyword(constraint->displayName(m_namePool))));
        return false;
    }

    // 4.2.2
    if (!validateUniqueIdentityConstraint(element, constraint, qualifiedNodeSet))
        return false;

    // 4.2.3
    for (const TargetNode node : qualifiedNodeSet) {
        const QVector<QXmlItem> fieldItems = node.fieldItems();
        for (int i = 0; i < fieldItems.count(); ++i) {
            const QXmlNodeModelIndex index = fieldItems.at(i).toNodeModelIndex();
            if (m_model->kind(index) == QXmlNodeModelIndex::Element) {
                const XsdElement::Ptr declaration = m_model->assignedElement(index);
                if (declaration && declaration->isNillable()) {
                    error(QtXmlPatterns::tr("Key constraint %1 contains references nillable element %2.")
                                           .arg(formatKeyword(constraint->displayName(m_namePool)))
                                           .arg(formatKeyword(declaration->displayName(m_namePool))));
                    return false;
                }
            }
        }
    }

    m_idcKeys.insert(constraint->name(m_namePool), qualifiedNodeSet);

    return true;
}

bool XsdValidatingInstanceReader::validateKeyRefIdentityConstraint(const XsdElement::Ptr&, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet)
{
    // @see http://www.w3.org/TR/xmlschema11-1/#d0e32243

    // 4.3
    const XsdSchemaSourceLocationReflection reflection(sourceLocation());

    const TargetNode::Set keySet = m_idcKeys.value(constraint->referencedKey()->name(m_namePool));

    for (const TargetNode &node : qualifiedNodeSet) {

        bool foundMatching = false;

        for (const TargetNode &keyNode : keySet) {
            if (node.fieldsAreEqual(keyNode, m_namePool, m_context, &reflection)) {
                foundMatching = true;
                break;
            }
        }

        if (!foundMatching) {
            error(QtXmlPatterns::tr("No referenced value found for key reference %1.").arg(formatKeyword(constraint->displayName(m_namePool))));
            return false;
        }
    }

    return true;
}

QXmlQuery XsdValidatingInstanceReader::createXQuery(const QList<QXmlName> &namespaceBindings, const QXmlItem &contextNode, const QString &queryString) const
{
    // create a public name pool from our name pool
    QXmlNamePool namePool(m_namePool.data());

    // the QXmlQuery shall work with the same name pool as we do
    QXmlQuery query(namePool);

    // add additional namespace bindings
    QXmlQueryPrivate *queryPrivate = query.d;

    for (int i = 0; i < namespaceBindings.count(); ++i) {
        if (namespaceBindings.at(i).prefix() != StandardPrefixes::empty)
            queryPrivate->addAdditionalNamespaceBinding(namespaceBindings.at(i));
    }

    // set the context node for that query and the query string
    query.setFocus(contextNode);
    query.setQuery(queryString, m_documentUri);

    return query;
}

bool XsdValidatingInstanceReader::selectNodeSets(const XsdElement::Ptr&, const QXmlItem &currentItem, const XsdIdentityConstraint::Ptr &constraint, TargetNode::Set &targetNodeSet, TargetNode::Set &qualifiedNodeSet)
{
    // at first select all target nodes
    const XsdXPathExpression::Ptr selector = constraint->selector();
    const XsdXPathExpression::List fields = constraint->fields();

    QXmlQuery query = createXQuery(selector->namespaceBindings(), currentItem, selector->expression());

    QXmlResultItems resultItems;
    query.evaluateTo(&resultItems);

    // now we iterate over all target nodes and select the fields for each node
    QXmlItem item(resultItems.next());
    while (!item.isNull()) {

        TargetNode targetNode(item);

        for (int i = 0; i < fields.count(); ++i) {
            const XsdXPathExpression::Ptr field = fields.at(i);
            QXmlQuery fieldQuery = createXQuery(field->namespaceBindings(), item, field->expression());

            QXmlResultItems fieldResultItems;
            fieldQuery.evaluateTo(&fieldResultItems);

            // copy result into vetor for better testing...
            QVector<QXmlItem> fieldVector;
            QXmlItem fieldItem(fieldResultItems.next());
            while (!fieldItem.isNull()) {
                fieldVector.append(fieldItem);
                fieldItem = fieldResultItems.next();
            }

            if (fieldVector.count() > 1) {
                error(QtXmlPatterns::tr("More than one value found for field %1.").arg(formatData(field->expression())));
                return false;
            }

            if (fieldVector.count() == 1) {
                fieldItem = fieldVector.first();

                const QXmlNodeModelIndex index = fieldItem.toNodeModelIndex();
                const SchemaType::Ptr type = m_model->assignedType(index);
                Q_ASSERT(type);

                bool typeOk = true;
                if (type->isComplexType()) {
                    if (type->isDefinedBySchema()) {
                        if (XsdComplexType::Ptr(type)->contentType()->variety() != XsdComplexType::ContentType::Simple)
                            typeOk = false;
                    } else {
                        typeOk = false;
                    }
                }
                if (!typeOk) {
                    error(QtXmlPatterns::tr("Field %1 has no simple type.").arg(formatData(field->expression())));
                    return false;
                }

                SchemaType::Ptr targetType = type;
                QString value = m_model->stringValue(fieldItem.toNodeModelIndex());

                if (type->isDefinedBySchema()) {
                    if (type->isSimpleType())
                        targetType = XsdSimpleType::Ptr(type)->primitiveType();
                    else
                        targetType = XsdComplexType::Ptr(type)->contentType()->simpleType();

                    if (!targetType) {
                        // QTBUG-77620: pattern type within a union doesn't get
                        // its primitive type set.  FIXME: find root cause and
                        // fix that, so we can remove this (and an XFAIL).
                        error(QtXmlPatterns::tr("Field %1 is missing its simple type.")
                                                        .arg(formatData(field->expression())));
                        return false;
                    }
                } else {
                    if (BuiltinTypes::xsAnySimpleType->name(m_namePool) == type->name(m_namePool)) {
                        targetType = BuiltinTypes::xsString;
                        value = QLatin1String("___anySimpleType_value");
                    }
                }

                // if it is xs:QName derived type, we normalize the name content
                // and do a string comparison
                if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
                    targetType = BuiltinTypes::xsString;

                    const QXmlName qName = convertToQName(value.trimmed());
                    value = QString::fromLatin1("%1:%2").arg(m_namePool->stringForNamespace(qName.namespaceURI())).arg(m_namePool->stringForLocalName(qName.localName()));
                }

                targetNode.addField(fieldItem, value, targetType);
            } else {
                // we add an empty entry here, that makes comparison easier later on
                targetNode.addField(QXmlItem(), QString(), SchemaType::Ptr());
            }
        }

        targetNodeSet.insert(targetNode);

        item = resultItems.next();
    }

    // copy all items from target node set to qualified node set, that have no empty fields
    for (const TargetNode &node : qAsConst(targetNodeSet)) {
        if (node.emptyFieldsCount() == 0)
            qualifiedNodeSet.insert(node);
    }

    return true;
}

XsdElement::Ptr XsdValidatingInstanceReader::elementByName(const QXmlName &name) const
{
    return m_schema->element(name);
}

XsdAttribute::Ptr XsdValidatingInstanceReader::attributeByName(const QXmlName &name) const
{
    return m_schema->attribute(name);
}

SchemaType::Ptr XsdValidatingInstanceReader::typeByName(const QXmlName &name) const
{
    const SchemaType::Ptr type = m_schema->type(name);
    if (type)
        return type;

    return m_context->schemaTypeFactory()->createSchemaType(name);
}

void XsdValidatingInstanceReader::addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding)
{
    if (!m_model->idIdRefBindings(id).isEmpty()) {
        error(QtXmlPatterns::tr("ID value '%1' is not unique.").arg(formatKeyword(id)));
        return;
    }

    m_model->addIdIdRefBinding(id, binding);
}

QString XsdValidatingInstanceReader::qNameAttribute(const QXmlName &attributeName)
{
    const QString value = attribute(attributeName).simplified();
    if (!XPathHelper::isQName(value)) {
        error(QtXmlPatterns::tr("'%1' attribute contains invalid QName content: %2.").arg(m_namePool->displayName(attributeName)).arg(formatData(value)));
        return QString();
    } else {
        return value;
    }
}

XsdComplexType::Ptr XsdValidatingInstanceReader::anyType()
{
    if (m_anyType)
        return m_anyType;

    const XsdWildcard::Ptr wildcard(new XsdWildcard());
    wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
    wildcard->setProcessContents(XsdWildcard::Lax);

    const XsdParticle::Ptr outerParticle(new XsdParticle());
    outerParticle->setMinimumOccurs(1);
    outerParticle->setMaximumOccurs(1);

    const XsdParticle::Ptr innerParticle(new XsdParticle());
    innerParticle->setMinimumOccurs(0);
    innerParticle->setMaximumOccursUnbounded(true);
    innerParticle->setTerm(wildcard);

    const XsdModelGroup::Ptr outerModelGroup(new XsdModelGroup());
    outerModelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
    outerModelGroup->setParticles(XsdParticle::List() << innerParticle);
    outerParticle->setTerm(outerModelGroup);

    m_anyType = XsdComplexType::Ptr(new XsdComplexType());
    m_anyType->setName(BuiltinTypes::xsAnyType->name(m_namePool));
    m_anyType->setDerivationMethod(XsdComplexType::DerivationRestriction);
    m_anyType->contentType()->setVariety(XsdComplexType::ContentType::Mixed);
    m_anyType->contentType()->setParticle(outerParticle);
    m_anyType->setAttributeWildcard(wildcard);
    m_anyType->setIsAbstract(false);

    return m_anyType;
}

QT_END_NAMESPACE
