1 //------------------------------------------------------------------------------
2 // <copyright file="XmlSchemaObjectTable.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 {
10 using System.Collections;
11 using System.Collections.Generic;
12 using System.Diagnostics;
14 /// <include file='doc\XmlSchemaObjectTable.uex' path='docs/doc[@for="XmlSchemaObjectTable"]/*' />
15 public class XmlSchemaObjectTable {
16 Dictionary<XmlQualifiedName, XmlSchemaObject> table = new Dictionary<XmlQualifiedName,XmlSchemaObject>();
17 List<XmlSchemaObjectEntry> entries = new List<XmlSchemaObjectEntry>();
19 internal XmlSchemaObjectTable() {
22 internal void Add(XmlQualifiedName name, XmlSchemaObject value) {
23 Debug.Assert(!table.ContainsKey(name), "XmlSchemaObjectTable.Add: entry already exists");
24 table.Add(name, value);
25 entries.Add(new XmlSchemaObjectEntry(name, value));
28 internal void Insert(XmlQualifiedName name, XmlSchemaObject value) {
29 XmlSchemaObject oldValue = null;
30 if (table.TryGetValue(name, out oldValue)) {
31 table[name] = value; //set new value
32 Debug.Assert(oldValue != null);
33 int matchedIndex = FindIndexByValue(oldValue);
34 Debug.Assert(matchedIndex >= 0);
36 Debug.Assert(entries[matchedIndex].qname == name);
37 entries[matchedIndex] = new XmlSchemaObjectEntry(name, value);
45 internal void Replace(XmlQualifiedName name, XmlSchemaObject value) {
46 XmlSchemaObject oldValue;
47 if (table.TryGetValue(name, out oldValue)) {
48 table[name] = value; //set new value
49 Debug.Assert(oldValue != null);
50 int matchedIndex = FindIndexByValue(oldValue);
51 Debug.Assert(entries[matchedIndex].qname == name);
52 entries[matchedIndex] = new XmlSchemaObjectEntry(name, value);
56 internal void Clear() {
61 internal void Remove(XmlQualifiedName name) {
62 XmlSchemaObject value;
63 if (table.TryGetValue(name, out value)) {
65 int matchedIndex = FindIndexByValue(value);
66 Debug.Assert(matchedIndex >= 0);
67 Debug.Assert(entries[matchedIndex].qname == name);
68 entries.RemoveAt(matchedIndex);
72 private int FindIndexByValue(XmlSchemaObject xso) {
74 for(index = 0; index < entries.Count; index++) {
75 if((object)entries[index].xso == (object)xso) {
81 /// <include file='doc\XmlSchemaObjectTable.uex' path='docs/doc[@for="XmlSchemaObjectTable.Count"]/*' />
84 Debug.Assert(table.Count == entries.Count);
89 /// <include file='doc\XmlSchemaObjectTable.uex' path='docs/doc[@for="XmlSchemaObjectTable.Contains"]/*' />
90 public bool Contains(XmlQualifiedName name) {
91 return table.ContainsKey(name);
94 /// <include file='doc\XmlSchemaObjectTable.uex' path='docs/doc[@for="XmlSchemaObjectTable.this"]/*' />
95 public XmlSchemaObject this[XmlQualifiedName name] {
97 XmlSchemaObject value;
98 if (table.TryGetValue(name, out value)) {
105 /// <include file='doc\XmlSchemaObjectTable.uex' path='docs/doc[@for="XmlSchemaObjectTable.Names"]/*' />
106 public ICollection Names {
108 return new NamesCollection(entries, table.Count);
112 /// <include file='doc\XmlSchemaObjectTable.uex' path='docs/doc[@for="XmlSchemaObjectTable.Values"]/*' />
113 public ICollection Values {
115 return new ValuesCollection(entries, table.Count);
119 /// <include file='doc\XmlSchemaObjectTable.uex' path='docs/doc[@for="XmlSchemaObjectTable.GetEnumerator"]/*' />
120 public IDictionaryEnumerator GetEnumerator() {
121 return new XSODictionaryEnumerator(this.entries, table.Count, EnumeratorType.DictionaryEntry);
124 internal enum EnumeratorType {
130 internal struct XmlSchemaObjectEntry {
131 internal XmlQualifiedName qname;
132 internal XmlSchemaObject xso;
134 public XmlSchemaObjectEntry(XmlQualifiedName name, XmlSchemaObject value) {
139 public XmlSchemaObject IsMatch(string localName, string ns) {
140 if (localName == qname.Name && ns == qname.Namespace) {
146 public void Reset() {
152 internal class NamesCollection : ICollection {
153 private List<XmlSchemaObjectEntry> entries;
156 internal NamesCollection(List<XmlSchemaObjectEntry> entries, int size) {
157 this.entries = entries;
165 public Object SyncRoot {
167 return ((ICollection)entries).SyncRoot;
171 public bool IsSynchronized {
173 return ((ICollection)entries).IsSynchronized;
177 public void CopyTo(Array array, int arrayIndex) {
179 throw new ArgumentNullException("array");
182 throw new ArgumentOutOfRangeException("arrayIndex");
184 Debug.Assert(array.Length >= size, "array is not big enough to hold all the items in the ICollection");
186 for (int i = 0; i < size; i++) {
187 array.SetValue(entries[i].qname, arrayIndex++);
191 public IEnumerator GetEnumerator() {
192 return new XSOEnumerator(this.entries, this.size, EnumeratorType.Keys);
196 //ICollection for Values
197 internal class ValuesCollection : ICollection {
198 private List<XmlSchemaObjectEntry> entries;
201 internal ValuesCollection(List<XmlSchemaObjectEntry> entries, int size) {
202 this.entries = entries;
210 public Object SyncRoot {
212 return ((ICollection)entries).SyncRoot;
216 public bool IsSynchronized {
218 return ((ICollection)entries).IsSynchronized;
222 public void CopyTo(Array array, int arrayIndex) {
224 throw new ArgumentNullException("array");
227 throw new ArgumentOutOfRangeException("arrayIndex");
229 Debug.Assert(array.Length >= size, "array is not big enough to hold all the items in the ICollection");
231 for (int i = 0; i < size; i++) {
232 array.SetValue(entries[i].xso, arrayIndex++);
236 public IEnumerator GetEnumerator() {
237 return new XSOEnumerator(this.entries, this.size, EnumeratorType.Values);
241 internal class XSOEnumerator : IEnumerator {
242 private List<XmlSchemaObjectEntry> entries;
243 private EnumeratorType enumType;
245 protected int currentIndex;
247 protected XmlQualifiedName currentKey;
248 protected XmlSchemaObject currentValue;
251 internal XSOEnumerator(List<XmlSchemaObjectEntry> entries, int size, EnumeratorType enumType) {
252 this.entries = entries;
254 this.enumType = enumType;
258 public Object Current {
260 if (currentIndex == -1) {
261 throw new InvalidOperationException(Res.GetString(Res.Sch_EnumNotStarted, string.Empty));
263 if (currentIndex >= size) {
264 throw new InvalidOperationException(Res.GetString(Res.Sch_EnumFinished, string.Empty));
267 case EnumeratorType.Keys:
270 case EnumeratorType.Values:
273 case EnumeratorType.DictionaryEntry:
274 return new DictionaryEntry(currentKey, currentValue);
283 public bool MoveNext() {
284 if (currentIndex >= size - 1) {
290 currentValue = entries[currentIndex].xso;
291 currentKey = entries[currentIndex].qname;
295 public void Reset() {
302 internal class XSODictionaryEnumerator : XSOEnumerator, IDictionaryEnumerator {
304 internal XSODictionaryEnumerator(List<XmlSchemaObjectEntry> entries, int size, EnumeratorType enumType) : base(entries, size, enumType) {
307 //IDictionaryEnumerator members
308 public DictionaryEntry Entry {
310 if (currentIndex == -1) {
311 throw new InvalidOperationException(Res.GetString(Res.Sch_EnumNotStarted, string.Empty));
313 if (currentIndex >= size) {
314 throw new InvalidOperationException(Res.GetString(Res.Sch_EnumFinished, string.Empty));
316 return new DictionaryEntry(currentKey, currentValue);
322 if (currentIndex == -1) {
323 throw new InvalidOperationException(Res.GetString(Res.Sch_EnumNotStarted, string.Empty));
325 if (currentIndex >= size) {
326 throw new InvalidOperationException(Res.GetString(Res.Sch_EnumFinished, string.Empty));
332 public object Value {
334 if (currentIndex == -1) {
335 throw new InvalidOperationException(Res.GetString(Res.Sch_EnumNotStarted, string.Empty));
337 if (currentIndex >= size) {
338 throw new InvalidOperationException(Res.GetString(Res.Sch_EnumFinished, string.Empty));