xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
				      xmlSchemaTypePtr type)
{
    xmlSchemaTypePtr base;

    /*
    * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
    * temporarily only.
    */
    base = type->baseType;
    if (! WXS_IS_COMPLEX(base)) {
	xmlSchemaCustomErr(ACTXT_CAST ctxt,
	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
	    type->node, WXS_BASIC_CAST type,
	    "The base type must be a complex type", NULL, NULL);
	return(ctxt->err);
    }
    if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
	/*
	* SPEC (1) "The {base type definition} must be a complex type
	* definition whose {final} does not contain restriction."
	*/
	xmlSchemaCustomErr(ACTXT_CAST ctxt,
	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
	    type->node, WXS_BASIC_CAST type,
	    "The 'final' of the base type definition "
	    "contains 'restriction'", NULL, NULL);
	return (ctxt->err);
    }
    /*
    * SPEC (2), (3) and (4)
    * Those are handled in a separate function, since the
    * same constraints are needed for redefinition of
    * attribute groups as well.
    */
    if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
	XML_SCHEMA_ACTION_DERIVE,
	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
	type->attrUses, base->attrUses,
	type->attributeWildcard,
	base->attributeWildcard) == -1)
    {
	return(-1);
    }
    /*
    * SPEC (5) "One of the following must be true:"
    */
    if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
	/*
	* SPEC (5.1) "The {base type definition} must be the
	* `ur-type definition`."
	* PASS
	*/
    } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
	/*
	* SPEC (5.2.1) "The {content type} of the complex type definition
	* must be a simple type definition"
	*
	* SPEC (5.2.2) "One of the following must be true:"
	*/
	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
	{
	    int err;
	    /*
	    * SPEC (5.2.2.1) "The {content type} of the {base type
	    * definition} must be a simple type definition from which
	    * the {content type} is validly derived given the empty
	    * set as defined in Type Derivation OK (Simple) ($3.14.6)."
	    *
	    * ATTENTION TODO: This seems not needed if the type implicitely
	    * derived from the base type.
	    *
	    */
	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
		type->contentTypeDef, base->contentTypeDef, 0);
	    if (err != 0) {
		xmlChar *strA = NULL, *strB = NULL;

		if (err == -1)
		    return(-1);
		xmlSchemaCustomErr(ACTXT_CAST ctxt,
		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
		    NULL, WXS_BASIC_CAST type,
		    "The {content type} %s is not validly derived from the "
		    "base type's {content type} %s",
		    xmlSchemaGetComponentDesignation(&strA,
			type->contentTypeDef),
		    xmlSchemaGetComponentDesignation(&strB,
			base->contentTypeDef));
		FREE_AND_NULL(strA);
		FREE_AND_NULL(strB);
		return(ctxt->err);
	    }
	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
	    (xmlSchemaIsParticleEmptiable(
		(xmlSchemaParticlePtr) base->subtypes))) {
	    /*
	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
	    * and have a particle which is `emptiable` as defined in
	    * Particle Emptiable ($3.9.6)."
	    * PASS
	    */
	} else {
	    xmlSchemaPCustomErr(ctxt,
		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
		WXS_BASIC_CAST type, NULL,
		"The content type of the base type must be either "
		"a simple type or 'mixed' and an emptiable particle", NULL);
	    return (ctxt->err);
	}
    } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
	/*
	* SPEC (5.3.1) "The {content type} of the complex type itself must
	* be empty"
	*/
	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
	    /*
	    * SPEC (5.3.2.1) "The {content type} of the {base type
	    * definition} must also be empty."
	    * PASS
	    */
	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
	    xmlSchemaIsParticleEmptiable(
		(xmlSchemaParticlePtr) base->subtypes)) {
	    /*
	    * SPEC (5.3.2.2) "The {content type} of the {base type
	    * definition} must be elementOnly or mixed and have a particle
	    * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
	    * PASS
	    */
	} else {
	    xmlSchemaPCustomErr(ctxt,
		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
		WXS_BASIC_CAST type, NULL,
		"The content type of the base type must be either "
		"empty or 'mixed' (or 'elements-only') and an emptiable "
		"particle", NULL);
	    return (ctxt->err);
	}
    } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
	WXS_HAS_MIXED_CONTENT(type)) {
	/*
	* SPEC (5.4.1.1) "The {content type} of the complex type definition
	* itself must be element-only"
	*/
	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
	    /*
	    * SPEC (5.4.1.2) "The {content type} of the complex type
	    * definition itself and of the {base type definition} must be
	    * mixed"
	    */
	    xmlSchemaPCustomErr(ctxt,
		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
		WXS_BASIC_CAST type, NULL,
		"If the content type is 'mixed', then the content type of the "
		"base type must also be 'mixed'", NULL);
	    return (ctxt->err);
	}
	/*
	* SPEC (5.4.2) "The particle of the complex type definition itself
	* must be a `valid restriction` of the particle of the {content
	* type} of the {base type definition} as defined in Particle Valid
	* (Restriction) ($3.9.6).
	*
	* URGENT TODO: (5.4.2)
	*/
    } else {
	xmlSchemaPCustomErr(ctxt,
	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
	    WXS_BASIC_CAST type, NULL,
	    "The type is not a valid restriction of its base type", NULL);
	return (ctxt->err);
    }
    return (0);
}