| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| /* |
| * $Id: UnionDatatypeValidator.cpp 568078 2007-08-21 11:43:25Z amassari $ |
| */ |
| |
| // --------------------------------------------------------------------------- |
| // Includes |
| // --------------------------------------------------------------------------- |
| #include <xercesc/validators/datatype/UnionDatatypeValidator.hpp> |
| #include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp> |
| #include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp> |
| #include <xercesc/util/OutOfMemoryException.hpp> |
| |
| #include <xercesc/internal/XTemplateSerializer.hpp> |
| |
| XERCES_CPP_NAMESPACE_BEGIN |
| |
| static const unsigned int BUF_LEN = 64; |
| |
| // --------------------------------------------------------------------------- |
| // Constructors and Destructor |
| // --------------------------------------------------------------------------- |
| UnionDatatypeValidator::UnionDatatypeValidator(MemoryManager* const manager) |
| :DatatypeValidator(0, 0, 0, DatatypeValidator::Union, manager) |
| ,fEnumerationInherited(false) |
| ,fMemberTypesInherited(false) |
| ,fEnumeration(0) |
| ,fMemberTypeValidators(0) |
| ,fValidatedDatatype(0) |
| |
| {} |
| |
| UnionDatatypeValidator::~UnionDatatypeValidator() |
| { |
| cleanUp(); |
| } |
| |
| UnionDatatypeValidator::UnionDatatypeValidator( |
| RefVectorOf<DatatypeValidator>* const memberTypeValidators |
| , const int finalSet |
| , MemoryManager* const manager) |
| :DatatypeValidator(0, 0, finalSet, DatatypeValidator::Union, manager) |
| ,fEnumerationInherited(false) |
| ,fMemberTypesInherited(false) |
| ,fEnumeration(0) |
| ,fMemberTypeValidators(0) |
| ,fValidatedDatatype(0) |
| { |
| if ( !memberTypeValidators ) |
| { |
| ThrowXMLwithMemMgr(InvalidDatatypeFacetException |
| , XMLExcepts::FACET_Union_Null_memberTypeValidators, manager); |
| } |
| |
| // no pattern, no enumeration |
| fMemberTypeValidators = memberTypeValidators; |
| } |
| |
| typedef JanitorMemFunCall<UnionDatatypeValidator> CleanupType; |
| |
| UnionDatatypeValidator::UnionDatatypeValidator( |
| DatatypeValidator* const baseValidator |
| , RefHashTableOf<KVStringPair>* const facets |
| , RefArrayVectorOf<XMLCh>* const enums |
| , const int finalSet |
| , MemoryManager* const manager |
| , RefVectorOf<DatatypeValidator>* const memberTypeValidators |
| , const bool memberTypesInherited |
| ) |
| :DatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::Union, manager) |
| ,fEnumerationInherited(false) |
| ,fMemberTypesInherited(memberTypesInherited) |
| ,fEnumeration(0) |
| ,fMemberTypeValidators(memberTypeValidators) |
| ,fValidatedDatatype(0) |
| { |
| // |
| // baseValidator another UnionDTV from which, |
| // this UnionDTV is derived by restriction. |
| // it shall be not null |
| // |
| if (!baseValidator) |
| { |
| ThrowXMLwithMemMgr(InvalidDatatypeFacetException |
| , XMLExcepts::FACET_Union_Null_baseValidator, manager); |
| } |
| |
| if (baseValidator->getType() != DatatypeValidator::Union) |
| { |
| XMLCh value1[BUF_LEN+1]; |
| XMLString::binToText(baseValidator->getType(), value1, BUF_LEN, 10, manager); |
| ThrowXMLwithMemMgr1(InvalidDatatypeFacetException |
| , XMLExcepts::FACET_Union_invalid_baseValidatorType |
| , value1 |
| , manager); |
| } |
| |
| CleanupType cleanup(this, &UnionDatatypeValidator::cleanUp); |
| |
| try |
| { |
| init(baseValidator, facets, enums, manager); |
| } |
| catch(const OutOfMemoryException&) |
| { |
| // Don't cleanup when out of memory, since executing the |
| // code can cause problems. |
| cleanup.release(); |
| |
| throw; |
| } |
| |
| cleanup.release(); |
| } |
| |
| void UnionDatatypeValidator::init(DatatypeValidator* const baseValidator |
| , RefHashTableOf<KVStringPair>* const facets |
| , RefArrayVectorOf<XMLCh>* const enums |
| , MemoryManager* const manager) |
| { |
| if (enums) |
| setEnumeration(enums, false); |
| |
| // Set Facets if any defined |
| if (facets) |
| { |
| XMLCh* key; |
| XMLCh* value; |
| RefHashTableOfEnumerator<KVStringPair> e(facets, false, manager); |
| |
| while (e.hasMoreElements()) |
| { |
| KVStringPair pair = e.nextElement(); |
| key = pair.getKey(); |
| value = pair.getValue(); |
| |
| if (XMLString::equals(key, SchemaSymbols::fgELT_PATTERN)) |
| { |
| setPattern(value); |
| if (getPattern()) |
| setFacetsDefined(DatatypeValidator::FACET_PATTERN); |
| // do not construct regex until needed |
| } |
| else |
| { |
| ThrowXMLwithMemMgr1(InvalidDatatypeFacetException |
| , XMLExcepts::FACET_Invalid_Tag |
| , key |
| , manager); |
| } |
| }//while |
| |
| /*** |
| Schema constraint: Part I -- self checking |
| ***/ |
| // Nil |
| |
| /*** |
| Schema constraint: Part II base vs derived checking |
| ***/ |
| // check 4.3.5.c0 must: enumeration values from the value space of base |
| if ( ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0) && |
| (getEnumeration() !=0)) |
| { |
| int i = 0; |
| int enumLength = getEnumeration()->size(); |
| try |
| { |
| for ( ; i < enumLength; i++) |
| { |
| // ask parent do a complete check |
| // |
| // enum need NOT be passed this->checkContent() |
| // since there are no other facets for Union, parent |
| // checking is good enough. |
| // |
| baseValidator->validate(getEnumeration()->elementAt(i), (ValidationContext*)0, manager); |
| |
| } |
| } |
| |
| catch ( XMLException& ) |
| { |
| ThrowXMLwithMemMgr1(InvalidDatatypeFacetException |
| , XMLExcepts::FACET_enum_base |
| , getEnumeration()->elementAt(i) |
| , manager); |
| } |
| } |
| |
| }// End of Facet setting |
| |
| /*** |
| Inherit facets from base.facets |
| |
| The reason of this inheriting (or copying values) is to ease |
| schema constraint checking, so that we need NOT trace back to our |
| very first base validator in the hierachy. Instead, we are pretty |
| sure checking against immediate base validator is enough. |
| ***/ |
| |
| UnionDatatypeValidator *pBaseValidator = (UnionDatatypeValidator*) baseValidator; |
| |
| // inherit enumeration |
| if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) !=0) && |
| ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) == 0)) |
| { |
| setEnumeration(pBaseValidator->getEnumeration(), true); |
| } |
| |
| } |
| |
| // |
| // 1) the bottom level UnionDTV would check against |
| // pattern and enumeration as well |
| // 2) each UnionDTV(s) above the bottom level UnionDTV and |
| // below the native UnionDTV (the top level DTV) |
| // would check against pattern only. |
| // 3) the natvie Union DTV (the top level DTV) would invoke |
| // memberTypeValidator to validate |
| // |
| void UnionDatatypeValidator::checkContent(const XMLCh* const content |
| , ValidationContext* const context |
| , bool asBase |
| , MemoryManager* const manager) |
| { |
| |
| DatatypeValidator* bv = getBaseValidator(); |
| if (bv) |
| ((UnionDatatypeValidator*)bv)->checkContent(content, context, true, manager); |
| else |
| { // 3) native union type |
| // check content against each member type validator in Union |
| // report an error only in case content is not valid against all member datatypes. |
| // |
| bool memTypeValid = false; |
| for ( unsigned int i = 0; i < fMemberTypeValidators->size(); ++i ) |
| { |
| if ( memTypeValid ) |
| break; |
| |
| try |
| { |
| fMemberTypeValidators->elementAt(i)->validate(content, context, manager); |
| memTypeValid = true; |
| |
| //set the validator of the type actually used to validate the content |
| DatatypeValidator *dtv = fMemberTypeValidators->elementAt(i); |
| fValidatedDatatype = dtv; |
| // context will be null during schema construction |
| if(context) |
| context->setValidatingMemberType(dtv); |
| } |
| catch (XMLException&) |
| { |
| //absorbed |
| } |
| } // for |
| |
| if ( !memTypeValid ) |
| { |
| ThrowXMLwithMemMgr1(InvalidDatatypeValueException |
| , XMLExcepts::VALUE_no_match_memberType |
| , content |
| , manager); |
| //( "Content '"+content+"' does not match any union types" ); |
| } |
| } |
| |
| // 1) and 2). we check pattern first |
| if ( (getFacetsDefined() & DatatypeValidator::FACET_PATTERN ) != 0 ) |
| { |
| if (getRegex()->matches(content, manager) == false) |
| { |
| ThrowXMLwithMemMgr2(InvalidDatatypeValueException |
| , XMLExcepts::VALUE_NotMatch_Pattern |
| , content |
| , getPattern() |
| , manager); |
| } |
| } |
| |
| // if this is a base validator, we only need to check pattern facet |
| // all other facet were inherited by the derived type |
| if (asBase) |
| return; |
| |
| if ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0 && |
| (getEnumeration() != 0)) |
| { |
| |
| // If the content match (compare equal) any enumeration with |
| // any of the member types, it is considerd valid. |
| // |
| RefVectorOf<DatatypeValidator>* memberDTV = getMemberTypeValidators(); |
| RefArrayVectorOf<XMLCh>* tmpEnum = getEnumeration(); |
| unsigned int memberTypeNumber = memberDTV->size(); |
| unsigned int enumLength = tmpEnum->size(); |
| |
| for ( unsigned int memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex) |
| { |
| for ( unsigned int enumIndex = 0; enumIndex < enumLength; ++enumIndex) |
| { |
| try |
| { |
| if (memberDTV->elementAt(memberIndex)->compare(content, tmpEnum->elementAt(enumIndex), manager) == 0) |
| return; |
| } |
| catch (XMLException&) |
| { |
| //absorbed |
| } |
| } // for enumIndex |
| } // for memberIndex |
| |
| ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); |
| |
| } // enumeration |
| |
| } |
| |
| // |
| // |
| // |
| int UnionDatatypeValidator::compare(const XMLCh* const lValue |
| , const XMLCh* const rValue |
| , MemoryManager* const manager) |
| { |
| RefVectorOf<DatatypeValidator>* memberDTV = getMemberTypeValidators(); |
| unsigned int memberTypeNumber = memberDTV->size(); |
| |
| for ( unsigned int memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex) |
| { |
| if (memberDTV->elementAt(memberIndex)->compare(lValue, rValue, manager) ==0) |
| return 0; |
| } |
| |
| //REVISIT: what does it mean for UNION1 to be <less than> or <greater than> UNION2 ? |
| // As long as -1 or +1 indicates an unequality, return either of them is ok. |
| return -1; |
| } |
| |
| const RefArrayVectorOf<XMLCh>* UnionDatatypeValidator::getEnumString() const |
| { |
| return getEnumeration(); |
| } |
| |
| /*** |
| * 2.5.1.3 Union datatypes |
| * |
| * The canonical-lexical-representation for a ·union· datatype is defined as the lexical form |
| * in which the values have the canonical lexical representation of the appropriate ·memberTypes·. |
| ***/ |
| const XMLCh* UnionDatatypeValidator::getCanonicalRepresentation(const XMLCh* const rawData |
| , MemoryManager* const memMgr |
| , bool toValidate) const |
| { |
| MemoryManager* toUse = memMgr? memMgr : getMemoryManager(); |
| UnionDatatypeValidator* temp = (UnionDatatypeValidator*) this; |
| |
| if (toValidate) |
| { |
| try |
| { |
| temp->checkContent(rawData, 0, false, toUse); |
| } |
| catch (...) |
| { |
| return 0; |
| } |
| } |
| |
| //get the native unionDv |
| UnionDatatypeValidator* bdv = (UnionDatatypeValidator*) temp->getBaseValidator(); |
| while (bdv) |
| { |
| temp = bdv; |
| bdv = (UnionDatatypeValidator*) temp->getBaseValidator(); |
| } |
| |
| //let the member dv which recognize the rawData, to return |
| //us the canonical form |
| for ( unsigned int i = 0; i < temp->fMemberTypeValidators->size(); ++i ) |
| { |
| try |
| { |
| temp->fMemberTypeValidators->elementAt(i)->validate(rawData, 0, toUse); |
| return temp->fMemberTypeValidators->elementAt(i)->getCanonicalRepresentation(rawData, toUse, false); |
| } |
| catch (XMLException&) |
| { |
| //absorbed |
| } |
| } |
| |
| //if no member dv recognize it |
| return 0; |
| } |
| |
| |
| /*** |
| * Support for Serialization/De-serialization |
| ***/ |
| |
| IMPL_XSERIALIZABLE_TOCREATE(UnionDatatypeValidator) |
| |
| void UnionDatatypeValidator::serialize(XSerializeEngine& serEng) |
| { |
| |
| DatatypeValidator::serialize(serEng); |
| |
| if (serEng.isStoring()) |
| { |
| serEng<<fEnumerationInherited; |
| serEng<<fMemberTypesInherited; |
| |
| /*** |
| * Serialize RefArrayVectorOf<XMLCh> |
| * Serialize RefVectorOf<DatatypeValidator> |
| ***/ |
| XTemplateSerializer::storeObject(fEnumeration, serEng); |
| XTemplateSerializer::storeObject(fMemberTypeValidators, serEng); |
| |
| DatatypeValidator::storeDV(serEng, fValidatedDatatype); |
| |
| } |
| else |
| { |
| serEng>>fEnumerationInherited; |
| serEng>>fMemberTypesInherited; |
| |
| /*** |
| * Deserialize RefArrayVectorOf<XMLCh> |
| * Deserialize RefVectorOf<DatatypeValidator> |
| ***/ |
| XTemplateSerializer::loadObject(&fEnumeration, 8, true, serEng); |
| XTemplateSerializer::loadObject(&fMemberTypeValidators, 4, false, serEng); |
| |
| fValidatedDatatype = DatatypeValidator::loadDV(serEng); |
| |
| } |
| } |
| |
| XERCES_CPP_NAMESPACE_END |
| |
| /** |
| * End of file UnionDatatypeValidator.cpp |
| */ |