1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /*
19  * $Id: QNameDatatypeValidator.cpp 676911 2008-07-15 13:27:32Z amassari $
20  */
21 
22 // ---------------------------------------------------------------------------
23 //  Includes
24 // ---------------------------------------------------------------------------
25 #include <xercesc/validators/datatype/QNameDatatypeValidator.hpp>
26 #include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
27 #include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>
28 #include <xercesc/internal/ValidationContextImpl.hpp>
29 #include <xercesc/util/XMLChar.hpp>
30 
31 XERCES_CPP_NAMESPACE_BEGIN
32 
33 // ---------------------------------------------------------------------------
34 //  Constructors and Destructor
35 // ---------------------------------------------------------------------------
QNameDatatypeValidator(MemoryManager * const manager)36 QNameDatatypeValidator::QNameDatatypeValidator(MemoryManager* const manager)
37 :AbstractStringValidator(0, 0, 0, DatatypeValidator::QName, manager)
38 {}
39 
~QNameDatatypeValidator()40 QNameDatatypeValidator::~QNameDatatypeValidator()
41 {}
42 
QNameDatatypeValidator(DatatypeValidator * const baseValidator,RefHashTableOf<KVStringPair> * const facets,RefArrayVectorOf<XMLCh> * const enums,const int finalSet,MemoryManager * const manager)43 QNameDatatypeValidator::QNameDatatypeValidator(
44                           DatatypeValidator*            const baseValidator
45                         , RefHashTableOf<KVStringPair>* const facets
46                         , RefArrayVectorOf<XMLCh>*      const enums
47                         , const int                           finalSet
48                         , MemoryManager* const                manager)
49 :AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::QName, manager)
50 {
51     init(enums, manager);
52 }
53 
newInstance(RefHashTableOf<KVStringPair> * const facets,RefArrayVectorOf<XMLCh> * const enums,const int finalSet,MemoryManager * const manager)54 DatatypeValidator* QNameDatatypeValidator::newInstance
55 (
56       RefHashTableOf<KVStringPair>* const facets
57     , RefArrayVectorOf<XMLCh>* const      enums
58     , const int                           finalSet
59     , MemoryManager* const                manager
60 )
61 {
62     return (DatatypeValidator*) new (manager) QNameDatatypeValidator(this, facets, enums, finalSet, manager);
63 }
64 
65 // ---------------------------------------------------------------------------
66 //  Utilities
67 // ---------------------------------------------------------------------------
68 
checkValueSpace(const XMLCh * const content,MemoryManager * const manager)69 void QNameDatatypeValidator::checkValueSpace(const XMLCh* const content
70                                              , MemoryManager* const manager)
71 {
72     //
73     // check 3.2.18.c0 must: QName
74     //
75 
76     if ( !XMLChar1_0::isValidQName(content, XMLString::stringLen(content)) )
77     {
78         ThrowXMLwithMemMgr1(InvalidDatatypeValueException
79                 , XMLExcepts::VALUE_QName_Invalid
80                 , content
81                 , manager);
82     }
83 }
84 
checkContent(const XMLCh * const content,ValidationContext * const context,bool asBase,MemoryManager * const manager)85 void QNameDatatypeValidator::checkContent( const XMLCh*             const content
86                                           ,       ValidationContext* const context
87                                           ,       bool                     asBase
88                                           ,       MemoryManager*     const manager
89                                           )
90 {
91 
92     //validate against base validator if any
93     QNameDatatypeValidator *pBaseValidator = (QNameDatatypeValidator*) this->getBaseValidator();
94     if (pBaseValidator)
95         pBaseValidator->checkContent(content, context, true, manager);
96 
97     int thisFacetsDefined = getFacetsDefined();
98 
99     // we check pattern first
100     if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 )
101     {
102         if (getRegex()->matches(content, manager) ==false)
103         {
104             ThrowXMLwithMemMgr2(InvalidDatatypeValueException
105                     , XMLExcepts::VALUE_NotMatch_Pattern
106                     , content
107                     , getPattern()
108                     , manager);
109         }
110     }
111 
112     // if this is a base validator, we only need to check pattern facet
113     // all other facet were inherited by the derived type
114     if (asBase)
115         return;
116 
117     checkValueSpace(content, manager);
118 
119     int colonPos = 0;
120     XMLCh* prefix = 0;
121     ArrayJanitor<XMLCh>  jan(prefix, manager);
122 
123     if (context) {
124         prefix = XMLString::replicate(content, manager);
125         jan.reset(prefix, manager);
126         normalizeContent(prefix, manager);
127 
128         colonPos = XMLString::indexOf(content, chColon);
129         if (colonPos > 0) {
130             prefix[colonPos] = chNull;
131             if (context->isPrefixUnknown(prefix)) {
132                 ThrowXMLwithMemMgr1(InvalidDatatypeValueException
133                     , XMLExcepts::VALUE_QName_Invalid2
134                     , content
135                     , manager);
136             }
137         }
138     }
139 
140 #if 0
141     if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 &&
142         (getEnumeration() != 0))
143     {
144         XMLCh* normContent = XMLString::replicate(content, manager);
145         ArrayJanitor<XMLCh>  jan(normContent, manager);
146         normalizeContent(normContent, manager);
147 
148         int i=0;
149         int enumLength = getEnumeration()->size();
150         for ( ; i < enumLength; i++)
151         {
152             if (XMLString::equals(normContent, getEnumeration()->elementAt(i)))
153                 break;
154         }
155 
156         if (i == enumLength)
157             ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager);
158     }
159 
160 
161 #else
162     if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 &&
163         (getEnumeration() != 0) && context)
164     {
165         XMLCh* localName;
166         if (colonPos > 0) {
167             localName = prefix + colonPos + 1;
168         }
169         else {
170             localName = prefix;
171         }
172 
173         XMLCh* enumPrefix;
174         XMLCh* enumLocalName;
175         XMLSize_t i=0;
176         XMLSize_t enumLength = getEnumeration()->size();
177         bool foundURIId = false;
178         const XMLCh* normURI = 0;
179 		// The +=2 is because the enumeration has prefix:localname as one entry followed
180 		// by the URI string for the prefix as the next entry.
181         for ( ; i < enumLength; i+=2)
182         {
183             enumPrefix = XMLString::replicate(getEnumeration()->elementAt(i), manager);
184             ArrayJanitor<XMLCh>  janEnum(enumPrefix, manager);
185             colonPos = XMLString::indexOf(enumPrefix, chColon, 0, manager);
186 
187             if (colonPos != -1) {
188                 enumLocalName = enumPrefix + colonPos + 1;
189                 enumPrefix[colonPos] = chNull;
190             }
191             else {
192                 enumLocalName = enumPrefix;
193             }
194 
195             if (XMLString::equals(localName, enumLocalName)) {
196 				if (colonPos < 0)
197 					break;
198 
199                 // now need to see if the prefix URI's are the same
200                 if (!foundURIId) {
201                     normURI = context->getURIForPrefix(prefix);
202                     foundURIId = true;
203                 }
204 				if (XMLString::equals(normURI, getEnumeration()->elementAt(i+1)))
205 					break;
206             }
207         }
208 
209         if (i == enumLength)
210             ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager);
211     }
212 #endif
213 
214     checkAdditionalFacet(content, manager);
215 }
216 
217 //
218 //  Check vs base
219 //         check common facets
220 //         check enumeration
221 //         check Additional Facet Constraint
222 //
inspectFacetBase(MemoryManager * const manager)223 void QNameDatatypeValidator::inspectFacetBase(MemoryManager* const manager)
224 {
225 
226     QNameDatatypeValidator *pBaseValidator = (QNameDatatypeValidator*) getBaseValidator();
227     int thisFacetsDefined = getFacetsDefined();
228 
229     if ( (!thisFacetsDefined && !getEnumeration()) ||
230          (!pBaseValidator)                      )
231         return;
232 
233     // check 4.3.5.c0 must: enumeration values from the value space of base
234     if ( ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0) &&
235         (getEnumeration() !=0))
236     {
237         XMLSize_t i = 0;
238         XMLSize_t enumLength = getEnumeration()->size();
239 		// The +=2 is because the enumeration has prefix:localname as one entry followed
240 		// by the URI string for the prefix as the next entry.
241         for ( ; i < enumLength; i+=2)
242         {
243             // ask parent do a complete check
244             pBaseValidator->checkContent(getEnumeration()->elementAt(i), (ValidationContext*)0, false, manager);
245 #if 0
246 // spec says that only base has to checkContent
247             // enum shall pass this->checkContent() as well.
248             checkContent(getEnumeration()->elementAt(i), (ValidationContext*)0, false, manager);
249 #endif
250         }
251     }
252 
253     checkAdditionalFacetConstraints(manager);
254 
255 } //end of inspectFacetBase
256 
257 /***
258  * Support for Serialization/De-serialization
259  ***/
260 
IMPL_XSERIALIZABLE_TOCREATE(QNameDatatypeValidator)261 IMPL_XSERIALIZABLE_TOCREATE(QNameDatatypeValidator)
262 
263 void QNameDatatypeValidator::serialize(XSerializeEngine& serEng)
264 {
265     AbstractStringValidator::serialize(serEng);
266 }
267 
268 XERCES_CPP_NAMESPACE_END
269 
270 /**
271   * End of file QNameDatatypeValidator.cpp
272   */
273