Qt 4.8
qxsdschemahelper.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qxsdschemahelper_p.h"
43 
44 #include "qbuiltintypes_p.h"
45 #include "qvaluefactory_p.h"
46 #include "qxsdcomplextype_p.h"
47 #include "qxsdmodelgroup_p.h"
48 #include "qxsdsimpletype_p.h"
49 #include "qxsdtypechecker_p.h"
50 
52 
53 using namespace QPatternist;
54 
55 /*
56  * Calculates the effective total range minimum of the given @p particle as
57  * described by the algorithm in the schema spec.
58  */
59 static inline unsigned int effectiveTotalRangeMinimum(const XsdParticle::Ptr &particle)
60 {
61  const XsdModelGroup::Ptr group = particle->term();
62 
64  // @see http://www.w3.org/TR/xmlschema11-1/# cos-choice-range
65 
66  int minValue = -1;
67 
68  const XsdParticle::List particles = group->particles();
69  if (particles.isEmpty())
70  minValue = 0;
71 
72  for (int i = 0; i < particles.count(); ++i) {
73  const XsdParticle::Ptr particle = particles.at(i);
74 
75  if (particle->term()->isElement() || particle->term()->isWildcard()) {
76  if (minValue == -1) {
77  minValue = particle->minimumOccurs();
78  } else {
79  minValue = qMin((unsigned int)minValue, particle->minimumOccurs());
80  }
81  } else if (particle->term()->isModelGroup()) {
82  if (minValue == -1) {
83  minValue = effectiveTotalRangeMinimum(particle);
84  } else {
85  minValue = qMin((unsigned int)minValue, effectiveTotalRangeMinimum(particle));
86  }
87  }
88  }
89 
90  return (particle->minimumOccurs() * minValue);
91 
92  } else {
93  // @see http://www.w3.org/TR/xmlschema11-1/# cos-seq-range
94 
95  unsigned int sum = 0;
96  const XsdParticle::List particles = group->particles();
97  for (int i = 0; i < particles.count(); ++i) {
98  const XsdParticle::Ptr particle = particles.at(i);
99 
100  if (particle->term()->isElement() || particle->term()->isWildcard())
101  sum += particle->minimumOccurs();
102  else if (particle->term()->isModelGroup())
103  sum += effectiveTotalRangeMinimum(particle);
104  }
105 
106  return (particle->minimumOccurs() * sum);
107  }
108 }
109 
111 {
112  // @see http://www.w3.org/TR/xmlschema11-1/#cos-group-emptiable
113 
114  if (particle->minimumOccurs() == 0)
115  return true;
116 
117  if (!(particle->term()->isModelGroup()))
118  return false;
119 
120  return (effectiveTotalRangeMinimum(particle) == 0);
121 }
122 
124 {
125  // @see http://www.w3.org/TR/xmlschema11-1/#cvc-wildcard-namespace
126 
127  // 1
128  if (constraint->variety() == XsdWildcard::NamespaceConstraint::Any)
129  return true;
130 
131  // 2
132  if (constraint->variety() == XsdWildcard::NamespaceConstraint::Not) { // 2.1
133  if (!constraint->namespaces().contains(nameSpace)) // 2.2
134  if (nameSpace != XsdWildcard::absentNamespace()) // 2.3
135  return true;
136  }
137 
138  // 3
139  if (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) {
140  if (constraint->namespaces().contains(nameSpace))
141  return true;
142  }
143 
144  return false;
145 }
146 
148 {
149  // @see http://www.w3.org/TR/xmlschema11-1/#cvc-wildcard-name
150 
151  // 1
153  return false;
154 
155  // 2, 3, 4
156  //TODO: we have no disallowed namespace yet
157 
158  return true;
159 }
160 
161 // small helper function that should be available in Qt 4.6
162 template<class T>
163 static inline bool containsSet(const QSet<T> &super, const QSet<T> &sub)
164 {
165  QSetIterator<T> it(sub);
166  while (it.hasNext()) {
167  if (!super.contains(it.next()))
168  return false;
169  }
170 
171  return true;
172 }
173 
174 bool XsdSchemaHelper::isWildcardSubset(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard)
175 {
176  // @see http://www.w3.org/TR/xmlschema11-1/#cos-ns-subset
177  // wildcard =^ sub
178  // otherWildcard =^ super
179 
180  const XsdWildcard::NamespaceConstraint::Ptr constraint(wildcard->namespaceConstraint());
181  const XsdWildcard::NamespaceConstraint::Ptr otherConstraint(otherWildcard->namespaceConstraint());
182 
183  // 1
184  if (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Any)
185  return true;
186 
187  // 2
188  if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
189  if (containsSet<QString>(otherConstraint->namespaces(), constraint->namespaces()))
190  return true;
191  }
192 
193  // 3
194  if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) {
195  if (constraint->namespaces().intersect(otherConstraint->namespaces()).isEmpty())
196  return true;
197  }
198 
199  // 4
200  if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) {
201  if (containsSet<QString>(constraint->namespaces(), otherConstraint->namespaces()))
202  return true;
203  }
204 
205  return false;
206 }
207 
209 {
210  // @see http://www.w3.org/TR/xmlschema11-1/#cos-aw-union
211 
212  XsdWildcard::Ptr unionWildcard(new XsdWildcard());
213 
214  const XsdWildcard::NamespaceConstraint::Ptr constraint(wildcard->namespaceConstraint());
215  const XsdWildcard::NamespaceConstraint::Ptr otherConstraint(otherWildcard->namespaceConstraint());
216 
217  // 1
218  if ((constraint->variety() == otherConstraint->variety()) &&
219  (constraint->namespaces() == otherConstraint->namespaces())) {
220  unionWildcard->namespaceConstraint()->setVariety(constraint->variety());
221  unionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces());
222  return unionWildcard;
223  }
224 
225  // 2
226  if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Any) || (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Any)) {
227  unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
228  return unionWildcard;
229  }
230 
231  // 3
232  if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
234  unionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces() + otherConstraint->namespaces());
235  return unionWildcard;
236  }
237 
238  // 4
239  if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) {
240  if (constraint->namespaces() != otherConstraint->namespaces()) {
241  unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
242  unionWildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << XsdWildcard::absentNamespace());
243  return unionWildcard;
244  }
245  }
246 
247  // 5
248  QSet<QString> sSet, negatedSet;
249  bool matches5 = false;
250  if (((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && !constraint->namespaces().contains(XsdWildcard::absentNamespace()))
251  && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
252 
253  negatedSet = constraint->namespaces();
254  sSet = otherConstraint->namespaces();
255  matches5 = true;
256  } else if (((otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not) && !otherConstraint->namespaces().contains(XsdWildcard::absentNamespace()))
257  && (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
258 
259  negatedSet = otherConstraint->namespaces();
260  sSet = constraint->namespaces();
261  matches5 = true;
262  }
263 
264  if (matches5) {
265  if (sSet.contains(negatedSet.values().first()) && sSet.contains(XsdWildcard::absentNamespace())) { // 5.1
266  unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
267  return unionWildcard;
268  }
269  if (sSet.contains(negatedSet.values().first()) && !sSet.contains(XsdWildcard::absentNamespace())) { // 5.2
270  unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
271  unionWildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << XsdWildcard::absentNamespace());
272  return unionWildcard;
273  }
274  if (!sSet.contains(negatedSet.values().first()) && sSet.contains(XsdWildcard::absentNamespace())) { // 5.3
275  return XsdWildcard::Ptr(); // not expressible
276  }
277  if (!sSet.contains(negatedSet.values().first()) && !sSet.contains(XsdWildcard::absentNamespace())) { // 5.4
278  unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
279  unionWildcard->namespaceConstraint()->setNamespaces(negatedSet);
280  return unionWildcard;
281  }
282  }
283 
284  // 6
285  bool matches6 = false;
286  if (((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && constraint->namespaces().contains(XsdWildcard::absentNamespace()))
287  && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
288 
289  negatedSet = constraint->namespaces();
290  sSet = otherConstraint->namespaces();
291  matches6 = true;
292  } else if (((otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not) && otherConstraint->namespaces().contains(XsdWildcard::absentNamespace()))
293  && (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
294 
295  negatedSet = otherConstraint->namespaces();
296  sSet = constraint->namespaces();
297  matches6 = true;
298  }
299 
300  if (matches6) {
301  if (sSet.contains(XsdWildcard::absentNamespace())) { // 6.1
302  unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
303  return unionWildcard;
304  }
305  if (!sSet.contains(XsdWildcard::absentNamespace())) { // 6.2
306  unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
307  unionWildcard->namespaceConstraint()->setNamespaces(QSet<QString>() += XsdWildcard::absentNamespace());
308  return unionWildcard;
309  }
310  }
311 
312  return XsdWildcard::Ptr();
313 }
314 
316 {
317  // @see http://www.w3.org/TR/xmlschema11-1/#cos-aw-intersect
318 
319  const XsdWildcard::NamespaceConstraint::Ptr constraint(wildcard->namespaceConstraint());
320  const XsdWildcard::NamespaceConstraint::Ptr otherConstraint(otherWildcard->namespaceConstraint());
321 
322  const XsdWildcard::Ptr intersectionWildcard(new XsdWildcard());
323 
324  // 1
325  if ((constraint->variety() == otherConstraint->variety()) &&
326  (constraint->namespaces() == otherConstraint->namespaces())) {
327  intersectionWildcard->namespaceConstraint()->setVariety(constraint->variety());
328  intersectionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces());
329  return intersectionWildcard;
330  }
331 
332  // 2
333  if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Any) &&
334  (otherConstraint->variety() != XsdWildcard::NamespaceConstraint::Any)) {
335  intersectionWildcard->namespaceConstraint()->setVariety(otherConstraint->variety());
336  intersectionWildcard->namespaceConstraint()->setNamespaces(otherConstraint->namespaces());
337  return intersectionWildcard;
338  }
339 
340  // 2
341  if ((constraint->variety() != XsdWildcard::NamespaceConstraint::Any) &&
342  (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Any)) {
343  intersectionWildcard->namespaceConstraint()->setVariety(constraint->variety());
344  intersectionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces());
345  return intersectionWildcard;
346  }
347 
348  // 3
349  if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) &&
350  (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
351 
352  QSet<QString> set = otherConstraint->namespaces();
353  set.subtract(constraint->namespaces());
355 
356  intersectionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
357  intersectionWildcard->namespaceConstraint()->setNamespaces(set);
358 
359  return intersectionWildcard;
360  }
361 
362  // 3
363  if ((otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not) &&
364  (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
365 
366  QSet<QString> set = constraint->namespaces();
367  set.subtract(otherConstraint->namespaces());
369 
370  intersectionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
371  intersectionWildcard->namespaceConstraint()->setNamespaces(set);
372 
373  return intersectionWildcard;
374  }
375 
376  // 4
377  if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) &&
378  (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
379 
380  QSet<QString> set = constraint->namespaces();
381  set.intersect(otherConstraint->namespaces());
382 
383  intersectionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
384  intersectionWildcard->namespaceConstraint()->setNamespaces(set);
385 
386  return intersectionWildcard;
387  }
388 
389  // 6
390  if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) &&
391  (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) {
392  if (!(constraint->namespaces().contains(XsdWildcard::absentNamespace())) && otherConstraint->namespaces().contains(XsdWildcard::absentNamespace())) {
393  return wildcard;
394  }
395  if (constraint->namespaces().contains(XsdWildcard::absentNamespace()) && !(otherConstraint->namespaces().contains(XsdWildcard::absentNamespace()))) {
396  return otherWildcard;
397  }
398  }
399 
400  // 5 as not expressible return empty wildcard
401  return XsdWildcard::Ptr();
402 }
403 
404 static SchemaType::DerivationConstraints convertBlockingConstraints(const NamedSchemaComponent::BlockingConstraints &constraints)
405 {
406  SchemaType::DerivationConstraints result = 0;
407 
412 
413  return result;
414 }
415 
416 bool XsdSchemaHelper::isValidlySubstitutable(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, const SchemaType::DerivationConstraints &constraints)
417 {
418  // @see http://www.w3.org/TR/xmlschema11-1/#key-val-sub-type
419 
420  // 1
421  if (type->isComplexType() && otherType->isComplexType()) {
422  SchemaType::DerivationConstraints keywords = constraints;
423  if (otherType->isDefinedBySchema())
425 
426  return isComplexDerivationOk(type, otherType, keywords);
427  }
428 
429  // 2
430  if (type->isComplexType() && otherType->isSimpleType()) {
431  return isComplexDerivationOk(type, otherType, constraints);
432  }
433 
434  // 3
435  if (type->isSimpleType() && otherType->isSimpleType()) {
436  return isSimpleDerivationOk(type, otherType, constraints);
437  }
438 
439  return false;
440 }
441 
442 bool XsdSchemaHelper::isSimpleDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr &baseType, const SchemaType::DerivationConstraints &constraints)
443 {
444  // @see http://www.w3.org/TR/xmlschema11-1/#cos-st-derived-ok
445 
446  // 1
447  if (derivedType == baseType)
448  return true;
449 
450  // 2.1
452  return false;
453  }
454 
455  // 2.2.1
456  if (derivedType->wxsSuperType() == baseType)
457  return true;
458 
459  // 2.2.2
460  if (derivedType->wxsSuperType() != BuiltinTypes::xsAnyType) {
461  if (isSimpleDerivationOk(derivedType->wxsSuperType(), baseType, constraints))
462  return true;
463  }
464 
465  // 2.2.3
466  if (derivedType->category() == SchemaType::SimpleTypeList || derivedType->category() == SchemaType::SimpleTypeUnion) {
467  if (baseType == BuiltinTypes::xsAnySimpleType)
468  return true;
469  }
470 
471  // 2.2.4
472  if (baseType->category() == SchemaType::SimpleTypeUnion && baseType->isDefinedBySchema()) { // 2.2.4.1
473  const AnySimpleType::List memberTypes = XsdSimpleType::Ptr(baseType)->memberTypes();
474  for (int i = 0; i < memberTypes.count(); ++i) {
475  if (isSimpleDerivationOk(derivedType, memberTypes.at(i), constraints)) { // 2.2.4.2
476  if (XsdSimpleType::Ptr(baseType)->facets().isEmpty()) { // 2.2.4.3
477  return true;
478  }
479  }
480  }
481  }
482 
483  return false;
484 }
485 
486 bool XsdSchemaHelper::isComplexDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr &baseType, const SchemaType::DerivationConstraints &constraints)
487 {
488  if (!derivedType)
489  return false;
490 
491  // @see http://www.w3.org/TR/xmlschema11-1/#cos-ct-derived-ok
492 
493  // 1
494  if (derivedType != baseType) {
496  return false;
497  if ((derivedType->derivationMethod() == SchemaType::DerivationExtension) && (constraints & SchemaType::ExtensionConstraint))
498  return false;
499  }
500 
501  // 2.1
502  if (derivedType == baseType)
503  return true;
504 
505  // 2.2
506  if (derivedType->wxsSuperType() == baseType)
507  return true;
508 
509  // 2.3
510  bool isOk = true;
511  if (derivedType->wxsSuperType() == BuiltinTypes::xsAnyType) { // 2.3.1
512  isOk = false;
513  } else { // 2.3.2
514  if (!derivedType->wxsSuperType())
515  return false;
516 
517  if (derivedType->wxsSuperType()->isComplexType()) { // 2.3.2.1
518  isOk = isComplexDerivationOk(derivedType->wxsSuperType(), baseType, constraints);
519  } else { // 2.3.2.2
520  isOk = isSimpleDerivationOk(derivedType->wxsSuperType(), baseType, constraints);
521  }
522  }
523  if (isOk)
524  return true;
525 
526  return false;
527 }
528 
531  const DerivedString<TypeString>::Ptr &operand2,
532  const SchemaType::Ptr &type,
533  const ReportContext::Ptr &context,
534  const SourceLocationReflection *const sourceLocationReflection)
535 {
537  "We can only compare atomic values.");
538 
539  // we can not cast a xs:String to a xs:QName, so lets go the safe way
540  if (type->name(context->namePool()) == BuiltinTypes::xsQName->name(context->namePool()))
541  return false;
542 
543  const AtomicValue::Ptr value1 = ValueFactory::fromLexical(operand1->stringValue(), type, context, sourceLocationReflection);
544  if (value1->hasError())
545  return false;
546 
547  const AtomicValue::Ptr value2 = ValueFactory::fromLexical(operand2->stringValue(), type, context, sourceLocationReflection);
548  if (value2->hasError())
549  return false;
550 
551  return ComparisonFactory::compare(value1, op, value2, type, context, sourceLocationReflection);
552 }
553 
554 bool XsdSchemaHelper::checkWildcardProcessContents(const XsdWildcard::Ptr &baseWildcard, const XsdWildcard::Ptr &derivedWildcard)
555 {
556  if (baseWildcard->processContents() == XsdWildcard::Strict) {
557  if (derivedWildcard->processContents() == XsdWildcard::Lax || derivedWildcard->processContents() == XsdWildcard::Skip) {
558  return false;
559  }
560  } else if (baseWildcard->processContents() == XsdWildcard::Lax) {
561  if (derivedWildcard->processContents() == XsdWildcard::Skip)
562  return false;
563  }
564 
565  return true;
566 }
567 
569 {
570  if (visitedElements.contains(member))
571  return false;
572  else
573  visitedElements.insert(member);
574 
575  if (member->substitutionGroupAffiliations().isEmpty())
576  return false;
577 
578  if (member->substitutionGroupAffiliations().contains(head)) {
579  return true;
580  } else {
581  const XsdElement::List affiliations = member->substitutionGroupAffiliations();
582  for (int i = 0; i < affiliations.count(); ++i) {
583  if (foundSubstitutionGroupTransitive(head, affiliations.at(i), visitedElements))
584  return true;
585  }
586 
587  return false;
588  }
589 }
590 
592  QSet<SchemaType::DerivationMethod> &derivationSet, NamedSchemaComponent::BlockingConstraints &blockSet)
593 {
594  if (!memberType)
595  return;
596 
597  if (memberType == headType)
598  return;
599 
600  derivationSet.insert(memberType->derivationMethod());
601 
602  if (memberType->isComplexType()) {
603  const XsdComplexType::Ptr complexType(memberType);
604  blockSet |= complexType->prohibitedSubstitutions();
605  }
606 
607  foundSubstitutionGroupTypeInheritance(headType, memberType->wxsSuperType(), derivationSet, blockSet);
608 }
609 
611 {
612  // @see http://www.w3.org/TR/xmlschema11-1/#cos-equiv-derived-ok-rec
613 
614  // 1
615  if ((member->name(namePool) == head->name(namePool)) && (member->type() == head->type()))
616  return true;
617 
618  // 2.1
620  return false;
621 
622  // 2.2
623  {
624  QSet<XsdElement::Ptr> visitedElements;
625  if (!foundSubstitutionGroupTransitive(head, member, visitedElements))
626  return false;
627  }
628 
629  // 2.3
630  {
632  NamedSchemaComponent::BlockingConstraints blockSet;
633 
634  foundSubstitutionGroupTypeInheritance(head->type(), member->type(), derivationSet, blockSet);
635 
636  NamedSchemaComponent::BlockingConstraints checkSet(blockSet);
637  checkSet |= head->disallowedSubstitutions();
638  if (head->type()->isComplexType()) {
639  const XsdComplexType::Ptr complexType(head->type());
640  checkSet |= complexType->prohibitedSubstitutions();
641  }
642 
644  return false;
646  return false;
648  return false;
649  }
650 
651  return true;
652 }
653 
654 bool XsdSchemaHelper::isValidAttributeGroupRestriction(const XsdAttributeGroup::Ptr &derivedAttributeGroup, const XsdAttributeGroup::Ptr &attributeGroup, const XsdSchemaContext::Ptr &context, QString &errorMsg)
655 {
656  // @see http://www.w3.org/TR/xmlschema-1/#derivation-ok-restriction
657 
658  const XsdAttributeUse::List derivedAttributeUses = derivedAttributeGroup->attributeUses();
659  const XsdAttributeUse::List baseAttributeUses = attributeGroup->attributeUses();
660 
661  return isValidAttributeUsesRestriction(derivedAttributeUses, baseAttributeUses,
662  derivedAttributeGroup->wildcard(), attributeGroup->wildcard(), context, errorMsg);
663 }
664 
665 bool XsdSchemaHelper::isValidAttributeUsesRestriction(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &baseAttributeUses,
666  const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg)
667 {
668  const NamePool::Ptr namePool(context->namePool());
669 
670  QHash<QXmlName, XsdAttributeUse::Ptr> baseAttributeUsesLookup;
671  for (int i = 0; i < baseAttributeUses.count(); ++i)
672  baseAttributeUsesLookup.insert(baseAttributeUses.at(i)->attribute()->name(namePool), baseAttributeUses.at(i));
673 
674  QHash<QXmlName, XsdAttributeUse::Ptr> derivedAttributeUsesLookup;
675  for (int i = 0; i < derivedAttributeUses.count(); ++i)
676  derivedAttributeUsesLookup.insert(derivedAttributeUses.at(i)->attribute()->name(namePool), derivedAttributeUses.at(i));
677 
678  // 2
679  for (int i = 0; i < derivedAttributeUses.count(); ++i) {
680  const XsdAttributeUse::Ptr derivedAttributeUse = derivedAttributeUses.at(i);
681 
682  // prohibited attributes are no real attributes, so skip them in that test here
683  if (derivedAttributeUse->useType() == XsdAttributeUse::ProhibitedUse)
684  continue;
685 
686  if (baseAttributeUsesLookup.contains(derivedAttributeUse->attribute()->name(namePool))) {
687  const XsdAttributeUse::Ptr baseAttributeUse(baseAttributeUsesLookup.value(derivedAttributeUse->attribute()->name(namePool)));
688 
689  // 2.1.1
690  if (baseAttributeUse->isRequired() == true && derivedAttributeUse->isRequired() == false) {
691  errorMsg = QtXmlPatterns::tr("Base attribute %1 is required but derived attribute is not.").arg(formatAttribute(baseAttributeUse->attribute()->displayName(namePool)));
692  return false;
693  }
694 
695  // 2.1.2
696  if (!isSimpleDerivationOk(derivedAttributeUse->attribute()->type(), baseAttributeUse->attribute()->type(), SchemaType::DerivationConstraints())) {
697  errorMsg = QtXmlPatterns::tr("Type of derived attribute %1 cannot be validly derived from type of base attribute.").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool)));
698  return false;
699  }
700 
701  // 2.1.3
702  XsdAttributeUse::ValueConstraint::Ptr derivedConstraint;
703  if (derivedAttributeUse->valueConstraint())
704  derivedConstraint = derivedAttributeUse->valueConstraint();
705  else if (derivedAttributeUse->attribute()->valueConstraint())
706  derivedConstraint = XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(derivedAttributeUse->attribute()->valueConstraint());
707 
709  if (baseAttributeUse->valueConstraint())
710  baseConstraint = baseAttributeUse->valueConstraint();
711  else if (baseAttributeUse->attribute()->valueConstraint())
712  baseConstraint = XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(baseAttributeUse->attribute()->valueConstraint());
713 
714  bool ok = false;
715  if (!baseConstraint || baseConstraint->variety() == XsdAttributeUse::ValueConstraint::Default)
716  ok = true;
717 
718  if (derivedConstraint && baseConstraint) {
719  const XsdTypeChecker checker(context, QVector<QXmlName>(), QSourceLocation(QUrl(QLatin1String("http://dummy.org")), 1, 1));
720  if (derivedConstraint->variety() == XsdAttributeUse::ValueConstraint::Fixed && checker.valuesAreEqual(derivedConstraint->value(), baseConstraint->value(), baseAttributeUse->attribute()->type()))
721  ok = true;
722  }
723 
724  if (!ok) {
725  errorMsg = QtXmlPatterns::tr("Value constraint of derived attribute %1 does not match value constraint of base attribute.").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool)));
726  return false;
727  }
728  } else {
729  if (!wildcard) {
730  errorMsg = QtXmlPatterns::tr("Derived attribute %1 does not exist in the base definition.").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool)));
731  return false;
732  }
733 
734  QXmlName name = derivedAttributeUse->attribute()->name(namePool);
735 
736  // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
738  name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace()));
739 
740  if (!wildcardAllowsExpandedName(name, wildcard, namePool)) {
741  errorMsg = QtXmlPatterns::tr("Derived attribute %1 does not match the wildcard in the base definition.").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool)));
742  return false;
743  }
744  }
745  }
746 
747  // 3
748  for (int i = 0; i < baseAttributeUses.count(); ++i) {
749  const XsdAttributeUse::Ptr baseAttributeUse = baseAttributeUses.at(i);
750 
751  if (baseAttributeUse->isRequired()) {
752  if (derivedAttributeUsesLookup.contains(baseAttributeUse->attribute()->name(namePool))) {
753  if (!derivedAttributeUsesLookup.value(baseAttributeUse->attribute()->name(namePool))->isRequired()) {
754  errorMsg = QtXmlPatterns::tr("Base attribute %1 is required but derived attribute is not.").arg(formatAttribute(baseAttributeUse->attribute()->displayName(namePool)));
755  return false;
756  }
757  } else {
758  errorMsg = QtXmlPatterns::tr("Base attribute %1 is required but missing in derived definition.").arg(formatAttribute(baseAttributeUse->attribute()->displayName(namePool)));
759  return false;
760  }
761  }
762  }
763 
764  // 4
765  if (derivedWildcard) {
766  if (!wildcard) {
767  errorMsg = QtXmlPatterns::tr("Derived definition contains an %1 element that does not exists in the base definition").arg(formatElement("anyAttribute."));
768  return false;
769  }
770 
771  if (!isWildcardSubset(derivedWildcard, wildcard)) {
772  errorMsg = QtXmlPatterns::tr("Derived wildcard is not a subset of the base wildcard.");
773  return false;
774  }
775 
776  if (!checkWildcardProcessContents(wildcard, derivedWildcard)) {
777  errorMsg = QtXmlPatterns::tr("%1 of derived wildcard is not a valid restriction of %2 of base wildcard").arg(formatKeyword("processContents")).arg(formatKeyword("processContents."));
778  return false;
779  }
780  }
781 
782  return true;
783 }
784 
786  const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg)
787 {
788  // @see http://www.w3.org/TR/xmlschema11-1/#cos-ct-extends
789 
790  const NamePool::Ptr namePool(context->namePool());
791 
792  // 1.2
794  for (int i = 0; i < derivedAttributeUses.count(); ++i)
795  lookupHash.insert(derivedAttributeUses.at(i)->attribute()->name(namePool), derivedAttributeUses.at(i)->attribute());
796 
797  for (int i = 0; i < attributeUses.count(); ++i) {
798  const QXmlName attributeName = attributeUses.at(i)->attribute()->name(namePool);
799  if (!lookupHash.contains(attributeName)) {
800  errorMsg = QtXmlPatterns::tr("Attribute %1 from base type is missing in derived type.").arg(formatKeyword(namePool->displayName(attributeName)));
801  return false;
802  }
803 
804  if (lookupHash.value(attributeName)->type() != attributeUses.at(i)->attribute()->type()) {
805  errorMsg = QtXmlPatterns::tr("Type of derived attribute %1 differs from type of base attribute.").arg(formatKeyword(namePool->displayName(attributeName)));
806  return false;
807  }
808  }
809 
810  // 1.3
811  if (wildcard) {
812  if (!derivedWildcard) {
813  errorMsg = QtXmlPatterns::tr("Base definition contains an %1 element that is missing in the derived definition").arg(formatElement("anyAttribute."));
814  return false;
815  }
816  }
817 
818  return true;
819 }
820 
static AtomicValue::Ptr fromLexical(const QString &lexicalValue, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const sourceLocationReflection)
Returns an AtomicValue of type type from the lexical space lexicalValue, and raise an error through c...
virtual TypeCategory category() const =0
int type
Definition: qmetatype.cpp:239
static QString absentNamespace()
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static bool wildcardAllowsNamespaceName(const QString &nameSpace, const XsdWildcard::NamespaceConstraint::Ptr &constraint)
virtual bool isSimpleType() const
Definition: qschematype.cpp:56
static XsdWildcard::Ptr wildcardIntersection(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard)
QString formatKeyword(const QString &keyword)
virtual bool hasError() const
#define it(className, varName)
ProcessContents processContents() const
The attribute use has a fixed value set.
XsdTerm::Ptr term() const
bool remove(const T &value)
Definition: qset.h:89
XsdWildcard::Ptr wildcard() const
The attribute is not allowed to be there.
static bool foundSubstitutionGroupTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, QSet< XsdElement::Ptr > &visitedElements)
XsdAttributeUse::List attributeUses() const
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
XsdElement::List substitutionGroupAffiliations() const
Represents a XSD wildcard object.
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
virtual NamePool::Ptr namePool() const
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
static bool constructAndCompare(const DerivedString< TypeString >::Ptr &operand1, const AtomicComparator::Operator op, const DerivedString< TypeString >::Ptr &operand2, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const sourceLocationReflection)
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
The attribute use has a default value set.
virtual bool isWildcard() const
Definition: qxsdterm.cpp:58
static ValueConstraint::Ptr fromAttributeValueConstraint(const XsdAttribute::ValueConstraint::Ptr &constraint)
static bool containsSet(const QSet< T > &super, const QSet< T > &sub)
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
Definition: qhash.h:872
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
SchemaType::Ptr type() const
static void foundSubstitutionGroupTypeInheritance(const SchemaType::Ptr &headType, const SchemaType::Ptr &memberType, QSet< SchemaType::DerivationMethod > &derivationSet, NamedSchemaComponent::BlockingConstraints &blockSet)
static const SchemaType::Ptr xsAnyType
virtual bool isElement() const
Definition: qxsdterm.cpp:48
No constraints at all: the item must simply be well-formed XML.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QSet< T > & intersect(const QSet< T > &other)
Definition: qset.h:256
virtual DerivationConstraints derivationConstraints() const =0
QBool contains(const T &t) const
Returns true if the list contains an occurrence of value; otherwise returns false.
Definition: qlist.h:880
static bool checkWildcardProcessContents(const XsdWildcard::Ptr &baseWildcard, const XsdWildcard::Ptr &derivedWildcard)
static bool isEmpty(const char *str)
There must be a top-level declaration for the item available, or the item must have an xsi:type...
unsigned int minimumOccurs() const
XsdParticle::List particles() const
static QString formatElement(const QString &element)
Formats element name.
Namespaces in the namespaces set are not allowed.
bool contains(const T &value) const
Definition: qset.h:91
virtual bool isComplexType() const
Definition: qschematype.cpp:70
const char * name
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
static bool isValidAttributeUsesExtension(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &attributeUses, const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg)
The namespace for the internal API of QtXmlPatterns.
bool isEmpty() const
Returns true if the hash contains no items; otherwise returns false.
Definition: qhash.h:297
const_iterator insert(const T &value)
Definition: qset.h:179
The QSourceLocation class identifies a location in a resource by URI, line, and column.
virtual QString stringValue() const =0
static bool isValidAttributeGroupRestriction(const XsdAttributeGroup::Ptr &derivedAttributeGroup, const XsdAttributeGroup::Ptr &attributeGroup, const XsdSchemaContext::Ptr &context, QString &errorMsg)
static bool isComplexDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr &baseType, const SchemaType::DerivationConstraints &constraints)
QSet< T > & subtract(const QSet< T > &other)
Definition: qset.h:270
virtual QXmlName name(const NamePool::Ptr &namePool) const
static bool isSimpleDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr &baseType, const SchemaType::DerivationConstraints &constraints)
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
NamespaceCode namespaceURI() const
Definition: qnamepool_p.h:503
static bool isWildcardSubset(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard)
bool valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const
NamespaceConstraint::Ptr namespaceConstraint() const
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
The QXmlName class represents the name of an XML node, in an efficient, namespace-aware way...
Definition: qxmlname.h:58
QExplicitlySharedDataPointer< XsdWildcard > Ptr
static const AtomicType::Ptr xsQName
QExplicitlySharedDataPointer< XsdSimpleType > Ptr
XsdFacet::Hash facets() const
static const char *const keywords[MAX_KEYWORD]
static unsigned int effectiveTotalRangeMinimum(const XsdParticle::Ptr &particle)
static const SchemaType::Ptr xsAnySimpleType
const QString & stringForNamespace(const QXmlName::NamespaceCode code) const
Definition: qnamepool_p.h:180
static XsdWildcard::Ptr wildcardUnion(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard)
virtual DerivationMethod derivationMethod() const =0
virtual bool isModelGroup() const
Definition: qxsdterm.cpp:53
AnySimpleType::List memberTypes() const
BlockingConstraints disallowedSubstitutions() const
static bool isParticleEmptiable(const XsdParticle::Ptr &particle)
static bool substitutionGroupOkTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, const NamePool::Ptr &namePool)
ModelCompositor compositor() const
Namespaces in the namespaces set are allowed.
QList< T > values() const
Definition: qset.h:232
If the item has a uniquely determined declaration available, it must be valid with respect to that de...
static bool isValidlySubstitutable(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, const SchemaType::DerivationConstraints &constraints)
static QString formatAttribute(const QString &attribute)
Formats attribute name.
BlockingConstraints prohibitedSubstitutions() const
static bool wildcardAllowsExpandedName(const QXmlName &name, const XsdWildcard::Ptr &wildcard, const NamePool::Ptr &namePool)
virtual bool isDefinedBySchema() const
Definition: qschematype.cpp:75
static SchemaType::DerivationConstraints convertBlockingConstraints(const NamedSchemaComponent::BlockingConstraints &constraints)
The class that provides methods for checking a string against a type.
virtual SchemaType::Ptr wxsSuperType() const =0
void setNamespaceURI(const NamespaceCode c)
Definition: qnamepool_p.h:518
virtual QXmlName name(const NamePool::Ptr &np) const =0
Returns the name of the type.
static bool compare(const AtomicValue::Ptr &operand1, const AtomicComparator::Operator op, const AtomicValue::Ptr &operand2, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const sourceLocationReflection)
Returns the result of evaluating operator op applied to the atomic values operand1 and operand2...
Base class for all instances that represents something at a certain location.
static bool isValidAttributeUsesRestriction(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &attributeUses, const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg)
#define Q_FUNC_INFO
Definition: qglobal.h:1871