GME  13
SubstitutionGroupComparator.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: SubstitutionGroupComparator.cpp 794273 2009-07-15 14:13:07Z amassari $
00020  */
00021 
00022 
00023 // ---------------------------------------------------------------------------
00024 //  Includes
00025 // ---------------------------------------------------------------------------
00026 #include <xercesc/framework/XMLGrammarPool.hpp>
00027 #include <xercesc/framework/XMLSchemaDescription.hpp>
00028 #include <xercesc/framework/psvi/XSAnnotation.hpp>
00029 #include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
00030 #include <xercesc/validators/common/Grammar.hpp>
00031 #include <xercesc/validators/schema/SchemaGrammar.hpp>
00032 #include <xercesc/validators/schema/ComplexTypeInfo.hpp>
00033 #include <xercesc/validators/schema/SchemaSymbols.hpp>
00034 
00035 XERCES_CPP_NAMESPACE_BEGIN
00036 
00037 bool SubstitutionGroupComparator::isEquivalentTo(const QName* const anElement
00038                                                , const QName* const exemplar)
00039 {
00040     if (!anElement && !exemplar)
00041         return true;
00042 
00043     if ((!anElement && exemplar) || (anElement && !exemplar))
00044         return false;
00045 
00046 
00047     if (XMLString::equals(anElement->getLocalPart(), exemplar->getLocalPart()) &&
00048         (anElement->getURI() == exemplar->getURI()))
00049         return true; // they're the same!
00050 
00051     if (!fGrammarResolver || !fStringPool )
00052     {
00053         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::SubGrpComparator_NGR, anElement->getMemoryManager());
00054     }
00055 
00056     unsigned int uriId = anElement->getURI();
00057     if (uriId == XMLContentModel::gEOCFakeId ||
00058         uriId == XMLContentModel::gEpsilonFakeId ||
00059         uriId == XMLElementDecl::fgPCDataElemId ||
00060         uriId == XMLElementDecl::fgInvalidElemId)
00061         return false;
00062 
00063     const XMLCh* uri = fStringPool->getValueForId(uriId);
00064     const XMLCh* localpart = anElement->getLocalPart();
00065 
00066     // In addition to simply trying to find a chain between anElement and exemplar,
00067     // we need to make sure that no steps in the chain are blocked.
00068     // That is, at every step, we need to make sure that the element
00069     // being substituted for will permit being substituted
00070     // for, and whether the type of the element will permit derivations in
00071     // instance documents of this sort.
00072 
00073     if (!uri)
00074         return false;
00075 
00076     SchemaGrammar *sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(uri);
00077     if (!sGrammar || sGrammar->getGrammarType() == Grammar::DTDGrammarType)
00078         return false;
00079 
00080     SchemaElementDecl* anElementDecl = (SchemaElementDecl*) sGrammar->getElemDecl(uriId, localpart, 0, Grammar::TOP_LEVEL_SCOPE);
00081     if (!anElementDecl)
00082         return false;
00083 
00084     SchemaElementDecl* pElemDecl = anElementDecl->getSubstitutionGroupElem();
00085     bool foundIt = false;
00086 
00087     while (pElemDecl) //(substitutionGroupFullName)
00088     {
00089         if (XMLString::equals(pElemDecl->getBaseName(), exemplar->getLocalPart()) &&
00090             (pElemDecl->getURI() == exemplar->getURI()))
00091         {
00092             // time to check for block value on element
00093             if((pElemDecl->getBlockSet() & SchemaSymbols::XSD_SUBSTITUTION) != 0)
00094                 return false;
00095 
00096             foundIt = true;
00097             break;
00098         }
00099 
00100         pElemDecl = pElemDecl->getSubstitutionGroupElem();
00101     }//while
00102 
00103     if (!foundIt)
00104         return false;
00105 
00106     // this will contain anElement's complexType information.
00107     ComplexTypeInfo *aComplexType = anElementDecl->getComplexTypeInfo();
00108     int exemplarBlockSet = pElemDecl->getBlockSet();
00109 
00110     if(!aComplexType)
00111     {
00112         // check on simpleType case
00113         DatatypeValidator *anElementDV = anElementDecl->getDatatypeValidator();
00114         DatatypeValidator *exemplarDV = pElemDecl->getDatatypeValidator();
00115 
00116         return((anElementDV == 0) ||
00117             ((anElementDV == exemplarDV) ||
00118             ((exemplarBlockSet & SchemaSymbols::XSD_RESTRICTION) == 0)));
00119     }
00120 
00121     // 2.3 The set of all {derivation method}s involved in the derivation of D's {type definition} from C's {type definition} does not intersect with the union of the blocking constraint, C's {prohibited substitutions} (if C is complex, otherwise the empty set) and the {prohibited substitutions} (respectively the empty set) of any intermediate {type definition}s in the derivation of D's {type definition} from C's {type definition}.
00122     // prepare the combination of {derivation method} and
00123     // {disallowed substitution}
00124     int devMethod = 0;
00125     int blockConstraint = exemplarBlockSet;
00126 
00127     ComplexTypeInfo *exemplarComplexType = pElemDecl->getComplexTypeInfo();
00128     ComplexTypeInfo *tempType = aComplexType;;
00129 
00130     while (tempType != 0 &&
00131         tempType != exemplarComplexType)
00132     {
00133         devMethod |= tempType->getDerivedBy();
00134         tempType = tempType->getBaseComplexTypeInfo();
00135         if (tempType) {
00136             blockConstraint |= tempType->getBlockSet();
00137         }
00138     }
00139     if (tempType != exemplarComplexType) {
00140         return false;
00141     }
00142     if ((devMethod & blockConstraint) != 0) {
00143         return false;
00144     }
00145 
00146     return true;
00147 }
00148 
00149 
00150 bool SubstitutionGroupComparator::isAllowedByWildcard(SchemaGrammar* const pGrammar,
00151                                                       QName* const element,
00152                                                       unsigned int wuri, bool wother)
00153 {
00154     // whether the uri is allowed directly by the wildcard
00155     unsigned int uriId = element->getURI();
00156 
00157     // Here we assume that empty string has id 1.
00158     //
00159     if ((!wother && uriId == wuri) ||
00160         (wother &&
00161          uriId != 1 &&
00162          uriId != wuri &&
00163          uriId != XMLContentModel::gEOCFakeId &&
00164          uriId != XMLContentModel::gEpsilonFakeId &&
00165          uriId != XMLElementDecl::fgPCDataElemId &&
00166          uriId != XMLElementDecl::fgInvalidElemId))
00167     {
00168         return true;
00169     }
00170 
00171     // get all elements that can substitute the current element
00172     RefHash2KeysTableOf<ElemVector>* theValidSubstitutionGroups = pGrammar->getValidSubstitutionGroups();
00173 
00174     if (!theValidSubstitutionGroups)
00175         return false;
00176 
00177     ValueVectorOf<SchemaElementDecl*>* subsElements = theValidSubstitutionGroups->get(element->getLocalPart(), uriId);
00178 
00179     if (!subsElements)
00180         return false;
00181 
00182     // then check whether there exists one element that is allowed by the wildcard
00183     XMLSize_t size = subsElements->size();
00184 
00185     for (XMLSize_t i = 0; i < size; i++)
00186     {
00187         unsigned int subUriId = subsElements->elementAt(i)->getElementName()->getURI();
00188 
00189         // Here we assume that empty string has id 1.
00190         //
00191         if ((!wother && subUriId == wuri) ||
00192             (wother &&
00193              subUriId != 1 &&
00194              subUriId != wuri &&
00195              subUriId != XMLContentModel::gEOCFakeId &&
00196              subUriId != XMLContentModel::gEpsilonFakeId &&
00197              subUriId != XMLElementDecl::fgPCDataElemId &&
00198              subUriId != XMLElementDecl::fgInvalidElemId))
00199         {
00200             return true;
00201         }
00202     }
00203     return false;
00204 }
00205 
00206 XERCES_CPP_NAMESPACE_END
00207