in src/xercesc/validators/schema/TraverseSchema.cpp [3657:4031]
void TraverseSchema::traverseSimpleContentDecl(const XMLCh* const typeName,
const XMLCh* const qualifiedName,
const DOMElement* const contentDecl,
ComplexTypeInfo* const typeInfo,
Janitor<XSAnnotation>* const janAnnot)
{
NamespaceScopeManager nsMgr(contentDecl, fSchemaInfo, this);
// -----------------------------------------------------------------------
// Check Attributes
// -----------------------------------------------------------------------
bool preProcessFlag = typeInfo->getPreprocessed();
if (!preProcessFlag) {
fAttributeCheck.checkAttributes(
contentDecl, GeneralAttributeCheck::E_SimpleContent
, this, false, fNonXSAttList
);
}
// -----------------------------------------------------------------------
// Set the content type to be simple, and initialize content spec handle
// -----------------------------------------------------------------------
typeInfo->setContentType(SchemaElementDecl::Simple);
// -----------------------------------------------------------------------
// Process annotation if any
// -----------------------------------------------------------------------
DOMElement* simpleContent = checkContent(contentDecl, XUtil::getFirstChildElement(contentDecl), false, !preProcessFlag);
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(contentDecl, fNonXSAttList);
}
if (fAnnotation)
{
if (janAnnot->isDataNull())
janAnnot->reset(fAnnotation);
else
janAnnot->get()->setNext(fAnnotation);
}
// If there are no children, return
if (simpleContent == 0) {
reportSchemaError(contentDecl, XMLUni::fgXMLErrDomain, XMLErrs::EmptySimpleTypeContent);
throw TraverseSchema::InvalidComplexTypeInfo;
}
NamespaceScopeManager nsMgr2(simpleContent, fSchemaInfo, this);
// -----------------------------------------------------------------------
// The content should be either "restriction" or "extension"
// -----------------------------------------------------------------------
if (!preProcessFlag) {
const XMLCh* const contentName = simpleContent->getLocalName();
if (XMLString::equals(contentName, SchemaSymbols::fgATTVAL_RESTRICTION)) {
fAttributeCheck.checkAttributes(
simpleContent, GeneralAttributeCheck::E_Restriction
, this, false, fNonXSAttList
);
typeInfo->setDerivedBy(SchemaSymbols::XSD_RESTRICTION);
}
else if (XMLString::equals(contentName, SchemaSymbols::fgATTVAL_EXTENSION)) {
fAttributeCheck.checkAttributes(
simpleContent, GeneralAttributeCheck::E_Extension
, this, false, fNonXSAttList
);
typeInfo->setDerivedBy(SchemaSymbols::XSD_EXTENSION);
}
else {
reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContent);
throw TraverseSchema::InvalidComplexTypeInfo;
}
}
//Skip over any annotations in the restriction or extension elements
DOMElement* content = checkContent(simpleContent, XUtil::getFirstChildElement(simpleContent), true, !preProcessFlag);
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(simpleContent, fNonXSAttList);
}
if (fAnnotation)
{
if (janAnnot->isDataNull())
janAnnot->reset(fAnnotation);
else
janAnnot->get()->setNext(fAnnotation);
}
// -----------------------------------------------------------------------
// Handle the base type name
// -----------------------------------------------------------------------
const XMLCh* baseName = getElementAttValue(simpleContent, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName);
if (!baseName || !*baseName) {
reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::UnspecifiedBase);
throw TraverseSchema::InvalidComplexTypeInfo;
}
const XMLCh* prefix = getPrefix(baseName);
const XMLCh* localPart = getLocalPart(baseName);
const XMLCh* uri = resolvePrefixToURI(simpleContent, prefix);
// check for 'anyType'
if (XMLString::equals(uri, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)
&& XMLString::equals(localPart, SchemaSymbols::fgATTVAL_ANYTYPE)) {
reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContentBase, baseName);
throw TraverseSchema::InvalidComplexTypeInfo;
}
processBaseTypeInfo(simpleContent, baseName, localPart, uri, typeInfo);
ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo();
DatatypeValidator* baseValidator = typeInfo->getBaseDatatypeValidator();
if (baseValidator != 0 && baseTypeInfo == 0) {
// check that the simpleType does not preclude derivation by extension
if ((baseValidator->getFinalSet() & SchemaSymbols::XSD_EXTENSION) == typeInfo->getDerivedBy()) {
reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::DisallowedSimpleTypeExtension,
baseName, typeName);
throw TraverseSchema::InvalidComplexTypeInfo;
}
//Schema Spec: 5.11: Complex Type Definition Properties Correct: 2
if (typeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION) {
reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexTypeBase, baseName);
throw TraverseSchema::InvalidComplexTypeInfo;
}
}
// check that the base isn't a complex type with complex content
// and that derivation method is not included in 'final'
bool simpleTypeRequired = false;
if (baseTypeInfo) {
if (baseTypeInfo->getContentType() != SchemaElementDecl::Simple) {
// Schema Errata: E1-27
if (typeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION
&& ((baseTypeInfo->getContentType() == SchemaElementDecl::Mixed_Simple
|| baseTypeInfo->getContentType() == SchemaElementDecl::Mixed_Complex)
&& emptiableParticle(baseTypeInfo->getContentSpec()))) {
simpleTypeRequired = true;
}
else {
reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContentBase, baseName);
throw TraverseSchema::InvalidComplexTypeInfo;
}
}
if ((baseTypeInfo->getFinalSet() & typeInfo->getDerivedBy()) != 0) {
reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::ForbiddenDerivation, baseName);
throw TraverseSchema::InvalidComplexTypeInfo;
}
}
// -----------------------------------------------------------------------
// Process the content of the derivation
// -----------------------------------------------------------------------
if (typeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION) {
if(baseTypeInfo)
typeInfo->setBaseDatatypeValidator(baseTypeInfo->getDatatypeValidator());
if (content != 0) {
// ---------------------------------------------------------------
// There may be a simple type definition in the restriction
// element. The data type validator will be based on it, if
// specified
// ---------------------------------------------------------------
if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) {
DatatypeValidator* simpleTypeDV = traverseSimpleTypeDecl(content, false);
if (simpleTypeDV) {
// Check that the simpleType validator is validly derived
// from base
DatatypeValidator* baseDV = typeInfo->getBaseDatatypeValidator();
if (baseDV && !baseDV->isSubstitutableBy(simpleTypeDV)) {
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::InvalidContentRestriction);
throw TraverseSchema::InvalidComplexTypeInfo;
}
typeInfo->setBaseDatatypeValidator(simpleTypeDV);
content = XUtil::getNextSiblingElement(content);
}
else {
throw TraverseSchema::InvalidComplexTypeInfo;
}
}
// Schema Errata E1-27
// Complex Type Definition Restriction OK: 2.2
else if (simpleTypeRequired) {
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::CT_SimpleTypeChildRequired);
throw TraverseSchema::InvalidComplexTypeInfo;
}
// ---------------------------------------------------------------
// Build up the facet info
// ---------------------------------------------------------------
RefHashTableOf<KVStringPair>* facets = 0;
RefArrayVectorOf<XMLCh>* enums = 0;
XMLBuffer pattern(128, fGrammarPoolMemoryManager);
XMLCh fixedFlagStr[16];
unsigned int fixedFlag = 0;
unsigned short scope = 0;
bool isFirstPattern = true;
while (content != 0) {
const XMLCh* facetName = content->getLocalName();
bool bDoBreak=false; // workaround for Borland bug with 'break' in 'catch'
// if not a valid facet, break from the loop
try {
scope = fAttributeCheck.getFacetId(facetName, fMemoryManager);
}
catch(const OutOfMemoryException&)
{
throw;
}
catch(...) {
bDoBreak=true;
}
if(bDoBreak)
break;
if (content->getNodeType() == DOMNode::ELEMENT_NODE) {
fAttributeCheck.checkAttributes(content, scope, this);
const XMLCh* attValue = content->getAttribute(SchemaSymbols::fgATT_VALUE);
if (facets == 0) {
facets = new (fGrammarPoolMemoryManager) RefHashTableOf<KVStringPair>(29, true, fGrammarPoolMemoryManager);
}
if (XMLString::equals(facetName, SchemaSymbols::fgELT_ENUMERATION)) {
if (!enums) {
enums = new (fGrammarPoolMemoryManager) RefArrayVectorOf<XMLCh>(8, true, fGrammarPoolMemoryManager);
}
enums->addElement(XMLString::replicate(attValue, fGrammarPoolMemoryManager));
}
else if (XMLString::equals(facetName, SchemaSymbols::fgELT_PATTERN)) {
if (isFirstPattern) { // fBuffer.isEmpty() - overhead call
isFirstPattern = false;
pattern.set(attValue);
}
else { //datatypes: 5.2.4 pattern
pattern.append(chPipe);
pattern.append(attValue);
}
}
else {
if (facets->containsKey(facetName)) {
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateFacet, facetName);
}
else {
const XMLCh* facetNameStr =
fStringPool->getValueForId(fStringPool->addOrFind(facetName));
facets->put((void*) facetNameStr, new (fGrammarPoolMemoryManager) KVStringPair(facetNameStr, attValue, fGrammarPoolMemoryManager));
checkFixedFacet(content, facetNameStr, typeInfo->getBaseDatatypeValidator(), fixedFlag);
}
}
}
content = XUtil::getNextSiblingElement(content);
}
if (facets) {
if (!pattern.isEmpty()) {
facets->put
(
(void*) SchemaSymbols::fgELT_PATTERN,
new (fGrammarPoolMemoryManager) KVStringPair
(
SchemaSymbols::fgELT_PATTERN
, pattern.getRawBuffer()
, pattern.getLen()
, fGrammarPoolMemoryManager
)
);
}
if (fixedFlag) {
XMLString::binToText(fixedFlag, fixedFlagStr, 15, 10, fGrammarPoolMemoryManager);
facets->put((void*) SchemaSymbols::fgATT_FIXED,
new (fGrammarPoolMemoryManager) KVStringPair(SchemaSymbols::fgATT_FIXED, fixedFlagStr, fGrammarPoolMemoryManager));
}
try {
DatatypeValidator* simpleDV =
fDatatypeRegistry->createDatatypeValidator
(
qualifiedName,
typeInfo->getBaseDatatypeValidator(),
facets, enums, false, 0, true, fGrammarPoolMemoryManager
);
simpleDV->setAnonymous();
typeInfo->setDatatypeValidator(simpleDV);
}
catch (const XMLException& excep) {
reportSchemaError(simpleContent, excep);
}
catch(const OutOfMemoryException&)
{
throw;
}
catch(...) {
reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::DatatypeValidatorCreationError, typeName);
}
}
else {
typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator());
}
}
else {
// Schema Errata E1-27
// Complex Type Definition Restriction OK: 2.2
if (simpleTypeRequired) {
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::CT_SimpleTypeChildRequired);
throw TraverseSchema::InvalidComplexTypeInfo;
}
typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator());
}
} // end RESTRICTION
else { // EXTENSION
ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo();
if (baseTypeInfo!= 0) {
typeInfo->setBaseDatatypeValidator(baseTypeInfo->getDatatypeValidator());
}
typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator());
}
// -----------------------------------------------------------------------
// Process attributes if any
// -----------------------------------------------------------------------
processAttributes(simpleContent, content, typeInfo);
if (XUtil::getNextSiblingElement(simpleContent) != 0) {
reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInSimpleContent);
}
} // End of function traverseSimpleContentDecl