1 //------------------------------------------------------------------------------
2 // <copyright file="XmlSchemaFacet.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 namespace System.Xml.Schema {
11 using System.ComponentModel;
12 using System.Xml.Serialization;
13 using System.Xml.Schema;
14 using System.Xml.XPath;
15 using System.Diagnostics;
16 using System.Collections;
18 using System.Text.RegularExpressions;
19 using System.Threading;
20 using System.Globalization;
22 /// <include file='doc\XmlSchemaFacet.uex' path='docs/doc[@for="XmlSchemaFacet"]/*' />
23 internal abstract class FacetsChecker {
25 private struct FacetsCompiler {
26 DatatypeImplementation datatype;
27 RestrictionFacets derivedRestriction;
29 RestrictionFlags baseFlags;
30 RestrictionFlags baseFixedFlags;
31 RestrictionFlags validRestrictionFlags;
34 XmlSchemaDatatype nonNegativeInt;
35 XmlSchemaDatatype builtInType;
36 XmlTypeCode builtInEnum;
40 XmlSchemaPatternFacet pattern_facet;
42 public FacetsCompiler(DatatypeImplementation baseDatatype, RestrictionFacets restriction) {
46 datatype = baseDatatype;
47 derivedRestriction = restriction;
48 baseFlags = datatype.Restriction != null ? datatype.Restriction.Flags : 0;
49 baseFixedFlags = datatype.Restriction != null ? datatype.Restriction.FixedFlags : 0;
50 validRestrictionFlags = datatype.ValidRestrictionFlags;
51 nonNegativeInt = DatatypeImplementation.GetSimpleTypeFromTypeCode(XmlTypeCode.NonNegativeInteger).Datatype;
52 builtInEnum = !(datatype is Datatype_union || datatype is Datatype_List) ? datatype.TypeCode : 0;
53 builtInType = (int)builtInEnum > 0 ? DatatypeImplementation.GetSimpleTypeFromTypeCode(builtInEnum).Datatype : datatype;
56 internal void CompileLengthFacet(XmlSchemaFacet facet) {
57 CheckProhibitedFlag(facet, RestrictionFlags.Length, Res.Sch_LengthFacetProhibited);
58 CheckDupFlag(facet, RestrictionFlags.Length, Res.Sch_DupLengthFacet);
59 derivedRestriction.Length = XmlBaseConverter.DecimalToInt32((decimal)ParseFacetValue(nonNegativeInt, facet, Res.Sch_LengthFacetInvalid, null, null));
61 if ((baseFixedFlags & RestrictionFlags.Length) != 0) {
62 if (!datatype.IsEqual(datatype.Restriction.Length, derivedRestriction.Length)) {
63 throw new XmlSchemaException(Res.Sch_FacetBaseFixed, facet);
66 if ((baseFlags & RestrictionFlags.Length) != 0) {
67 if (datatype.Restriction.Length < derivedRestriction.Length) {
68 throw new XmlSchemaException(Res.Sch_LengthGtBaseLength, facet);
71 // If the base has the MinLength facet, check that our derived length is not violating it
72 if ((baseFlags & RestrictionFlags.MinLength) != 0) {
73 if (datatype.Restriction.MinLength > derivedRestriction.Length) {
74 throw new XmlSchemaException(Res.Sch_MaxMinLengthBaseLength, facet);
77 // If the base has the MaxLength facet, check that our derived length is not violating it
78 if ((baseFlags & RestrictionFlags.MaxLength) != 0) {
79 if (datatype.Restriction.MaxLength < derivedRestriction.Length) {
80 throw new XmlSchemaException(Res.Sch_MaxMinLengthBaseLength, facet);
83 SetFlag(facet, RestrictionFlags.Length);
86 internal void CompileMinLengthFacet(XmlSchemaFacet facet) {
87 CheckProhibitedFlag(facet, RestrictionFlags.MinLength, Res.Sch_MinLengthFacetProhibited);
88 CheckDupFlag(facet, RestrictionFlags.MinLength, Res.Sch_DupMinLengthFacet);
89 derivedRestriction.MinLength = XmlBaseConverter.DecimalToInt32((decimal)ParseFacetValue(nonNegativeInt, facet, Res.Sch_MinLengthFacetInvalid, null, null));
91 if ((baseFixedFlags & RestrictionFlags.MinLength) != 0) {
92 if (!datatype.IsEqual(datatype.Restriction.MinLength, derivedRestriction.MinLength)) {
93 throw new XmlSchemaException(Res.Sch_FacetBaseFixed, facet);
96 if ((baseFlags & RestrictionFlags.MinLength) != 0) {
97 if (datatype.Restriction.MinLength > derivedRestriction.MinLength) {
98 throw new XmlSchemaException(Res.Sch_MinLengthGtBaseMinLength, facet);
101 if ((baseFlags & RestrictionFlags.Length) != 0) {
102 if (datatype.Restriction.Length < derivedRestriction.MinLength) {
103 throw new XmlSchemaException(Res.Sch_MaxMinLengthBaseLength, facet);
106 SetFlag(facet, RestrictionFlags.MinLength);
109 internal void CompileMaxLengthFacet(XmlSchemaFacet facet) {
110 CheckProhibitedFlag(facet, RestrictionFlags.MaxLength, Res.Sch_MaxLengthFacetProhibited);
111 CheckDupFlag(facet, RestrictionFlags.MaxLength, Res.Sch_DupMaxLengthFacet);
112 derivedRestriction.MaxLength = XmlBaseConverter.DecimalToInt32((decimal)ParseFacetValue(nonNegativeInt, facet, Res.Sch_MaxLengthFacetInvalid, null, null));
114 if ((baseFixedFlags & RestrictionFlags.MaxLength) != 0) {
115 if (!datatype.IsEqual(datatype.Restriction.MaxLength, derivedRestriction.MaxLength)) {
116 throw new XmlSchemaException(Res.Sch_FacetBaseFixed, facet);
119 if ((baseFlags & RestrictionFlags.MaxLength) != 0) {
120 if (datatype.Restriction.MaxLength < derivedRestriction.MaxLength) {
121 throw new XmlSchemaException(Res.Sch_MaxLengthGtBaseMaxLength, facet);
124 if ((baseFlags & RestrictionFlags.Length) != 0) {
125 if (datatype.Restriction.Length > derivedRestriction.MaxLength) {
126 throw new XmlSchemaException(Res.Sch_MaxMinLengthBaseLength, facet);
129 SetFlag(facet, RestrictionFlags.MaxLength);
132 internal void CompilePatternFacet(XmlSchemaPatternFacet facet) {
133 CheckProhibitedFlag(facet, RestrictionFlags.Pattern, Res.Sch_PatternFacetProhibited);
134 if(firstPattern == true) {
135 regStr = new StringBuilder();
137 regStr.Append(facet.Value);
138 pattern_facet = facet;
139 firstPattern = false;
142 regStr.Append(")|(");
143 regStr.Append(facet.Value);
145 SetFlag(facet, RestrictionFlags.Pattern);
148 internal void CompileEnumerationFacet(XmlSchemaFacet facet, IXmlNamespaceResolver nsmgr, XmlNameTable nameTable) {
149 CheckProhibitedFlag(facet, RestrictionFlags.Enumeration, Res.Sch_EnumerationFacetProhibited);
150 if (derivedRestriction.Enumeration == null) {
151 derivedRestriction.Enumeration = new ArrayList();
153 derivedRestriction.Enumeration.Add(ParseFacetValue(datatype, facet, Res.Sch_EnumerationFacetInvalid, nsmgr, nameTable));
154 SetFlag(facet, RestrictionFlags.Enumeration);
157 internal void CompileWhitespaceFacet(XmlSchemaFacet facet) {
158 CheckProhibitedFlag(facet, RestrictionFlags.WhiteSpace, Res.Sch_WhiteSpaceFacetProhibited);
159 CheckDupFlag(facet, RestrictionFlags.WhiteSpace, Res.Sch_DupWhiteSpaceFacet);
160 if (facet.Value == "preserve") {
161 derivedRestriction.WhiteSpace = XmlSchemaWhiteSpace.Preserve;
163 else if (facet.Value == "replace") {
164 derivedRestriction.WhiteSpace = XmlSchemaWhiteSpace.Replace;
166 else if (facet.Value == "collapse") {
167 derivedRestriction.WhiteSpace = XmlSchemaWhiteSpace.Collapse;
170 throw new XmlSchemaException(Res.Sch_InvalidWhiteSpace, facet.Value, facet);
172 if ((baseFixedFlags & RestrictionFlags.WhiteSpace) != 0) {
173 if (!datatype.IsEqual(datatype.Restriction.WhiteSpace, derivedRestriction.WhiteSpace)) {
174 throw new XmlSchemaException(Res.Sch_FacetBaseFixed, facet);
177 //Check base and derived whitespace facets
178 XmlSchemaWhiteSpace baseWhitespace;
179 if ((baseFlags & RestrictionFlags.WhiteSpace) != 0) {
180 baseWhitespace = datatype.Restriction.WhiteSpace;
183 baseWhitespace = datatype.BuiltInWhitespaceFacet;
185 if ( baseWhitespace == XmlSchemaWhiteSpace.Collapse &&
186 (derivedRestriction.WhiteSpace == XmlSchemaWhiteSpace.Replace || derivedRestriction.WhiteSpace == XmlSchemaWhiteSpace.Preserve)
188 throw new XmlSchemaException(Res.Sch_WhiteSpaceRestriction1, facet);
190 if (baseWhitespace == XmlSchemaWhiteSpace.Replace &&
191 derivedRestriction.WhiteSpace == XmlSchemaWhiteSpace.Preserve
193 throw new XmlSchemaException(Res.Sch_WhiteSpaceRestriction2, facet);
195 SetFlag(facet, RestrictionFlags.WhiteSpace);
198 internal void CompileMaxInclusiveFacet(XmlSchemaFacet facet) {
199 CheckProhibitedFlag(facet, RestrictionFlags.MaxInclusive, Res.Sch_MaxInclusiveFacetProhibited);
200 CheckDupFlag(facet, RestrictionFlags.MaxInclusive, Res.Sch_DupMaxInclusiveFacet);
201 derivedRestriction.MaxInclusive = ParseFacetValue(builtInType, facet, Res.Sch_MaxInclusiveFacetInvalid, null, null);
203 if ((baseFixedFlags & RestrictionFlags.MaxInclusive) != 0) {
204 if (!datatype.IsEqual(datatype.Restriction.MaxInclusive, derivedRestriction.MaxInclusive)) {
205 throw new XmlSchemaException(Res.Sch_FacetBaseFixed, facet);
208 CheckValue(derivedRestriction.MaxInclusive, facet);
209 SetFlag(facet, RestrictionFlags.MaxInclusive);
212 internal void CompileMaxExclusiveFacet(XmlSchemaFacet facet) {
213 CheckProhibitedFlag(facet, RestrictionFlags.MaxExclusive, Res.Sch_MaxExclusiveFacetProhibited);
214 CheckDupFlag(facet, RestrictionFlags.MaxExclusive, Res.Sch_DupMaxExclusiveFacet);
215 derivedRestriction.MaxExclusive = ParseFacetValue(builtInType, facet, Res.Sch_MaxExclusiveFacetInvalid, null, null);
217 if ((baseFixedFlags & RestrictionFlags.MaxExclusive) != 0) {
218 if (!datatype.IsEqual(datatype.Restriction.MaxExclusive, derivedRestriction.MaxExclusive)) {
219 throw new XmlSchemaException(Res.Sch_FacetBaseFixed, facet);
222 CheckValue(derivedRestriction.MaxExclusive, facet);
223 SetFlag(facet, RestrictionFlags.MaxExclusive);
226 internal void CompileMinInclusiveFacet(XmlSchemaFacet facet) {
227 CheckProhibitedFlag(facet, RestrictionFlags.MinInclusive, Res.Sch_MinInclusiveFacetProhibited);
228 CheckDupFlag(facet, RestrictionFlags.MinInclusive, Res.Sch_DupMinInclusiveFacet);
229 derivedRestriction.MinInclusive = ParseFacetValue(builtInType, facet, Res.Sch_MinInclusiveFacetInvalid, null, null);
231 if ((baseFixedFlags & RestrictionFlags.MinInclusive) != 0) {
232 if (!datatype.IsEqual(datatype.Restriction.MinInclusive, derivedRestriction.MinInclusive)) {
233 throw new XmlSchemaException(Res.Sch_FacetBaseFixed, facet);
236 CheckValue(derivedRestriction.MinInclusive, facet);
237 SetFlag(facet, RestrictionFlags.MinInclusive);
240 internal void CompileMinExclusiveFacet(XmlSchemaFacet facet) {
241 CheckProhibitedFlag(facet, RestrictionFlags.MinExclusive, Res.Sch_MinExclusiveFacetProhibited);
242 CheckDupFlag(facet, RestrictionFlags.MinExclusive, Res.Sch_DupMinExclusiveFacet);
243 derivedRestriction.MinExclusive = ParseFacetValue(builtInType, facet, Res.Sch_MinExclusiveFacetInvalid, null, null);
245 if ((baseFixedFlags & RestrictionFlags.MinExclusive) != 0) {
246 if (!datatype.IsEqual(datatype.Restriction.MinExclusive, derivedRestriction.MinExclusive)) {
247 throw new XmlSchemaException(Res.Sch_FacetBaseFixed, facet);
250 CheckValue(derivedRestriction.MinExclusive, facet);
251 SetFlag(facet, RestrictionFlags.MinExclusive);
254 internal void CompileTotalDigitsFacet(XmlSchemaFacet facet) {
255 CheckProhibitedFlag(facet, RestrictionFlags.TotalDigits, Res.Sch_TotalDigitsFacetProhibited);
256 CheckDupFlag(facet, RestrictionFlags.TotalDigits, Res.Sch_DupTotalDigitsFacet);
257 XmlSchemaDatatype positiveInt = DatatypeImplementation.GetSimpleTypeFromTypeCode(XmlTypeCode.PositiveInteger).Datatype;
258 derivedRestriction.TotalDigits = XmlBaseConverter.DecimalToInt32((decimal)ParseFacetValue(positiveInt, facet, Res.Sch_TotalDigitsFacetInvalid, null, null));
260 if ((baseFixedFlags & RestrictionFlags.TotalDigits) != 0) {
261 if (!datatype.IsEqual(datatype.Restriction.TotalDigits, derivedRestriction.TotalDigits)) {
262 throw new XmlSchemaException(Res.Sch_FacetBaseFixed, facet);
265 if ((baseFlags & RestrictionFlags.TotalDigits) != 0) {
266 if(derivedRestriction.TotalDigits > datatype.Restriction.TotalDigits) {
267 throw new XmlSchemaException(Res.Sch_TotalDigitsMismatch, string.Empty);
270 SetFlag(facet, RestrictionFlags.TotalDigits);
273 internal void CompileFractionDigitsFacet(XmlSchemaFacet facet) {
274 CheckProhibitedFlag(facet, RestrictionFlags.FractionDigits, Res.Sch_FractionDigitsFacetProhibited);
275 CheckDupFlag(facet, RestrictionFlags.FractionDigits, Res.Sch_DupFractionDigitsFacet);
276 derivedRestriction.FractionDigits = XmlBaseConverter.DecimalToInt32((decimal)ParseFacetValue(nonNegativeInt, facet, Res.Sch_FractionDigitsFacetInvalid, null, null));
278 if ((derivedRestriction.FractionDigits != 0) && (datatype.TypeCode != XmlTypeCode.Decimal)) {
279 throw new XmlSchemaException(Res.Sch_FractionDigitsFacetInvalid, Res.GetString(Res.Sch_FractionDigitsNotOnDecimal), facet);
281 if ((baseFlags & RestrictionFlags.FractionDigits) != 0) {
282 if (derivedRestriction.FractionDigits > datatype.Restriction.FractionDigits) {
283 throw new XmlSchemaException(Res.Sch_TotalDigitsMismatch, string.Empty);
286 SetFlag(facet, RestrictionFlags.FractionDigits);
289 internal void FinishFacetCompile() {
290 //Additional check for pattern facet
291 //If facet is XMLSchemaPattern, then the String built inside the loop
292 //needs to be converted to a RegEx
293 if(firstPattern == false) {
294 if (derivedRestriction.Patterns == null) {
295 derivedRestriction.Patterns = new ArrayList();
299 string tempStr = regStr.ToString();
300 if(tempStr.IndexOf('|') != -1) { // ordinal compare
301 regStr.Insert(0,"(");
304 derivedRestriction.Patterns.Add(new Regex(Preprocess(regStr.ToString()), RegexOptions.None));
306 } catch (Exception e) {
307 throw new XmlSchemaException(Res.Sch_PatternFacetInvalid, new string[] {e.Message}, e, pattern_facet.SourceUri, pattern_facet.LineNumber, pattern_facet.LinePosition, pattern_facet);
312 private void CheckValue(object value, XmlSchemaFacet facet) {
313 RestrictionFacets restriction = datatype.Restriction;
314 switch (facet.FacetType) {
315 case FacetType.MaxInclusive:
316 if ((baseFlags & RestrictionFlags.MaxInclusive) != 0) { //Base facet has maxInclusive
317 if (datatype.Compare(value, restriction.MaxInclusive) > 0) {
318 throw new XmlSchemaException(Res.Sch_MaxInclusiveMismatch, string.Empty);
321 if ((baseFlags & RestrictionFlags.MaxExclusive) != 0) { //Base facet has maxExclusive
322 if (datatype.Compare(value, restriction.MaxExclusive) >= 0) {
323 throw new XmlSchemaException(Res.Sch_MaxIncExlMismatch, string.Empty);
328 case FacetType.MaxExclusive:
329 if ((baseFlags & RestrictionFlags.MaxExclusive) != 0) { //Base facet has maxExclusive
330 if (datatype.Compare(value, restriction.MaxExclusive) > 0) {
331 throw new XmlSchemaException(Res.Sch_MaxExclusiveMismatch, string.Empty);
334 if ((baseFlags & RestrictionFlags.MaxInclusive) != 0) { //Base facet has maxInclusive
335 if (datatype.Compare(value, restriction.MaxInclusive) > 0) {
336 throw new XmlSchemaException(Res.Sch_MaxExlIncMismatch, string.Empty);
341 case FacetType.MinInclusive:
342 if ((baseFlags & RestrictionFlags.MinInclusive) != 0) { //Base facet has minInclusive
343 if (datatype.Compare(value, restriction.MinInclusive) < 0) {
344 throw new XmlSchemaException(Res.Sch_MinInclusiveMismatch, string.Empty);
347 if ((baseFlags & RestrictionFlags.MinExclusive) != 0) { //Base facet has minExclusive
348 if (datatype.Compare(value, restriction.MinExclusive) < 0) {
349 throw new XmlSchemaException(Res.Sch_MinIncExlMismatch, string.Empty);
352 if ((baseFlags & RestrictionFlags.MaxExclusive) != 0) { //Base facet has maxExclusive
353 if (datatype.Compare(value, restriction.MaxExclusive) >= 0) {
354 throw new XmlSchemaException(Res.Sch_MinIncMaxExlMismatch, string.Empty);
359 case FacetType.MinExclusive:
360 if ((baseFlags & RestrictionFlags.MinExclusive) != 0) { //Base facet has minExclusive
361 if (datatype.Compare(value, restriction.MinExclusive) < 0) {
362 throw new XmlSchemaException(Res.Sch_MinExclusiveMismatch, string.Empty);
365 if ((baseFlags & RestrictionFlags.MinInclusive) != 0) { //Base facet has minInclusive
366 if (datatype.Compare(value, restriction.MinInclusive) < 0) {
367 throw new XmlSchemaException(Res.Sch_MinExlIncMismatch, string.Empty);
370 if ((baseFlags & RestrictionFlags.MaxExclusive) != 0) { //Base facet has maxExclusive
371 if (datatype.Compare(value, restriction.MaxExclusive) >= 0) {
372 throw new XmlSchemaException(Res.Sch_MinExlMaxExlMismatch, string.Empty);
383 internal void CompileFacetCombinations() {
384 RestrictionFacets baseRestriction = datatype.Restriction;
385 //They are not allowed on the same type but allowed on derived types.
387 (derivedRestriction.Flags & RestrictionFlags.MaxInclusive) != 0 &&
388 (derivedRestriction.Flags & RestrictionFlags.MaxExclusive) != 0
390 throw new XmlSchemaException(Res.Sch_MaxInclusiveExclusive, string.Empty);
393 (derivedRestriction.Flags & RestrictionFlags.MinInclusive) != 0 &&
394 (derivedRestriction.Flags & RestrictionFlags.MinExclusive) != 0
396 throw new XmlSchemaException(Res.Sch_MinInclusiveExclusive, string.Empty);
399 (derivedRestriction.Flags & RestrictionFlags.Length) != 0 &&
400 (derivedRestriction.Flags & (RestrictionFlags.MinLength|RestrictionFlags.MaxLength)) != 0
402 throw new XmlSchemaException(Res.Sch_LengthAndMinMax, string.Empty);
405 CopyFacetsFromBaseType();
407 // Check combinations
409 (derivedRestriction.Flags & RestrictionFlags.MinLength) != 0 &&
410 (derivedRestriction.Flags & RestrictionFlags.MaxLength) != 0
412 if (derivedRestriction.MinLength > derivedRestriction.MaxLength) {
413 throw new XmlSchemaException(Res.Sch_MinLengthGtMaxLength, string.Empty);
419 (derivedRestriction.Flags & RestrictionFlags.MinInclusive) != 0 &&
420 (derivedRestriction.Flags & RestrictionFlags.MaxInclusive) != 0
422 if (datatype.Compare(derivedRestriction.MinInclusive, derivedRestriction.MaxInclusive) > 0) {
423 throw new XmlSchemaException(Res.Sch_MinInclusiveGtMaxInclusive, string.Empty);
427 (derivedRestriction.Flags & RestrictionFlags.MinInclusive) != 0 &&
428 (derivedRestriction.Flags & RestrictionFlags.MaxExclusive) != 0
430 if (datatype.Compare(derivedRestriction.MinInclusive, derivedRestriction.MaxExclusive) > 0) {
431 throw new XmlSchemaException(Res.Sch_MinInclusiveGtMaxExclusive, string.Empty);
435 (derivedRestriction.Flags & RestrictionFlags.MinExclusive) != 0 &&
436 (derivedRestriction.Flags & RestrictionFlags.MaxExclusive) != 0
438 if (datatype.Compare(derivedRestriction.MinExclusive, derivedRestriction.MaxExclusive) > 0) {
439 throw new XmlSchemaException(Res.Sch_MinExclusiveGtMaxExclusive, string.Empty);
443 (derivedRestriction.Flags & RestrictionFlags.MinExclusive) != 0 &&
444 (derivedRestriction.Flags & RestrictionFlags.MaxInclusive) != 0
446 if (datatype.Compare(derivedRestriction.MinExclusive, derivedRestriction.MaxInclusive) > 0) {
447 throw new XmlSchemaException(Res.Sch_MinExclusiveGtMaxInclusive, string.Empty);
450 if ((derivedRestriction.Flags & (RestrictionFlags.TotalDigits|RestrictionFlags.FractionDigits)) == (RestrictionFlags.TotalDigits|RestrictionFlags.FractionDigits)) {
451 if (derivedRestriction.FractionDigits > derivedRestriction.TotalDigits) {
452 throw new XmlSchemaException(Res.Sch_FractionDigitsGtTotalDigits, string.Empty);
457 private void CopyFacetsFromBaseType() {
458 RestrictionFacets baseRestriction = datatype.Restriction;
459 // Copy additional facets from the base type
461 (derivedRestriction.Flags & RestrictionFlags.Length) == 0 &&
462 (baseFlags & RestrictionFlags.Length) != 0
464 derivedRestriction.Length = baseRestriction.Length;
465 SetFlag(RestrictionFlags.Length);
468 (derivedRestriction.Flags & RestrictionFlags.MinLength) == 0 &&
469 (baseFlags & RestrictionFlags.MinLength) != 0
471 derivedRestriction.MinLength = baseRestriction.MinLength;
472 SetFlag(RestrictionFlags.MinLength);
475 (derivedRestriction.Flags & RestrictionFlags.MaxLength) == 0 &&
476 (baseFlags & RestrictionFlags.MaxLength) != 0
478 derivedRestriction.MaxLength = baseRestriction.MaxLength;
479 SetFlag(RestrictionFlags.MaxLength);
481 if ((baseFlags & RestrictionFlags.Pattern) != 0) {
482 if (derivedRestriction.Patterns == null) {
483 derivedRestriction.Patterns = baseRestriction.Patterns;
486 derivedRestriction.Patterns.AddRange(baseRestriction.Patterns);
488 SetFlag(RestrictionFlags.Pattern);
491 if ((baseFlags & RestrictionFlags.Enumeration) != 0) {
492 if (derivedRestriction.Enumeration == null) {
493 derivedRestriction.Enumeration = baseRestriction.Enumeration;
495 SetFlag(RestrictionFlags.Enumeration);
499 (derivedRestriction.Flags & RestrictionFlags.WhiteSpace) == 0 &&
500 (baseFlags & RestrictionFlags.WhiteSpace) != 0
502 derivedRestriction.WhiteSpace = baseRestriction.WhiteSpace;
503 SetFlag(RestrictionFlags.WhiteSpace);
506 (derivedRestriction.Flags & RestrictionFlags.MaxInclusive) == 0 &&
507 (baseFlags & RestrictionFlags.MaxInclusive) != 0
509 derivedRestriction.MaxInclusive = baseRestriction.MaxInclusive;
510 SetFlag(RestrictionFlags.MaxInclusive);
513 (derivedRestriction.Flags & RestrictionFlags.MaxExclusive) == 0 &&
514 (baseFlags & RestrictionFlags.MaxExclusive) != 0
516 derivedRestriction.MaxExclusive = baseRestriction.MaxExclusive;
517 SetFlag(RestrictionFlags.MaxExclusive);
520 (derivedRestriction.Flags & RestrictionFlags.MinInclusive) == 0 &&
521 (baseFlags & RestrictionFlags.MinInclusive) != 0
523 derivedRestriction.MinInclusive = baseRestriction.MinInclusive;
524 SetFlag(RestrictionFlags.MinInclusive);
527 (derivedRestriction.Flags & RestrictionFlags.MinExclusive) == 0 &&
528 (baseFlags & RestrictionFlags.MinExclusive) != 0
530 derivedRestriction.MinExclusive = baseRestriction.MinExclusive;
531 SetFlag(RestrictionFlags.MinExclusive);
534 (derivedRestriction.Flags & RestrictionFlags.TotalDigits) == 0 &&
535 (baseFlags & RestrictionFlags.TotalDigits) != 0
537 derivedRestriction.TotalDigits = baseRestriction.TotalDigits;
538 SetFlag(RestrictionFlags.TotalDigits);
541 (derivedRestriction.Flags & RestrictionFlags.FractionDigits) == 0 &&
542 (baseFlags & RestrictionFlags.FractionDigits) != 0
544 derivedRestriction.FractionDigits = baseRestriction.FractionDigits;
545 SetFlag(RestrictionFlags.FractionDigits);
549 private object ParseFacetValue(XmlSchemaDatatype datatype, XmlSchemaFacet facet, string code, IXmlNamespaceResolver nsmgr, XmlNameTable nameTable) {
551 Exception ex = datatype.TryParseValue(facet.Value, nameTable, nsmgr, out typedValue);
556 throw new XmlSchemaException(code, new string[] {ex.Message} , ex, facet.SourceUri, facet.LineNumber, facet.LinePosition, facet);
561 internal Map(char m, string r) {
566 internal string replacement;
569 private static readonly Map[] c_map = {
570 new Map('c', "\\p{_xmlC}"),
571 new Map('C', "\\P{_xmlC}"),
572 new Map('d', "\\p{_xmlD}"),
573 new Map('D', "\\P{_xmlD}"),
574 new Map('i', "\\p{_xmlI}"),
575 new Map('I', "\\P{_xmlI}"),
576 new Map('w', "\\p{_xmlW}"),
577 new Map('W', "\\P{_xmlW}"),
579 private static string Preprocess(string pattern) {
580 StringBuilder bufBld = new StringBuilder();
583 char[] source = pattern.ToCharArray();
584 int length = pattern.Length;
585 int copyPosition = 0;
586 for (int position = 0; position < length - 2; position ++) {
587 if (source[position] == '\\') {
588 if (source[position + 1] == '\\') {
589 position ++; // skip it
592 char ch = source[position + 1];
593 for (int i = 0; i < c_map.Length; i++) {
594 if (c_map[i].match == ch) {
595 if (copyPosition < position) {
596 bufBld.Append(source, copyPosition, position - copyPosition);
598 bufBld.Append(c_map[i].replacement);
600 copyPosition = position + 1;
607 if (copyPosition < length) {
608 bufBld.Append(source, copyPosition, length - copyPosition);
612 return bufBld.ToString();
615 private void CheckProhibitedFlag(XmlSchemaFacet facet, RestrictionFlags flag, string errorCode) {
616 if ((validRestrictionFlags & flag) == 0) {
617 throw new XmlSchemaException(errorCode, datatype.TypeCodeString, facet);
621 private void CheckDupFlag(XmlSchemaFacet facet, RestrictionFlags flag, string errorCode) {
622 if ((derivedRestriction.Flags & flag) != 0) {
623 throw new XmlSchemaException(errorCode, facet);
627 private void SetFlag(XmlSchemaFacet facet, RestrictionFlags flag) {
628 derivedRestriction.Flags |= flag;
630 derivedRestriction.FixedFlags |= flag;
634 private void SetFlag(RestrictionFlags flag) {
635 derivedRestriction.Flags |= flag;
636 if ((baseFixedFlags & flag) != 0) {
637 derivedRestriction.FixedFlags |= flag;
643 internal virtual Exception CheckLexicalFacets(ref string parseString, XmlSchemaDatatype datatype) {
644 CheckWhitespaceFacets(ref parseString, datatype);
645 return CheckPatternFacets(datatype.Restriction, parseString);
647 internal virtual Exception CheckValueFacets(object value, XmlSchemaDatatype datatype) {
650 internal virtual Exception CheckValueFacets(decimal value, XmlSchemaDatatype datatype) {
653 internal virtual Exception CheckValueFacets(Int64 value, XmlSchemaDatatype datatype) {
656 internal virtual Exception CheckValueFacets(Int32 value, XmlSchemaDatatype datatype) {
659 internal virtual Exception CheckValueFacets(Int16 value, XmlSchemaDatatype datatype) {
662 internal virtual Exception CheckValueFacets(byte value, XmlSchemaDatatype datatype) {
665 internal virtual Exception CheckValueFacets(DateTime value, XmlSchemaDatatype datatype) {
668 internal virtual Exception CheckValueFacets(double value, XmlSchemaDatatype datatype) {
671 internal virtual Exception CheckValueFacets(float value, XmlSchemaDatatype datatype) {
674 internal virtual Exception CheckValueFacets(string value, XmlSchemaDatatype datatype) {
677 internal virtual Exception CheckValueFacets(byte[] value, XmlSchemaDatatype datatype) {
680 internal virtual Exception CheckValueFacets(TimeSpan value, XmlSchemaDatatype datatype) {
683 internal virtual Exception CheckValueFacets(XmlQualifiedName value, XmlSchemaDatatype datatype) {
687 internal void CheckWhitespaceFacets(ref string s, XmlSchemaDatatype datatype) {
688 // before parsing, check whitespace facet
689 RestrictionFacets restriction = datatype.Restriction;
691 switch (datatype.Variety) {
692 case XmlSchemaDatatypeVariety.List:
696 case XmlSchemaDatatypeVariety.Atomic:
697 if (datatype.BuiltInWhitespaceFacet == XmlSchemaWhiteSpace.Collapse) {
698 s = XmlComplianceUtil.NonCDataNormalize(s);
700 else if (datatype.BuiltInWhitespaceFacet == XmlSchemaWhiteSpace.Replace) {
701 s = XmlComplianceUtil.CDataNormalize(s);
703 else if (restriction != null && (restriction.Flags & RestrictionFlags.WhiteSpace) != 0) { //Restriction has whitespace facet specified
704 if (restriction.WhiteSpace == XmlSchemaWhiteSpace.Replace) {
705 s = XmlComplianceUtil.CDataNormalize(s);
707 else if (restriction.WhiteSpace == XmlSchemaWhiteSpace.Collapse) {
708 s = XmlComplianceUtil.NonCDataNormalize(s);
718 internal Exception CheckPatternFacets(RestrictionFacets restriction, string value) {
719 if (restriction != null && (restriction.Flags & RestrictionFlags.Pattern) != 0) {
720 for (int i = 0; i < restriction.Patterns.Count; ++i) {
721 Regex regex = (Regex)restriction.Patterns[i];
722 if (!regex.IsMatch(value)) {
723 return new XmlSchemaException(Res.Sch_PatternConstraintFailed, string.Empty);
730 internal virtual bool MatchEnumeration(object value, ArrayList enumeration, XmlSchemaDatatype datatype) {
734 //Compile-time Facet Checking
735 internal virtual RestrictionFacets ConstructRestriction(DatatypeImplementation datatype, XmlSchemaObjectCollection facets, XmlNameTable nameTable) {
736 //Datatype is the type on which this method is called
737 RestrictionFacets derivedRestriction = new RestrictionFacets();
738 FacetsCompiler facetCompiler = new FacetsCompiler(datatype, derivedRestriction);
740 for (int i = 0; i < facets.Count; ++i) {
741 XmlSchemaFacet facet = (XmlSchemaFacet)facets[i];
742 if (facet.Value == null) {
743 throw new XmlSchemaException(Res.Sch_InvalidFacet, facet);
745 IXmlNamespaceResolver nsmgr = new SchemaNamespaceManager(facet);
746 switch(facet.FacetType) {
747 case FacetType.Length:
748 facetCompiler.CompileLengthFacet(facet);
751 case FacetType.MinLength:
752 facetCompiler.CompileMinLengthFacet(facet);
755 case FacetType.MaxLength:
756 facetCompiler.CompileMaxLengthFacet(facet);
759 case FacetType.Pattern:
760 facetCompiler.CompilePatternFacet(facet as XmlSchemaPatternFacet);
763 case FacetType.Enumeration:
764 facetCompiler.CompileEnumerationFacet(facet, nsmgr, nameTable);
767 case FacetType.Whitespace:
768 facetCompiler.CompileWhitespaceFacet(facet);
771 case FacetType.MinInclusive:
772 facetCompiler.CompileMinInclusiveFacet(facet);
775 case FacetType.MinExclusive:
776 facetCompiler.CompileMinExclusiveFacet(facet);
779 case FacetType.MaxInclusive:
780 facetCompiler.CompileMaxInclusiveFacet(facet);
783 case FacetType.MaxExclusive:
784 facetCompiler.CompileMaxExclusiveFacet(facet);
787 case FacetType.TotalDigits:
788 facetCompiler.CompileTotalDigitsFacet(facet);
791 case FacetType.FractionDigits:
792 facetCompiler.CompileFractionDigitsFacet(facet);
796 throw new XmlSchemaException(Res.Sch_UnknownFacet, facet);
799 facetCompiler.FinishFacetCompile();
800 facetCompiler.CompileFacetCombinations();
801 return derivedRestriction;
808 internal static decimal Power(int x, int y) {
809 //Returns X raised to the power Y
810 decimal returnValue = 1m;
811 decimal decimalValue = (decimal)x;
812 if ( y > 28 ) { //CLR decimal cannot handle more than 29 digits (10 power 28.)
813 return decimal.MaxValue;
815 for (int i = 0; i < y; i++) {
816 returnValue = returnValue * decimalValue;
823 internal class Numeric10FacetsChecker : FacetsChecker {
824 static readonly char[] signs = new char[] {'+', '-'};
828 internal Numeric10FacetsChecker(decimal minVal, decimal maxVal) {
833 internal override Exception CheckValueFacets(object value, XmlSchemaDatatype datatype) {
835 decimal decimalValue = datatype.ValueConverter.ToDecimal(value);
836 return CheckValueFacets(decimalValue, datatype);
839 internal override Exception CheckValueFacets(decimal value, XmlSchemaDatatype datatype) {
840 RestrictionFacets restriction = datatype.Restriction;
841 RestrictionFlags flags = restriction != null ? restriction.Flags : 0;
842 XmlValueConverter valueConverter = datatype.ValueConverter;
844 //Check built-in facets
845 if (value > maxValue || value < minValue) {
846 return new OverflowException(Res.GetString(Res.XmlConvert_Overflow, value.ToString(CultureInfo.InvariantCulture), datatype.TypeCodeString));
848 //Check user-defined facets
850 if ((flags & RestrictionFlags.MaxInclusive) != 0) {
851 if (value > valueConverter.ToDecimal(restriction.MaxInclusive)) {
852 return new XmlSchemaException(Res.Sch_MaxInclusiveConstraintFailed, string.Empty);
856 if ((flags & RestrictionFlags.MaxExclusive) != 0) {
857 if (value >= valueConverter.ToDecimal(restriction.MaxExclusive)) {
858 return new XmlSchemaException(Res.Sch_MaxExclusiveConstraintFailed, string.Empty);
862 if ((flags & RestrictionFlags.MinInclusive) != 0) {
863 if (value < valueConverter.ToDecimal(restriction.MinInclusive)) {
864 return new XmlSchemaException(Res.Sch_MinInclusiveConstraintFailed, string.Empty);
868 if ((flags & RestrictionFlags.MinExclusive) != 0) {
869 if (value <= valueConverter.ToDecimal(restriction.MinExclusive)) {
870 return new XmlSchemaException(Res.Sch_MinExclusiveConstraintFailed, string.Empty);
873 if ((flags & RestrictionFlags.Enumeration) != 0) {
874 if (!MatchEnumeration(value, restriction.Enumeration, valueConverter)) {
875 return new XmlSchemaException(Res.Sch_EnumerationConstraintFailed, string.Empty);
878 return CheckTotalAndFractionDigits(value, restriction.TotalDigits, restriction.FractionDigits, ((flags & RestrictionFlags.TotalDigits) != 0), ((flags & RestrictionFlags.FractionDigits) != 0));
883 internal override Exception CheckValueFacets(Int64 value, XmlSchemaDatatype datatype) {
884 decimal decimalValue = (decimal)value;
885 return CheckValueFacets(decimalValue, datatype);
888 internal override Exception CheckValueFacets(Int32 value, XmlSchemaDatatype datatype) {
889 decimal decimalValue = (decimal)value;
890 return CheckValueFacets(decimalValue, datatype);
892 internal override Exception CheckValueFacets(Int16 value, XmlSchemaDatatype datatype) {
893 decimal decimalValue = (decimal)value;
894 return CheckValueFacets(decimalValue, datatype);
896 internal override Exception CheckValueFacets(byte value, XmlSchemaDatatype datatype) {
897 decimal decimalValue = (decimal)value;
898 return CheckValueFacets(decimalValue, datatype);
900 internal override bool MatchEnumeration(object value, ArrayList enumeration, XmlSchemaDatatype datatype) {
901 return MatchEnumeration(datatype.ValueConverter.ToDecimal(value), enumeration, datatype.ValueConverter);
904 internal bool MatchEnumeration(decimal value, ArrayList enumeration, XmlValueConverter valueConverter) {
905 for (int i = 0; i < enumeration.Count; ++i) {
906 if (value == valueConverter.ToDecimal(enumeration[i])) {
912 internal Exception CheckTotalAndFractionDigits(decimal value, int totalDigits, int fractionDigits, bool checkTotal, bool checkFraction) {
913 decimal maxValue = FacetsChecker.Power(10, totalDigits) - 1; //(decimal)Math.Pow(10, totalDigits) - 1 ;
916 value = Decimal.Negate(value); //Need to compare maxValue allowed against the absolute value
918 while (Decimal.Truncate(value) != value) { //Till it has a fraction
923 if (checkTotal && (value > maxValue || powerCnt > totalDigits)) {
924 return new XmlSchemaException(Res.Sch_TotalDigitsConstraintFailed, string.Empty);
926 if (checkFraction && powerCnt > fractionDigits) {
927 return new XmlSchemaException(Res.Sch_FractionDigitsConstraintFailed, string.Empty);
934 internal class Numeric2FacetsChecker : FacetsChecker {
936 internal override Exception CheckValueFacets(object value, XmlSchemaDatatype datatype) {
937 double doubleValue = datatype.ValueConverter.ToDouble(value);
938 return CheckValueFacets(doubleValue, datatype);
941 internal override Exception CheckValueFacets(double value, XmlSchemaDatatype datatype) {
942 RestrictionFacets restriction = datatype.Restriction;
943 RestrictionFlags flags = restriction != null ? restriction.Flags : 0;
944 XmlValueConverter valueConverter = datatype.ValueConverter;
946 if ((flags & RestrictionFlags.MaxInclusive) != 0) {
947 if (value > valueConverter.ToDouble(restriction.MaxInclusive)) {
948 return new XmlSchemaException(Res.Sch_MaxInclusiveConstraintFailed, string.Empty);
951 if ((flags & RestrictionFlags.MaxExclusive) != 0) {
952 if (value >= valueConverter.ToDouble(restriction.MaxExclusive)) {
953 return new XmlSchemaException(Res.Sch_MaxExclusiveConstraintFailed, string.Empty);
957 if ((flags & RestrictionFlags.MinInclusive) != 0) {
958 if (value < (valueConverter.ToDouble(restriction.MinInclusive))) {
959 return new XmlSchemaException(Res.Sch_MinInclusiveConstraintFailed, string.Empty);
963 if ((flags & RestrictionFlags.MinExclusive) != 0) {
964 if (value <= valueConverter.ToDouble(restriction.MinExclusive)) {
965 return new XmlSchemaException(Res.Sch_MinExclusiveConstraintFailed, string.Empty);
968 if ((flags & RestrictionFlags.Enumeration) != 0) {
969 if (!MatchEnumeration(value, restriction.Enumeration, valueConverter)) {
970 return new XmlSchemaException(Res.Sch_EnumerationConstraintFailed, string.Empty);
976 internal override Exception CheckValueFacets(float value, XmlSchemaDatatype datatype) {
977 double doubleValue = (double)value;
978 return CheckValueFacets(doubleValue, datatype);
980 internal override bool MatchEnumeration(object value, ArrayList enumeration, XmlSchemaDatatype datatype) {
981 return MatchEnumeration(datatype.ValueConverter.ToDouble(value), enumeration, datatype.ValueConverter);
983 private bool MatchEnumeration(double value, ArrayList enumeration, XmlValueConverter valueConverter) {
984 for (int i = 0; i < enumeration.Count; ++i) {
985 if (value == valueConverter.ToDouble(enumeration[i])) {
993 internal class DurationFacetsChecker: FacetsChecker {
995 internal override Exception CheckValueFacets(object value, XmlSchemaDatatype datatype) {
996 TimeSpan timeSpanValue = (TimeSpan)datatype.ValueConverter.ChangeType(value, typeof(TimeSpan));
997 return CheckValueFacets(timeSpanValue, datatype);
1000 internal override Exception CheckValueFacets(TimeSpan value, XmlSchemaDatatype datatype) {
1001 RestrictionFacets restriction = datatype.Restriction;
1002 RestrictionFlags flags = restriction != null ? restriction.Flags : 0;
1004 if ((flags & RestrictionFlags.MaxInclusive) != 0) {
1005 if (TimeSpan.Compare(value, (TimeSpan)restriction.MaxInclusive) > 0) {
1006 return new XmlSchemaException(Res.Sch_MaxInclusiveConstraintFailed, string.Empty);
1010 if ((flags & RestrictionFlags.MaxExclusive) != 0) {
1011 if (TimeSpan.Compare(value, (TimeSpan)restriction.MaxExclusive) >= 0) {
1012 return new XmlSchemaException(Res.Sch_MaxExclusiveConstraintFailed, string.Empty);
1016 if ((flags & RestrictionFlags.MinInclusive) != 0) {
1017 if (TimeSpan.Compare(value, (TimeSpan)restriction.MinInclusive) < 0) {
1018 return new XmlSchemaException(Res.Sch_MinInclusiveConstraintFailed, string.Empty);
1022 if ((flags & RestrictionFlags.MinExclusive) != 0) {
1023 if (TimeSpan.Compare(value, (TimeSpan)restriction.MinExclusive) <= 0) {
1024 return new XmlSchemaException(Res.Sch_MinExclusiveConstraintFailed, string.Empty);
1027 if ((flags & RestrictionFlags.Enumeration) != 0) {
1028 if (!MatchEnumeration(value, restriction.Enumeration)) {
1029 return new XmlSchemaException(Res.Sch_EnumerationConstraintFailed, string.Empty);
1034 internal override bool MatchEnumeration(object value, ArrayList enumeration, XmlSchemaDatatype datatype) {
1035 return MatchEnumeration((TimeSpan)value, enumeration);
1038 private bool MatchEnumeration(TimeSpan value, ArrayList enumeration) {
1039 for (int i = 0; i < enumeration.Count; ++i) {
1040 if (TimeSpan.Compare(value, (TimeSpan)enumeration[i]) == 0) {
1048 internal class DateTimeFacetsChecker: FacetsChecker {
1050 internal override Exception CheckValueFacets(object value, XmlSchemaDatatype datatype) {
1051 DateTime dateTimeValue = datatype.ValueConverter.ToDateTime(value);
1052 return CheckValueFacets(dateTimeValue, datatype);
1055 internal override Exception CheckValueFacets(DateTime value, XmlSchemaDatatype datatype) {
1056 RestrictionFacets restriction = datatype.Restriction;
1057 RestrictionFlags flags = restriction != null ? restriction.Flags : 0;
1059 if ((flags & RestrictionFlags.MaxInclusive) != 0) {
1060 if (datatype.Compare(value, (DateTime)restriction.MaxInclusive) > 0) {
1061 return new XmlSchemaException(Res.Sch_MaxInclusiveConstraintFailed, string.Empty);
1065 if ((flags & RestrictionFlags.MaxExclusive) != 0) {
1066 if (datatype.Compare(value, (DateTime)restriction.MaxExclusive) >= 0) {
1067 return new XmlSchemaException(Res.Sch_MaxExclusiveConstraintFailed, string.Empty);
1071 if ((flags & RestrictionFlags.MinInclusive) != 0) {
1072 if (datatype.Compare(value, (DateTime)restriction.MinInclusive) < 0) {
1073 return new XmlSchemaException(Res.Sch_MinInclusiveConstraintFailed, string.Empty);
1077 if ((flags & RestrictionFlags.MinExclusive) != 0) {
1078 if (datatype.Compare(value, (DateTime)restriction.MinExclusive) <= 0) {
1079 return new XmlSchemaException(Res.Sch_MinExclusiveConstraintFailed, string.Empty);
1082 if ((flags & RestrictionFlags.Enumeration) != 0) {
1083 if (!MatchEnumeration(value, restriction.Enumeration, datatype)) {
1084 return new XmlSchemaException(Res.Sch_EnumerationConstraintFailed, string.Empty);
1090 internal override bool MatchEnumeration(object value, ArrayList enumeration, XmlSchemaDatatype datatype) {
1091 return MatchEnumeration(datatype.ValueConverter.ToDateTime(value), enumeration, datatype);
1094 private bool MatchEnumeration(DateTime value, ArrayList enumeration, XmlSchemaDatatype datatype) {
1095 for (int i = 0; i < enumeration.Count; ++i) {
1096 if (datatype.Compare(value, (DateTime)enumeration[i]) == 0) {
1104 internal class StringFacetsChecker : FacetsChecker { //All types derived from string & anyURI
1105 static Regex languagePattern;
1107 static Regex LanguagePattern {
1109 if (languagePattern == null) {
1110 Regex langRegex = new Regex("^([a-zA-Z]{1,8})(-[a-zA-Z0-9]{1,8})*$", RegexOptions.None);
1111 Interlocked.CompareExchange(ref languagePattern, langRegex, null);
1113 return languagePattern;
1117 internal override Exception CheckValueFacets(object value, XmlSchemaDatatype datatype) {
1118 string stringValue = datatype.ValueConverter.ToString(value);
1119 return CheckValueFacets(stringValue, datatype, true);
1122 internal override Exception CheckValueFacets(string value, XmlSchemaDatatype datatype) {
1123 return CheckValueFacets(value, datatype, true);
1126 internal Exception CheckValueFacets(string value, XmlSchemaDatatype datatype, bool verifyUri) {
1127 //Length, MinLength, MaxLength
1128 int length = value.Length;
1129 RestrictionFacets restriction = datatype.Restriction;
1130 RestrictionFlags flags = restriction != null ? restriction.Flags : 0;
1131 Exception exception;
1133 exception = CheckBuiltInFacets(value, datatype.TypeCode, verifyUri);
1134 if (exception != null) return exception;
1137 if ((flags & RestrictionFlags.Length) != 0) {
1138 if (restriction.Length != length) {
1139 return new XmlSchemaException(Res.Sch_LengthConstraintFailed, string.Empty);
1142 if ((flags & RestrictionFlags.MinLength) != 0) {
1143 if (length < restriction.MinLength) {
1144 return new XmlSchemaException(Res.Sch_MinLengthConstraintFailed, string.Empty);
1147 if ((flags & RestrictionFlags.MaxLength) != 0) {
1148 if (restriction.MaxLength < length) {
1149 return new XmlSchemaException(Res.Sch_MaxLengthConstraintFailed, string.Empty);
1152 if ((flags & RestrictionFlags.Enumeration) != 0) {
1153 if (!MatchEnumeration(value, restriction.Enumeration, datatype)) {
1154 return new XmlSchemaException(Res.Sch_EnumerationConstraintFailed, string.Empty);
1161 internal override bool MatchEnumeration(object value, ArrayList enumeration, XmlSchemaDatatype datatype) {
1162 return MatchEnumeration(datatype.ValueConverter.ToString(value), enumeration, datatype);
1165 private bool MatchEnumeration(string value, ArrayList enumeration, XmlSchemaDatatype datatype) {
1166 if (datatype.TypeCode == XmlTypeCode.AnyUri) {
1167 for (int i = 0; i < enumeration.Count; ++i) {
1168 if (value.Equals(((Uri)enumeration[i]).OriginalString)) {
1174 for (int i = 0; i < enumeration.Count; ++i) {
1175 if (value.Equals((string)enumeration[i])) {
1183 private Exception CheckBuiltInFacets(string s, XmlTypeCode typeCode, bool verifyUri) {
1184 Exception exception = null;
1188 case XmlTypeCode.AnyUri:
1191 exception = XmlConvert.TryToUri(s, out uri);
1195 case XmlTypeCode.NormalizedString:
1196 exception = XmlConvert.TryVerifyNormalizedString(s);
1199 case XmlTypeCode.Token:
1200 exception = XmlConvert.TryVerifyTOKEN(s);
1203 case XmlTypeCode.Language:
1204 if (s == null || s.Length == 0) {
1205 return new XmlSchemaException(Res.Sch_EmptyAttributeValue, string.Empty);
1207 if (!LanguagePattern.IsMatch(s)) {
1208 return new XmlSchemaException(Res.Sch_InvalidLanguageId, string.Empty);
1212 case XmlTypeCode.NmToken:
1213 exception = XmlConvert.TryVerifyNMTOKEN(s);
1216 case XmlTypeCode.Name:
1217 exception = XmlConvert.TryVerifyName(s);
1220 case XmlTypeCode.NCName:
1221 case XmlTypeCode.Id:
1222 case XmlTypeCode.Idref:
1223 case XmlTypeCode.Entity:
1224 exception = XmlConvert.TryVerifyNCName(s);
1233 internal class QNameFacetsChecker : FacetsChecker {
1235 internal override Exception CheckValueFacets(object value, XmlSchemaDatatype datatype) {
1236 XmlQualifiedName qualifiedNameValue = (XmlQualifiedName)datatype.ValueConverter.ChangeType(value, typeof(XmlQualifiedName));
1237 return CheckValueFacets(qualifiedNameValue, datatype);
1240 internal override Exception CheckValueFacets(XmlQualifiedName value, XmlSchemaDatatype datatype) {
1241 RestrictionFacets restriction = datatype.Restriction;
1242 RestrictionFlags flags = restriction != null ? restriction.Flags : 0;
1243 if (flags != 0) { //If there are facets defined
1244 string strValue = value.ToString();
1245 int length = strValue.Length;
1246 if ((flags & RestrictionFlags.Length) != 0) {
1247 if (restriction.Length != length) {
1248 return new XmlSchemaException(Res.Sch_LengthConstraintFailed, string.Empty);
1251 if ((flags & RestrictionFlags.MinLength) != 0) {
1252 if (length < restriction.MinLength) {
1253 return new XmlSchemaException(Res.Sch_MinLengthConstraintFailed, string.Empty);
1256 if ((flags & RestrictionFlags.MaxLength) != 0) {
1257 if (restriction.MaxLength < length) {
1258 return new XmlSchemaException(Res.Sch_MaxLengthConstraintFailed, string.Empty);
1261 if ((flags & RestrictionFlags.Enumeration) != 0) {
1262 if (!MatchEnumeration(value, restriction.Enumeration)) {
1263 return new XmlSchemaException(Res.Sch_EnumerationConstraintFailed, string.Empty);
1269 internal override bool MatchEnumeration(object value, ArrayList enumeration, XmlSchemaDatatype datatype) {
1270 return MatchEnumeration((XmlQualifiedName)datatype.ValueConverter.ChangeType(value, typeof(XmlQualifiedName)), enumeration);
1273 private bool MatchEnumeration(XmlQualifiedName value, ArrayList enumeration) {
1274 for (int i = 0; i < enumeration.Count; ++i) {
1275 if (value.Equals((XmlQualifiedName)enumeration[i])) {
1283 internal class MiscFacetsChecker : FacetsChecker { //For bool, anySimpleType
1286 internal class BinaryFacetsChecker : FacetsChecker { //hexBinary & Base64Binary
1288 internal override Exception CheckValueFacets(object value, XmlSchemaDatatype datatype) {
1289 byte[] byteArrayValue = (byte[])value;
1290 return CheckValueFacets(byteArrayValue, datatype);
1293 internal override Exception CheckValueFacets(byte[] value, XmlSchemaDatatype datatype) {
1294 //Length, MinLength, MaxLength
1295 RestrictionFacets restriction = datatype.Restriction;
1296 int length = value.Length;
1297 RestrictionFlags flags = restriction != null ? restriction.Flags : 0;
1298 if (flags != 0) { //if it has facets defined
1299 if ((flags & RestrictionFlags.Length) != 0) {
1300 if (restriction.Length != length) {
1301 return new XmlSchemaException(Res.Sch_LengthConstraintFailed, string.Empty);
1304 if ((flags & RestrictionFlags.MinLength) != 0) {
1305 if (length < restriction.MinLength) {
1306 return new XmlSchemaException(Res.Sch_MinLengthConstraintFailed, string.Empty);
1309 if ((flags & RestrictionFlags.MaxLength) != 0) {
1310 if (restriction.MaxLength < length) {
1311 return new XmlSchemaException(Res.Sch_MaxLengthConstraintFailed, string.Empty);
1314 if ((flags & RestrictionFlags.Enumeration) != 0) {
1315 if (!MatchEnumeration(value, restriction.Enumeration, datatype)) {
1316 return new XmlSchemaException(Res.Sch_EnumerationConstraintFailed, string.Empty);
1322 internal override bool MatchEnumeration(object value, ArrayList enumeration, XmlSchemaDatatype datatype) {
1323 return MatchEnumeration((byte[])value, enumeration, datatype);
1326 private bool MatchEnumeration(byte[] value, ArrayList enumeration, XmlSchemaDatatype datatype) {
1327 for (int i = 0; i < enumeration.Count; ++i) {
1328 if (datatype.Compare(value, (byte[])enumeration[i]) == 0) {
1336 internal class ListFacetsChecker : FacetsChecker {
1338 internal override Exception CheckValueFacets(object value, XmlSchemaDatatype datatype) {
1339 //Check for facets allowed on lists - Length, MinLength, MaxLength
1340 Array values = value as Array;
1341 Debug.Assert(values != null);
1343 RestrictionFacets restriction = datatype.Restriction;
1344 RestrictionFlags flags = restriction != null ? restriction.Flags : 0;
1346 if ((flags & (RestrictionFlags.Length|RestrictionFlags.MinLength|RestrictionFlags.MaxLength)) != 0) {
1347 int length = values.Length;
1348 if ((flags & RestrictionFlags.Length) != 0) {
1349 if (restriction.Length != length) {
1350 return new XmlSchemaException(Res.Sch_LengthConstraintFailed, string.Empty);
1354 if ((flags & RestrictionFlags.MinLength) != 0) {
1355 if (length < restriction.MinLength) {
1356 return new XmlSchemaException(Res.Sch_MinLengthConstraintFailed, string.Empty);
1360 if ((flags & RestrictionFlags.MaxLength) != 0) {
1361 if (restriction.MaxLength < length) {
1362 return new XmlSchemaException(Res.Sch_MaxLengthConstraintFailed, string.Empty);
1366 if ((flags & RestrictionFlags.Enumeration) != 0) {
1367 if (!MatchEnumeration(value, restriction.Enumeration, datatype)) {
1368 return new XmlSchemaException(Res.Sch_EnumerationConstraintFailed, string.Empty);
1374 internal override bool MatchEnumeration(object value, ArrayList enumeration, XmlSchemaDatatype datatype) {
1375 for (int i = 0; i < enumeration.Count; ++i) {
1376 if (datatype.Compare(value, enumeration[i]) == 0) {
1384 internal class UnionFacetsChecker : FacetsChecker {
1386 internal override Exception CheckValueFacets(object value, XmlSchemaDatatype datatype) {
1387 RestrictionFacets restriction = datatype.Restriction;
1388 RestrictionFlags flags = restriction != null ? restriction.Flags : 0;
1390 if ((flags & RestrictionFlags.Enumeration) != 0) {
1391 if (!MatchEnumeration(value, restriction.Enumeration, datatype)) {
1392 return new XmlSchemaException(Res.Sch_EnumerationConstraintFailed, string.Empty);
1398 internal override bool MatchEnumeration(object value, ArrayList enumeration, XmlSchemaDatatype datatype) {
1399 for (int i = 0; i < enumeration.Count; ++i) {
1400 if (datatype.Compare(value, enumeration[i]) == 0) { //Compare on Datatype_union will compare two XsdSimpleValue