GME  13
UnionDatatypeValidator.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  * 
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  * 
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: UnionDatatypeValidator.cpp 677559 2008-07-17 11:35:27Z amassari $
00020  */
00021 
00022 // ---------------------------------------------------------------------------
00023 //  Includes
00024 // ---------------------------------------------------------------------------
00025 #include <xercesc/validators/datatype/UnionDatatypeValidator.hpp>
00026 #include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
00027 #include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>
00028 #include <xercesc/util/OutOfMemoryException.hpp>
00029 
00030 #include <xercesc/internal/XTemplateSerializer.hpp>
00031 
00032 XERCES_CPP_NAMESPACE_BEGIN
00033 
00034 static const unsigned int BUF_LEN = 64;
00035 
00036 // ---------------------------------------------------------------------------
00037 //  Constructors and Destructor
00038 // ---------------------------------------------------------------------------
00039 UnionDatatypeValidator::UnionDatatypeValidator(MemoryManager* const manager)
00040 :DatatypeValidator(0, 0, 0, DatatypeValidator::Union, manager)
00041 ,fEnumerationInherited(false)
00042 ,fMemberTypesInherited(false)
00043 ,fEnumeration(0)
00044 ,fMemberTypeValidators(0)
00045 
00046 {}
00047 
00048 UnionDatatypeValidator::~UnionDatatypeValidator()
00049 {
00050     cleanUp();
00051 }
00052 
00053 UnionDatatypeValidator::UnionDatatypeValidator(
00054                         RefVectorOf<DatatypeValidator>* const memberTypeValidators
00055                       , const int                             finalSet
00056                       , MemoryManager* const                  manager)
00057 :DatatypeValidator(0, 0, finalSet, DatatypeValidator::Union, manager)
00058 ,fEnumerationInherited(false)
00059 ,fMemberTypesInherited(false)
00060 ,fEnumeration(0)
00061 ,fMemberTypeValidators(0)
00062 {
00063     if ( !memberTypeValidators )
00064     {
00065         ThrowXMLwithMemMgr(InvalidDatatypeFacetException
00066                , XMLExcepts::FACET_Union_Null_memberTypeValidators, manager);
00067     }
00068 
00069     // no pattern, no enumeration
00070     fMemberTypeValidators = memberTypeValidators;
00071 }
00072 
00073 typedef JanitorMemFunCall<UnionDatatypeValidator>   CleanupType;
00074 
00075 UnionDatatypeValidator::UnionDatatypeValidator(
00076                           DatatypeValidator*            const baseValidator
00077                         , RefHashTableOf<KVStringPair>* const facets
00078                         , RefArrayVectorOf<XMLCh>*      const enums
00079                         , const int                           finalSet
00080                         , MemoryManager* const                manager
00081                         , RefVectorOf<DatatypeValidator>* const memberTypeValidators 
00082                         , const bool memberTypesInherited
00083                         )
00084 :DatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::Union, manager)
00085 ,fEnumerationInherited(false)
00086 ,fMemberTypesInherited(memberTypesInherited)
00087 ,fEnumeration(0)
00088 ,fMemberTypeValidators(memberTypeValidators)
00089 {
00090     //
00091     // baseValidator another UnionDTV from which,
00092     // this UnionDTV is derived by restriction.
00093     // it shall be not null
00094     //
00095     if (!baseValidator)
00096     {
00097         ThrowXMLwithMemMgr(InvalidDatatypeFacetException
00098                , XMLExcepts::FACET_Union_Null_baseValidator, manager);
00099     }
00100 
00101     if (baseValidator->getType() != DatatypeValidator::Union)
00102     {
00103         XMLCh value1[BUF_LEN+1];
00104         XMLString::binToText(baseValidator->getType(), value1, BUF_LEN, 10, manager);
00105         ThrowXMLwithMemMgr1(InvalidDatatypeFacetException
00106                 , XMLExcepts::FACET_Union_invalid_baseValidatorType
00107                 , value1
00108                 , manager);
00109     }
00110 
00111     CleanupType cleanup(this, &UnionDatatypeValidator::cleanUp);
00112 
00113     try
00114     {
00115         init(baseValidator, facets, enums, manager);
00116     }
00117     catch(const OutOfMemoryException&)
00118     {
00119         // Don't cleanup when out of memory, since executing the
00120         // code can cause problems.
00121         cleanup.release();
00122 
00123         throw;
00124     }
00125 
00126     cleanup.release();
00127 }
00128 
00129 void UnionDatatypeValidator::init(DatatypeValidator*            const baseValidator
00130                                 , RefHashTableOf<KVStringPair>* const facets
00131                                 , RefArrayVectorOf<XMLCh>*      const enums
00132                                 , MemoryManager*                const manager)
00133 {
00134     if (enums)
00135         setEnumeration(enums, false);
00136 
00137     // Set Facets if any defined
00138     if (facets)
00139     {
00140         XMLCh* key;
00141         XMLCh* value;
00142         RefHashTableOfEnumerator<KVStringPair> e(facets, false, manager);
00143 
00144         while (e.hasMoreElements())
00145         {
00146             KVStringPair pair = e.nextElement();
00147             key = pair.getKey();
00148             value = pair.getValue();
00149 
00150             if (XMLString::equals(key, SchemaSymbols::fgELT_PATTERN))
00151             {
00152                 setPattern(value);
00153                 if (getPattern())
00154                     setFacetsDefined(DatatypeValidator::FACET_PATTERN);
00155                 // do not construct regex until needed
00156             }
00157             else
00158             {
00159                  ThrowXMLwithMemMgr1(InvalidDatatypeFacetException
00160                          , XMLExcepts::FACET_Invalid_Tag
00161                          , key
00162                          , manager);
00163             }
00164         }//while
00165 
00166         /***
00167            Schema constraint: Part I -- self checking
00168         ***/
00169         // Nil
00170 
00171         /***
00172            Schema constraint: Part II base vs derived checking
00173         ***/
00174         // check 4.3.5.c0 must: enumeration values from the value space of base
00175         if ( ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0) &&
00176             (getEnumeration() !=0))
00177         {
00178             XMLSize_t i = 0;
00179             XMLSize_t enumLength = getEnumeration()->size();
00180             try
00181             {
00182                 for ( ; i < enumLength; i++)
00183                 {
00184                     // ask parent do a complete check
00185                     //
00186                     // enum need NOT be passed this->checkContent()
00187                     // since there are no other facets for Union, parent
00188                     // checking is good enough.
00189                     //
00190                     baseValidator->validate(getEnumeration()->elementAt(i), (ValidationContext*)0, manager);
00191 
00192                 }
00193             }
00194 
00195             catch ( XMLException& )
00196             {
00197                 ThrowXMLwithMemMgr1(InvalidDatatypeFacetException
00198                             , XMLExcepts::FACET_enum_base
00199                             , getEnumeration()->elementAt(i)
00200                             , manager);
00201             }
00202         }
00203 
00204     }// End of Facet setting
00205 
00206     /***
00207         Inherit facets from base.facets
00208 
00209         The reason of this inheriting (or copying values) is to ease
00210         schema constraint checking, so that we need NOT trace back to our
00211         very first base validator in the hierachy. Instead, we are pretty
00212         sure checking against immediate base validator is enough.
00213     ***/
00214 
00215     UnionDatatypeValidator *pBaseValidator = (UnionDatatypeValidator*) baseValidator;
00216 
00217     // inherit enumeration
00218     if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) !=0) &&
00219         ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) == 0))
00220     {
00221         setEnumeration(pBaseValidator->getEnumeration(), true);
00222     }
00223 
00224 }
00225 
00226 //
00227 // 1) the bottom level UnionDTV would check against
00228 //        pattern and enumeration as well
00229 // 2) each UnionDTV(s) above the bottom level UnionDTV and
00230 //        below the native UnionDTV (the top level DTV)
00231 //        would check against pattern only.
00232 // 3) the natvie Union DTV (the top level DTV) would invoke
00233 //        memberTypeValidator to validate
00234 //
00235 void UnionDatatypeValidator::checkContent(const XMLCh*             const content
00236                                         ,       ValidationContext* const context
00237                                         ,       bool                     asBase
00238                                         ,       MemoryManager*     const manager)
00239 {
00240 
00241     DatatypeValidator* bv = getBaseValidator();
00242     if (bv)
00243         ((UnionDatatypeValidator*)bv)->checkContent(content, context, true, manager);
00244     else
00245     {   // 3) native union type
00246         // check content against each member type validator in Union
00247         // report an error only in case content is not valid against all member datatypes.
00248         //
00249         bool memTypeValid = false;
00250         for ( unsigned int i = 0; i < fMemberTypeValidators->size(); ++i )
00251         {
00252             if ( memTypeValid )
00253                 break;
00254 
00255             try
00256             {
00257                 fMemberTypeValidators->elementAt(i)->validate(content, context, manager);
00258                 memTypeValid = true;
00259                 
00260                 //set the validator of the type actually used to validate the content
00261                 DatatypeValidator *dtv = fMemberTypeValidators->elementAt(i);                
00262                 // context will be null during schema construction
00263                 if(context)
00264                     context->setValidatingMemberType(dtv);
00265             }
00266             catch (XMLException&)
00267             {
00268                 //absorbed
00269             }
00270         } // for
00271 
00272         if ( !memTypeValid )
00273         {
00274             ThrowXMLwithMemMgr1(InvalidDatatypeValueException
00275                     , XMLExcepts::VALUE_no_match_memberType
00276                     , content
00277                     , manager);
00278             //( "Content '"+content+"' does not match any union types" );
00279         }
00280     }
00281 
00282     // 1) and 2). we check pattern first
00283     if ( (getFacetsDefined() & DatatypeValidator::FACET_PATTERN ) != 0 )
00284     {
00285         if (getRegex()->matches(content, manager) == false)
00286         {
00287             ThrowXMLwithMemMgr2(InvalidDatatypeValueException
00288                     , XMLExcepts::VALUE_NotMatch_Pattern
00289                     , content
00290                     , getPattern()
00291                     , manager);
00292         }
00293     }
00294 
00295     // if this is a base validator, we only need to check pattern facet
00296     // all other facet were inherited by the derived type
00297     if (asBase)
00298         return;
00299 
00300     if ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0 &&
00301         (getEnumeration() != 0))
00302     {
00303 
00304         // If the content match (compare equal) any enumeration with
00305         // any of the member types, it is considerd valid.
00306         //
00307         RefVectorOf<DatatypeValidator>* memberDTV = getMemberTypeValidators();
00308         RefArrayVectorOf<XMLCh>* tmpEnum = getEnumeration();
00309         XMLSize_t memberTypeNumber = memberDTV->size();
00310         XMLSize_t enumLength = tmpEnum->size();
00311 
00312         for ( XMLSize_t memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex)
00313         {
00314             for ( XMLSize_t enumIndex = 0; enumIndex < enumLength; ++enumIndex)
00315             {
00316                 try
00317                 {
00318                     if (memberDTV->elementAt(memberIndex)->compare(content, tmpEnum->elementAt(enumIndex), manager) == 0)
00319                         return;
00320                 }
00321                 catch (XMLException&)
00322                 {
00323                     //absorbed
00324                 }
00325             } // for enumIndex
00326         } // for memberIndex
00327 
00328         ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager);
00329 
00330     } // enumeration
00331 
00332 }
00333 
00334 //
00335 //
00336 //
00337 int UnionDatatypeValidator::compare(const XMLCh* const lValue
00338                                   , const XMLCh* const rValue
00339                                   , MemoryManager* const manager)
00340 {
00341     RefVectorOf<DatatypeValidator>* memberDTV = getMemberTypeValidators();
00342     XMLSize_t memberTypeNumber = memberDTV->size();
00343 
00344     for ( XMLSize_t memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex)
00345     {
00346         // 'compare' can throw exceptions when the datatype is not valid, or just 
00347         // return -1; so attempt to validate both values to get the right validator
00348         try
00349         {
00350             memberDTV->elementAt(memberIndex)->validate(lValue, 0, manager);                       
00351             memberDTV->elementAt(memberIndex)->validate(rValue, 0, manager);                       
00352             if (memberDTV->elementAt(memberIndex)->compare(lValue, rValue, manager) ==0)
00353                 return  0;
00354         }
00355         catch (XMLException&)
00356         {
00357             //absorbed
00358         }
00359     }
00360 
00361     //REVISIT: what does it mean for UNION1 to be <less than> or <greater than> UNION2 ?
00362     // As long as -1 or +1 indicates an unequality, return either of them is ok.
00363     return -1;
00364 }
00365 
00366 const RefArrayVectorOf<XMLCh>* UnionDatatypeValidator::getEnumString() const
00367 {
00368         return getEnumeration();
00369 }
00370 
00371 /***
00372  * 2.5.1.3 Union datatypes
00373  *
00374  * The canonical-lexical-representation for a union datatype is defined as the lexical form 
00375  * in which the values have the canonical lexical representation of the appropriate memberTypes.       
00376  ***/
00377 const XMLCh* UnionDatatypeValidator::getCanonicalRepresentation(const XMLCh*         const rawData
00378                                                               ,       MemoryManager* const memMgr
00379                                                               ,       bool                 toValidate) const
00380 {
00381     MemoryManager* toUse = memMgr? memMgr : getMemoryManager();
00382     UnionDatatypeValidator* temp = (UnionDatatypeValidator*) this;
00383 
00384     if (toValidate)
00385     {
00386         try
00387         {
00388             temp->checkContent(rawData, 0, false, toUse);
00389         }
00390         catch (...)
00391         {
00392             return 0;
00393         }
00394     }    
00395 
00396     //get the native unionDv
00397     UnionDatatypeValidator* bdv = (UnionDatatypeValidator*) temp->getBaseValidator();
00398     while (bdv)
00399     {
00400         temp = bdv;
00401         bdv = (UnionDatatypeValidator*) temp->getBaseValidator();
00402     }
00403 
00404     //let the member dv which recognize the rawData, to return
00405     //us the canonical form
00406     for ( unsigned int i = 0; i < temp->fMemberTypeValidators->size(); ++i )
00407     {
00408         try
00409         {
00410             temp->fMemberTypeValidators->elementAt(i)->validate(rawData, 0, toUse);                       
00411             return temp->fMemberTypeValidators->elementAt(i)->getCanonicalRepresentation(rawData, toUse, false);
00412         }
00413         catch (XMLException&)
00414         {
00415             //absorbed
00416         }
00417     }
00418 
00419     //if no member dv recognize it
00420     return 0;
00421 }
00422 
00423 
00424 /***
00425  * Support for Serialization/De-serialization
00426  ***/
00427 
00428 IMPL_XSERIALIZABLE_TOCREATE(UnionDatatypeValidator)
00429 
00430 void UnionDatatypeValidator::serialize(XSerializeEngine& serEng)
00431 {
00432 
00433     DatatypeValidator::serialize(serEng);
00434 
00435     if (serEng.isStoring())
00436     {
00437         serEng<<fEnumerationInherited;
00438         serEng<<fMemberTypesInherited;
00439 
00440         /***
00441          * Serialize RefArrayVectorOf<XMLCh>
00442          * Serialize RefVectorOf<DatatypeValidator>
00443          ***/
00444         XTemplateSerializer::storeObject(fEnumeration, serEng);
00445         XTemplateSerializer::storeObject(fMemberTypeValidators, serEng);
00446     }
00447     else
00448     {
00449         serEng>>fEnumerationInherited;
00450         serEng>>fMemberTypesInherited;
00451 
00452         /***
00453          * Deserialize RefArrayVectorOf<XMLCh>
00454          * Deserialize RefVectorOf<DatatypeValidator>
00455          ***/
00456         XTemplateSerializer::loadObject(&fEnumeration, 8, true, serEng);
00457         XTemplateSerializer::loadObject(&fMemberTypeValidators, 4, false, serEng);
00458     }
00459 }
00460 
00461 XERCES_CPP_NAMESPACE_END
00462