Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Xml / System / Xml / Schema / XmlSchemaComplexType.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="XmlSchemaComplexType.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>  
5 // <owner current="true" primary="true">[....]</owner>                                                              
6 //------------------------------------------------------------------------------
7
8 namespace System.Xml.Schema {
9
10     using System.Collections;
11     using System.ComponentModel;
12     using System.Xml.Serialization;
13
14     /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType"]/*' />
15     /// <devdoc>
16     ///    <para>[To be supplied.]</para>
17     /// </devdoc>
18     public class XmlSchemaComplexType : XmlSchemaType {
19         XmlSchemaDerivationMethod block = XmlSchemaDerivationMethod.None;
20
21         XmlSchemaContentModel contentModel;
22         XmlSchemaParticle particle;
23         XmlSchemaObjectCollection attributes;
24         XmlSchemaAnyAttribute anyAttribute;
25
26         XmlSchemaParticle contentTypeParticle = XmlSchemaParticle.Empty;
27         XmlSchemaDerivationMethod blockResolved;
28         XmlSchemaObjectTable localElements;
29         XmlSchemaObjectTable attributeUses;
30         XmlSchemaAnyAttribute attributeWildcard;
31
32         static XmlSchemaComplexType anyTypeLax;
33         static XmlSchemaComplexType anyTypeSkip;
34         static XmlSchemaComplexType untypedAnyType;
35
36         //additional info for Partial validation
37         byte pvFlags;
38         const byte wildCardMask = 0x01;
39         const byte isMixedMask = 0x02;
40         const byte isAbstractMask = 0x04;
41         //const byte dupDeclMask = 0x08;
42
43         static XmlSchemaComplexType() {
44             anyTypeLax = CreateAnyType(XmlSchemaContentProcessing.Lax);
45             anyTypeSkip = CreateAnyType(XmlSchemaContentProcessing.Skip);
46
47             // Create xdt:untypedAny
48             untypedAnyType = new XmlSchemaComplexType();
49             untypedAnyType.SetQualifiedName(new XmlQualifiedName("untypedAny", XmlReservedNs.NsXQueryDataType));
50             untypedAnyType.IsMixed = true;
51             untypedAnyType.SetContentTypeParticle(anyTypeLax.ContentTypeParticle);
52             untypedAnyType.SetContentType(XmlSchemaContentType.Mixed);
53
54             untypedAnyType.ElementDecl = SchemaElementDecl.CreateAnyTypeElementDecl();
55             untypedAnyType.ElementDecl.SchemaType = untypedAnyType;
56             untypedAnyType.ElementDecl.ContentValidator = AnyTypeContentValidator;
57
58         }
59
60         static XmlSchemaComplexType CreateAnyType(XmlSchemaContentProcessing processContents) {
61             XmlSchemaComplexType localAnyType = new XmlSchemaComplexType();
62             localAnyType.SetQualifiedName(DatatypeImplementation.QnAnyType);
63
64             XmlSchemaAny anyElement = new XmlSchemaAny();
65             anyElement.MinOccurs = decimal.Zero;
66             anyElement.MaxOccurs = decimal.MaxValue;
67
68             anyElement.ProcessContents = processContents;
69             anyElement.BuildNamespaceList(null);
70             XmlSchemaSequence seq = new XmlSchemaSequence();
71             seq.Items.Add(anyElement);
72
73             localAnyType.SetContentTypeParticle(seq);
74             localAnyType.SetContentType(XmlSchemaContentType.Mixed);
75
76             localAnyType.ElementDecl = SchemaElementDecl.CreateAnyTypeElementDecl();
77             localAnyType.ElementDecl.SchemaType = localAnyType;
78
79             //Create contentValidator for Any
80             ParticleContentValidator contentValidator = new ParticleContentValidator(XmlSchemaContentType.Mixed);
81             contentValidator.Start();
82             contentValidator.OpenGroup();
83             contentValidator.AddNamespaceList(anyElement.NamespaceList, anyElement);
84             contentValidator.AddStar();
85             contentValidator.CloseGroup();
86             ContentValidator anyContentValidator = contentValidator.Finish(true);
87             localAnyType.ElementDecl.ContentValidator = anyContentValidator;
88
89             XmlSchemaAnyAttribute anyAttribute = new XmlSchemaAnyAttribute();
90             anyAttribute.ProcessContents = processContents;
91             anyAttribute.BuildNamespaceList(null);
92             localAnyType.SetAttributeWildcard(anyAttribute);
93             localAnyType.ElementDecl.AnyAttribute = anyAttribute;
94             return localAnyType;
95         }
96
97         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.XmlSchemaComplexType"]/*' />
98         /// <devdoc>
99         ///    <para>[To be supplied.]</para>
100         /// </devdoc>
101         public XmlSchemaComplexType() {
102         }
103
104
105         [XmlIgnore]
106         internal static XmlSchemaComplexType AnyType {
107              get { return anyTypeLax; }
108         }
109
110         [XmlIgnore]
111         internal static XmlSchemaComplexType UntypedAnyType {
112              get { return untypedAnyType; }
113         }
114         
115         [XmlIgnore]
116         internal static XmlSchemaComplexType AnyTypeSkip {
117              get { return anyTypeSkip; }
118         }
119
120         internal static ContentValidator AnyTypeContentValidator {
121             get {
122                 return anyTypeLax.ElementDecl.ContentValidator;
123             }
124         }
125         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.IsAbstract"]/*' />
126         /// <devdoc>
127         ///    <para>[To be supplied.]</para>
128         /// </devdoc>
129         [XmlAttribute("abstract"), DefaultValue(false)]
130         public bool IsAbstract {
131             get {
132                 return (pvFlags & isAbstractMask) != 0;
133             }
134             set {
135                 if (value) {
136                     pvFlags = (byte)(pvFlags | isAbstractMask);
137                 }
138                 else {
139                     pvFlags = (byte)(pvFlags & ~isAbstractMask);
140                 }
141             }
142         }
143
144         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.Block"]/*' />
145         /// <devdoc>
146         ///    <para>[To be supplied.]</para>
147         /// </devdoc>
148         [XmlAttribute("block"), DefaultValue(XmlSchemaDerivationMethod.None)]
149         public XmlSchemaDerivationMethod Block {
150             get { return block; }
151             set { block = value; }
152         }
153
154         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.IsMixed"]/*' />
155         /// <devdoc>
156         ///    <para>[To be supplied.]</para>
157         /// </devdoc>
158         [XmlAttribute("mixed"), DefaultValue(false)]
159         public override bool IsMixed {
160             get {
161                 return (pvFlags & isMixedMask) != 0;
162             }
163             set {
164                 if (value) {
165                     pvFlags = (byte)(pvFlags | isMixedMask);
166                 }
167                 else {
168                     pvFlags = (byte)(pvFlags & ~isMixedMask);
169                 }
170             }
171         }
172
173
174         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.ContentModel"]/*' />
175         /// <devdoc>
176         ///    <para>[To be supplied.]</para>
177         /// </devdoc>
178         [XmlElement("simpleContent", typeof(XmlSchemaSimpleContent)),
179          XmlElement("complexContent", typeof(XmlSchemaComplexContent))]
180         public XmlSchemaContentModel ContentModel {
181             get { return contentModel; }
182             set { contentModel = value; }
183         }
184
185         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.Particle"]/*' />
186         /// <devdoc>
187         ///    <para>[To be supplied.]</para>
188         /// </devdoc>
189         [XmlElement("group", typeof(XmlSchemaGroupRef)),
190          XmlElement("choice", typeof(XmlSchemaChoice)),
191          XmlElement("all", typeof(XmlSchemaAll)),
192          XmlElement("sequence", typeof(XmlSchemaSequence))]
193         public XmlSchemaParticle Particle {
194             get { return particle; }
195             set { particle = value; }
196         }
197
198         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.Attributes"]/*' />
199         /// <devdoc>
200         ///    <para>[To be supplied.]</para>
201         /// </devdoc>
202         [XmlElement("attribute", typeof(XmlSchemaAttribute)),
203          XmlElement("attributeGroup", typeof(XmlSchemaAttributeGroupRef))]
204         public XmlSchemaObjectCollection Attributes {
205             get {
206                 if (attributes == null) {
207                     attributes = new XmlSchemaObjectCollection();
208                 }
209                 return attributes;
210             }
211         }
212
213         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.AnyAttribute"]/*' />
214         /// <devdoc>
215         ///    <para>[To be supplied.]</para>
216         /// </devdoc>
217         [XmlElement("anyAttribute")]
218         public XmlSchemaAnyAttribute AnyAttribute {
219             get { return anyAttribute; }
220             set { anyAttribute = value; }
221         }
222
223
224         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.ContentType"]/*' />
225         /// <devdoc>
226         ///    <para>[To be supplied.]</para>
227         /// </devdoc>
228         [XmlIgnore]
229         public XmlSchemaContentType ContentType {
230             get { return SchemaContentType; }
231         }
232
233         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.ContentTypeParticle"]/*' />
234         /// <devdoc>
235         ///    <para>[To be supplied.]</para>
236         /// </devdoc>
237         [XmlIgnore]
238         public XmlSchemaParticle ContentTypeParticle {
239             get { return contentTypeParticle; }
240         }
241
242         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.BlockResolved"]/*' />
243         /// <devdoc>
244         ///    <para>[To be supplied.]</para>
245         /// </devdoc>
246         [XmlIgnore]
247         public XmlSchemaDerivationMethod BlockResolved {
248              get { return blockResolved; }
249         }
250
251         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.AttributeUses"]/*' />
252         /// <devdoc>
253         ///    <para>[To be supplied.]</para>
254         /// </devdoc>
255         [XmlIgnore]
256         public XmlSchemaObjectTable AttributeUses {
257             get {
258                 if (attributeUses == null) {
259                     attributeUses = new XmlSchemaObjectTable();
260                 }
261                 return attributeUses;
262             }
263         }
264
265         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.AttributeWildcard"]/*' />
266         /// <devdoc>
267         ///    <para>[To be supplied.]</para>
268         /// </devdoc>
269         [XmlIgnore]
270         public XmlSchemaAnyAttribute AttributeWildcard {
271             get { return attributeWildcard; }
272         }
273
274         /// <include file='doc\XmlSchemaComplexType.uex' path='docs/doc[@for="XmlSchemaComplexType.LocalElements"]/*' />
275         /// <devdoc>
276         ///    <para>[To be supplied.]</para>
277         /// </devdoc>
278         [XmlIgnore]
279         internal XmlSchemaObjectTable LocalElements {
280             get {
281                 if (localElements == null) {
282                     localElements = new XmlSchemaObjectTable();
283                 }
284                 return localElements;
285             }
286         }
287
288         internal void SetContentTypeParticle(XmlSchemaParticle value) { 
289             contentTypeParticle = value; 
290         }
291
292         internal void SetBlockResolved(XmlSchemaDerivationMethod value) {
293              blockResolved = value; 
294         }
295
296         internal void SetAttributeWildcard(XmlSchemaAnyAttribute value) {
297              attributeWildcard = value; 
298         }
299
300         internal bool HasWildCard {
301             get {
302                 return (pvFlags & wildCardMask) != 0;
303             }
304             set {
305                 if (value) {
306                     pvFlags = (byte)(pvFlags | wildCardMask);
307                 }
308                 else {
309                     pvFlags = (byte)(pvFlags & ~wildCardMask);
310                 }
311             }
312         }
313
314         internal override XmlQualifiedName DerivedFrom {
315             get {
316                 if (contentModel == null) {
317                     // type derived from anyType
318                     return XmlQualifiedName.Empty;
319                 }
320                 if (contentModel.Content is XmlSchemaComplexContentRestriction)
321                     return ((XmlSchemaComplexContentRestriction)contentModel.Content).BaseTypeName;
322                 else if (contentModel.Content is XmlSchemaComplexContentExtension)
323                     return ((XmlSchemaComplexContentExtension)contentModel.Content).BaseTypeName;
324                 else if (contentModel.Content is XmlSchemaSimpleContentRestriction)
325                     return ((XmlSchemaSimpleContentRestriction)contentModel.Content).BaseTypeName;
326                 else if (contentModel.Content is XmlSchemaSimpleContentExtension)
327                     return ((XmlSchemaSimpleContentExtension)contentModel.Content).BaseTypeName;
328                 else
329                     return XmlQualifiedName.Empty;
330             }
331         }
332         
333         internal void SetAttributes(XmlSchemaObjectCollection newAttributes) {
334             attributes = newAttributes;
335         }
336
337         internal bool ContainsIdAttribute(bool findAll) {
338             int idCount = 0;
339             foreach(XmlSchemaAttribute attribute in this.AttributeUses.Values) {
340                 if (attribute.Use != XmlSchemaUse.Prohibited) {
341                     XmlSchemaDatatype datatype = attribute.Datatype;
342                     if (datatype != null && datatype.TypeCode == XmlTypeCode.Id) {
343                         idCount++;
344                         if (idCount > 1) { //two or more attributes is error
345                             break;
346                         }
347                     }
348                 }
349             }
350             return findAll ? (idCount > 1) : (idCount > 0);
351         }
352
353         internal override XmlSchemaObject Clone() {
354             System.Diagnostics.Debug.Assert(false, "Should never call Clone() on XmlSchemaComplexType. Call Clone(XmlSchema) instead.");
355             return Clone(null);
356         }
357
358         internal XmlSchemaObject Clone(XmlSchema parentSchema) {
359             XmlSchemaComplexType complexType = (XmlSchemaComplexType)MemberwiseClone();
360             
361             //Deep clone the QNames as these will be updated on chameleon includes
362             if (complexType.ContentModel != null) { //simpleContent or complexContent
363
364                 XmlSchemaSimpleContent simpleContent = complexType.ContentModel as XmlSchemaSimpleContent; 
365                 if (simpleContent != null) {
366                     XmlSchemaSimpleContent newSimpleContent = (XmlSchemaSimpleContent)simpleContent.Clone();
367                     
368                     XmlSchemaSimpleContentExtension simpleExt =  simpleContent.Content as XmlSchemaSimpleContentExtension;   
369                     if (simpleExt != null) {
370                         XmlSchemaSimpleContentExtension newSimpleExt = (XmlSchemaSimpleContentExtension)simpleExt.Clone();
371                         newSimpleExt.BaseTypeName = simpleExt.BaseTypeName.Clone();
372                         newSimpleExt.SetAttributes(CloneAttributes(simpleExt.Attributes));
373                         newSimpleContent.Content = newSimpleExt;
374                     }
375                     else { //simpleContent.Content is XmlSchemaSimpleContentRestriction
376                         XmlSchemaSimpleContentRestriction simpleRest = (XmlSchemaSimpleContentRestriction)simpleContent.Content;
377                         XmlSchemaSimpleContentRestriction newSimpleRest = (XmlSchemaSimpleContentRestriction)simpleRest.Clone();
378                         newSimpleRest.BaseTypeName = simpleRest.BaseTypeName.Clone();
379                         newSimpleRest.SetAttributes(CloneAttributes(simpleRest.Attributes));
380                         newSimpleContent.Content = newSimpleRest;
381                     }
382                     
383                     complexType.ContentModel = newSimpleContent;
384                 }
385                 else { // complexType.ContentModel is XmlSchemaComplexContent
386                     XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)complexType.ContentModel;
387                     XmlSchemaComplexContent newComplexContent = (XmlSchemaComplexContent)complexContent.Clone();
388
389                     XmlSchemaComplexContentExtension complexExt = complexContent.Content as XmlSchemaComplexContentExtension;
390                     if (complexExt != null) {
391                         XmlSchemaComplexContentExtension newComplexExt = (XmlSchemaComplexContentExtension)complexExt.Clone();
392                         newComplexExt.BaseTypeName = complexExt.BaseTypeName.Clone();
393                         newComplexExt.SetAttributes(CloneAttributes(complexExt.Attributes));
394                         if (HasParticleRef(complexExt.Particle, parentSchema)) {
395                             newComplexExt.Particle = CloneParticle(complexExt.Particle, parentSchema);
396                         }
397                         newComplexContent.Content = newComplexExt;
398                     }
399                     else { // complexContent.Content is XmlSchemaComplexContentRestriction
400                         XmlSchemaComplexContentRestriction complexRest = complexContent.Content as XmlSchemaComplexContentRestriction;
401                         XmlSchemaComplexContentRestriction newComplexRest = (XmlSchemaComplexContentRestriction)complexRest.Clone();
402                         newComplexRest.BaseTypeName = complexRest.BaseTypeName.Clone();
403                         newComplexRest.SetAttributes(CloneAttributes(complexRest.Attributes));
404                         if (HasParticleRef(newComplexRest.Particle, parentSchema)) {
405                             newComplexRest.Particle = CloneParticle(newComplexRest.Particle, parentSchema);
406                         }
407                         newComplexContent.Content = newComplexRest;
408                     }
409                     complexType.ContentModel = newComplexContent;
410                 }
411             }
412             else { //equals XmlSchemaComplexContent with baseType is anyType
413                 if (HasParticleRef(complexType.Particle, parentSchema)) {
414                     complexType.Particle = CloneParticle(complexType.Particle, parentSchema);
415                 }
416                 complexType.SetAttributes(CloneAttributes(complexType.Attributes));
417             }
418             complexType.ClearCompiledState();
419             return complexType;
420         }
421
422         private void ClearCompiledState() {
423             //Re-set post-compiled state for cloned object
424             this.attributeUses = null;
425             this.localElements = null;
426             this.attributeWildcard = null;
427             this.contentTypeParticle = XmlSchemaParticle.Empty;
428             this.blockResolved = XmlSchemaDerivationMethod.None;
429         }
430
431         internal static XmlSchemaObjectCollection CloneAttributes(XmlSchemaObjectCollection attributes) {
432             if (HasAttributeQNameRef(attributes)) {
433                 XmlSchemaObjectCollection newAttributes = attributes.Clone();
434                 XmlSchemaAttributeGroupRef attributeGroupRef;
435                 XmlSchemaAttributeGroupRef newAttGroupRef;
436                 XmlSchemaObject xso;
437                 XmlSchemaAttribute att;
438
439                 for (int i = 0; i < attributes.Count; i++) {
440                     xso = attributes[i];
441                     attributeGroupRef = xso as XmlSchemaAttributeGroupRef;
442                     if (attributeGroupRef != null) {
443                         newAttGroupRef = (XmlSchemaAttributeGroupRef)attributeGroupRef.Clone();
444                         newAttGroupRef.RefName = attributeGroupRef.RefName.Clone();
445                         newAttributes[i] = newAttGroupRef;
446                     }
447                     else { //Its XmlSchemaAttribute
448                         att = xso as XmlSchemaAttribute;
449                         if (!att.RefName.IsEmpty || !att.SchemaTypeName.IsEmpty) {
450                             newAttributes[i] = att.Clone();     
451                         }
452                     }
453                 }
454                 return newAttributes;
455             }
456             return attributes;
457         }
458
459         private static XmlSchemaObjectCollection CloneGroupBaseParticles(XmlSchemaObjectCollection groupBaseParticles, XmlSchema parentSchema) {
460             XmlSchemaObjectCollection newParticles = groupBaseParticles.Clone();
461
462             for (int i = 0; i < groupBaseParticles.Count; i++) {
463                 XmlSchemaParticle p = (XmlSchemaParticle)groupBaseParticles[i];
464                 newParticles[i] = CloneParticle(p, parentSchema);
465             }
466             return newParticles; 
467         }
468
469         internal static XmlSchemaParticle CloneParticle(XmlSchemaParticle particle, XmlSchema parentSchema) {
470             XmlSchemaGroupBase groupBase = particle as XmlSchemaGroupBase;
471             if (groupBase != null) { //Choice or sequence
472                 XmlSchemaGroupBase newGroupBase = groupBase;
473
474                 XmlSchemaObjectCollection newGroupbaseParticles = CloneGroupBaseParticles(groupBase.Items, parentSchema);
475                 newGroupBase = (XmlSchemaGroupBase)groupBase.Clone();
476                 newGroupBase.SetItems(newGroupbaseParticles);
477                 return newGroupBase;
478             }
479             else if (particle is XmlSchemaGroupRef) { // group ref
480                 XmlSchemaGroupRef newGroupRef = (XmlSchemaGroupRef)particle.Clone();
481                 newGroupRef.RefName = newGroupRef.RefName.Clone();
482                 return newGroupRef;
483             }
484             else {
485                 XmlSchemaElement oldElem = particle as XmlSchemaElement;
486                 // If the particle is an element and one of the following is true:
487                 //   - it references another element by name
488                 //   - it references its type by name
489                 //   - it's form (effective) is qualified (meaning it will inherint namespace from chameleon includes if that happens)
490                 // then the element itself needs to be cloned.
491                 if (oldElem != null && (!oldElem.RefName.IsEmpty || !oldElem.SchemaTypeName.IsEmpty ||
492                     GetResolvedElementForm(parentSchema, oldElem) == XmlSchemaForm.Qualified)) {
493                     XmlSchemaElement newElem = (XmlSchemaElement)oldElem.Clone(parentSchema);
494                     return newElem;
495                 }
496             }
497             return particle;
498         }
499
500         // This method returns the effective value of the "element form" for the specified element in the specified
501         //   parentSchema. Element form is either qualified, unqualified or none. If it's qualified it means that
502         //   if the element doesn't declare its own namespace the targetNamespace of the schema is used instead.
503         // The element form can be either specified on the element itself via the "form" attribute or 
504         //   if that one is not present its inheritted from the value of the elementFormDefault attribute on the owning 
505         //   schema.
506         private static XmlSchemaForm GetResolvedElementForm(XmlSchema parentSchema, XmlSchemaElement element) {
507             if (element.Form == XmlSchemaForm.None && parentSchema != null) {
508                 return parentSchema.ElementFormDefault;
509             }
510             else {
511                 return element.Form;
512             }
513         }
514
515         internal static bool HasParticleRef(XmlSchemaParticle particle, XmlSchema parentSchema) {
516             XmlSchemaGroupBase groupBase = particle as XmlSchemaGroupBase;
517             if (groupBase != null) {
518                 bool foundRef = false;
519                 int i = 0;
520                 while (i < groupBase.Items.Count && !foundRef) {
521                     XmlSchemaParticle p = (XmlSchemaParticle)groupBase.Items[i++];
522                     if (p is XmlSchemaGroupRef) {
523                         foundRef = true;
524                     }
525                     else {
526                         XmlSchemaElement elem = p as XmlSchemaElement;
527                         // This is the same condition as in the CloneParticle method
528                         //   that's on purpose. This method is used to determine if we need to clone the whole particle.
529                         //   If we do, then the CloneParticle is called and it will try to clone only
530                         //   those elements which need cloning - and those are the ones matching this condition.
531                         if (elem != null && (!elem.RefName.IsEmpty || !elem.SchemaTypeName.IsEmpty ||
532                             GetResolvedElementForm(parentSchema, elem) == XmlSchemaForm.Qualified)) {
533                             foundRef = true;
534                         }
535                         else {
536                             foundRef = HasParticleRef(p, parentSchema);
537                         }
538                     }
539                 }
540                 return foundRef;
541             }
542             else if (particle is XmlSchemaGroupRef) {
543                 return true;
544             }
545             return false;
546         }
547
548         internal static bool HasAttributeQNameRef(XmlSchemaObjectCollection attributes) {
549             for (int i = 0; i < attributes.Count; ++i) {
550                 if (attributes[i] is XmlSchemaAttributeGroupRef) {
551                     return true;
552                 }
553                 else {
554                     XmlSchemaAttribute attribute = attributes[i] as XmlSchemaAttribute;
555                     if (!attribute.RefName.IsEmpty || !attribute.SchemaTypeName.IsEmpty) {
556                         return true;
557                     }
558                 }
559             }
560             return false;
561         }
562     }
563
564 }