ConfigurationElementCollection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Configuration / System / Configuration / ConfigurationElementCollection.cs / 4 / ConfigurationElementCollection.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Collections.Specialized;
using System.Xml; 

namespace System.Configuration {

    [System.Diagnostics.DebuggerDisplay("Count = {Count}")] 
    public abstract class ConfigurationElementCollection : ConfigurationElement, ICollection {
        internal const string DefaultAddItemName = "add"; 
        internal const string DefaultRemoveItemName = "remove"; 
        internal const string DefaultClearItemsName = "clear";
 
        private int _removedItemCount = 0;    // Number of items removed for this collection (not including parent)
        private int _inheritedCount = 0;      // Total number of inherited items
        private ArrayList _items = new ArrayList();
        private String _addElement = DefaultAddItemName; 
        private String _removeElement = DefaultRemoveItemName;
        private String _clearElement = DefaultClearItemsName; 
        private bool bEmitClearTag = false; 
        private bool bCollectionCleared = false;
        private bool bModified = false; 
        private bool bReadOnly = false;
        private IComparer _comparer;
        internal bool internalAddToEnd = false;
        internal String internalElementTagName = string.Empty; 

        protected ConfigurationElementCollection() { 
        } 

        protected ConfigurationElementCollection(IComparer comparer) { 
            if (comparer == null) {
                throw new ArgumentNullException("comparer");
            }
 
            _comparer = comparer;
        } 
 
        private ArrayList Items {
            get { 
                return _items;
            }
        }
 
        private enum InheritedType {
            inNeither = 0, 
            inParent = 1, 
            inSelf = 2,
            inBothSame = 3, 
            inBothDiff = 4,
            inBothCopyNoRemove = 5,
        }
 
        protected internal string AddElementName {
            get { 
                return _addElement; 
            }
            set { 
                _addElement = value;
                if (BaseConfigurationRecord.IsReservedAttributeName(value)) {
                    throw new ArgumentException(SR.GetString(SR.Item_name_reserved, DefaultAddItemName, value));
                } 
            }
        } 
 
        protected internal string RemoveElementName {
            get { 
                return _removeElement;
            }
            set {
                if (BaseConfigurationRecord.IsReservedAttributeName(value)) { 
                    throw new ArgumentException(SR.GetString(SR.Item_name_reserved, DefaultRemoveItemName, value));
                } 
                _removeElement = value; 
            }
        } 

        protected internal string ClearElementName {
            get {
                return _clearElement; 
            }
            set { 
                if (BaseConfigurationRecord.IsReservedAttributeName(value)) { 
                    throw new ArgumentException(SR.GetString(SR.Item_name_reserved, DefaultClearItemsName, value));
                } 
                _clearElement = value;
            }
        }
 
        // AssociateContext
        // 
        // Associate a collection of values with a configRecord 
        //
        internal override void AssociateContext(BaseConfigurationRecord configRecord) { 
            base.AssociateContext(configRecord);

            foreach (Entry entry in _items) {
                if (entry._value != null) { 
                    entry._value.AssociateContext(configRecord);
                } 
            } 
        }
 
        protected internal override bool IsModified() {
            if (bModified == true) {
                return true;
            } 

            if (base.IsModified() == true) { 
                return true; 
            }
 
            foreach (Entry entry in _items) {
                if (entry._entryType != EntryType.Removed) {
                    ConfigurationElement elem = entry._value;
                    if (elem.IsModified()) { 
                        return true;
                    } 
                } 
            }
            return false; 
        }

        protected internal override void ResetModified() {
            bModified = false; 
            base.ResetModified();
 
            foreach (Entry entry in _items) { 
                if (entry._entryType != EntryType.Removed) {
                    ConfigurationElement elem = entry._value; 
                    elem.ResetModified();
                }
            }
        } 

        public override bool IsReadOnly() { 
            return bReadOnly; 
        }
 
        protected internal override void SetReadOnly() {
            bReadOnly = true;
            foreach (Entry entry in _items) {
                if (entry._entryType != EntryType.Removed) { 
                    ConfigurationElement elem = entry._value;
                    elem.SetReadOnly(); 
                } 
            }
        } 

        internal virtual IEnumerator GetEnumeratorImpl() {
            return new Enumerator(_items, this);
        } 

        internal IEnumerator GetElementsEnumerator() { 
            // Return an enumerator over the collection's config elements. 
            // This is different then the std GetEnumerator because the second one
            // can return different set of items if overriden in a derived class 

            return new Enumerator(_items, this);
        }
 
        public override bool Equals(object compareTo) {
            if (compareTo.GetType() == this.GetType()) { 
                ConfigurationElementCollection compareToElem = (ConfigurationElementCollection)compareTo; 
                if (this.Count != compareToElem.Count) {
                    return false; 
                }

                foreach (Entry thisEntry in Items) {
                    bool found = false; 
                    foreach (Entry compareEntry in compareToElem.Items) {
                        if (Object.Equals(thisEntry._value, compareEntry._value)) { 
                            found = true; 
                            break;
                        } 
                    }
                    if (found == false) {
                        // not in the collection must be different
                        return false; 
                    }
                } 
                return true; 
            }
            return false; 
        }

        public override int GetHashCode() {
            int hHashCode = 0; 
            foreach (Entry thisEntry in Items) {
                ConfigurationElement elem = thisEntry._value; 
                hHashCode ^= elem.GetHashCode(); 
            }
            return hHashCode; 
        }


        protected internal override void Unmerge(ConfigurationElement sourceElement, 
                                                 ConfigurationElement parentElement,
                                                 ConfigurationSaveMode saveMode) { 
 
            base.Unmerge(sourceElement, parentElement, saveMode);
            if (sourceElement != null) { 
                ConfigurationElementCollection parentCollection = parentElement as ConfigurationElementCollection;
                ConfigurationElementCollection sourceCollection = sourceElement as ConfigurationElementCollection;
                Hashtable Inheritance = new Hashtable();
                _lockedAllExceptAttributesList = sourceElement._lockedAllExceptAttributesList; 
                _lockedAllExceptElementsList = sourceElement._lockedAllExceptElementsList;
                _fItemLocked = sourceElement._fItemLocked; 
                _lockedAttributesList = sourceElement._lockedAttributesList; 
                _lockedElementsList = sourceElement._lockedElementsList;
 
                AssociateContext(sourceElement._configRecord);

                if (parentElement != null) {
                    if (parentElement._lockedAttributesList != null) 
                        _lockedAttributesList = UnMergeLockList(sourceElement._lockedAttributesList,
                            parentElement._lockedAttributesList, saveMode); 
                    if (parentElement._lockedElementsList != null) 
                        _lockedElementsList = UnMergeLockList(sourceElement._lockedElementsList,
                            parentElement._lockedElementsList, saveMode); 
                    if (parentElement._lockedAllExceptAttributesList != null)
                        _lockedAllExceptAttributesList = UnMergeLockList(sourceElement._lockedAllExceptAttributesList,
                            parentElement._lockedAllExceptAttributesList, saveMode);
                    if (parentElement._lockedAllExceptElementsList != null) 
                        _lockedAllExceptElementsList = UnMergeLockList(sourceElement._lockedAllExceptElementsList,
                            parentElement._lockedAllExceptElementsList, saveMode); 
                } 

                if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap || 
                    CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                    // When writing out portable configurations the  tag should be written
                    bCollectionCleared = sourceCollection.bCollectionCleared;
                    EmitClear = (saveMode == ConfigurationSaveMode.Full && (_clearElement.Length != 0)) || 
                                (saveMode == ConfigurationSaveMode.Modified && bCollectionCleared) ?
                                    true : sourceCollection.EmitClear; 
 
                    if ((parentCollection != null) && (EmitClear != true)) {
                        foreach (Entry entry in parentCollection.Items) { 
                            if (entry._entryType != EntryType.Removed) {
                                Inheritance[entry.GetKey(this)] = InheritedType.inParent;
                            }
                        } 
                    }
 
                    foreach (Entry entry in sourceCollection.Items) { 
                        if (entry._entryType != EntryType.Removed) {
                            if (Inheritance.Contains(entry.GetKey(this))) { 
                                Entry parentEntry = (Entry)parentCollection.Items[parentCollection.RealIndexOf(entry._value)];

                                ConfigurationElement elem = entry._value;
                                if (elem.Equals(parentEntry._value)) { 
                                    // in modified mode we consider any change to be different than the parent
                                    Inheritance[entry.GetKey(this)] = InheritedType.inBothSame; 
                                    if (saveMode == ConfigurationSaveMode.Modified) { 
                                        if (elem.IsModified()) {
                                            Inheritance[entry.GetKey(this)] = InheritedType.inBothDiff; 
                                        } else
                                        if (elem.ElementPresent) {
                                            // This is when the source file contained the entry but it was an
                                            // exact copy.  We don't want to emit a remove so we treat it as 
                                            // a special case.
                                            Inheritance[entry.GetKey(this)] = InheritedType.inBothCopyNoRemove; 
                                        } 
                                    }
                                } 
                                else {
                                    Inheritance[entry.GetKey(this)] = InheritedType.inBothDiff;
                                    if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate
                                        && entry._entryType == EntryType.Added) { 
                                        // this is a special case for deailing with defect number 529517
                                        // this code allow the config to write out the same xml when no remove was 
                                        // present during deserialization. 
                                        Inheritance[entry.GetKey(this)] = InheritedType.inBothCopyNoRemove;
                                    } 
                                }
                            }
                            else { // not in parent
                                Inheritance[entry.GetKey(this)] = InheritedType.inSelf; 
                            }
                        } 
                    } 

                    // 
                    if ((parentCollection != null) && (EmitClear != true)) {
                        foreach (Entry entry in parentCollection.Items) {
                            if (entry._entryType != EntryType.Removed) {
 
                                InheritedType tp = (InheritedType)Inheritance[entry.GetKey(this)];
                                if (tp == InheritedType.inParent || tp == InheritedType.inBothDiff) { 
                                    ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString()); 

                                    elem.Reset(entry._value); // copy this entry 
                                    BaseAdd(elem,ThrowOnDuplicate,true);                          // Add it (so that is once existed in the temp
                                    BaseRemove(entry.GetKey(this), false);   // now remove it to for a remove instruction
                                }
                            } 
                        }
                    } 
 
                    foreach (Entry entry in sourceCollection.Items) {
                        if (entry._entryType != EntryType.Removed) { 
                            InheritedType tp = (InheritedType)Inheritance[entry.GetKey(this)];

                            if (tp == InheritedType.inSelf || tp == InheritedType.inBothDiff ||
                                tp == InheritedType.inBothCopyNoRemove) { 
                                ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
 
                                elem.Unmerge(entry._value, null, saveMode); 

                                if (tp == InheritedType.inSelf) { 
                                    elem.RemoveAllInheritedLocks(); // If the key changed only local locks are kept
                                }

                                BaseAdd(elem,ThrowOnDuplicate,true);                     // Add it 
                            }
                        } 
                    } 
                }
                else { 
                    if (CollectionType == ConfigurationElementCollectionType.BasicMap ||
                        CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                        foreach (Entry entry in sourceCollection.Items) {
                            bool FoundKeyInParent = false; 
                            Entry parentEntrySaved = null;
 
                            if (entry._entryType == EntryType.Added || 
                                entry._entryType == EntryType.Replaced) {
                                bool InParent = false; 

                                if (parentCollection != null) {
                                    foreach (Entry parentEntry in parentCollection.Items) {
                                        if (Object.Equals(entry.GetKey(this), parentEntry.GetKey(this))) { 
                                            // for basic map collection where the key is actually an element
                                            // we do not want the merging behavior or data will not get written 
                                            // out for the properties if they match the first element deamed to be a parent 
                                            // For example  will loose the users because
                                            // an entry exists in the root element. 
                                            if (!IsElementName(entry.GetKey(this).ToString())) {
                                                // For elements which are not keyed by the element name
                                                // need to be unmerged
                                                FoundKeyInParent = true; 
                                                parentEntrySaved = parentEntry;
                                            } 
                                        } 

                                        if (Object.Equals(entry._value, parentEntry._value)) { 
                                            FoundKeyInParent = true;
                                            InParent = true;  // in parent and the same exact values
                                            parentEntrySaved = parentEntry;
                                            break; 
                                        }
                                    } 
                                } 

                                ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString()); 

                                if (!FoundKeyInParent) {   // Unmerge is similar to a reset when used like this
                                    // except that it handles the different update modes
                                    // which Reset does not understand 
                                    elem.Unmerge(entry._value, null, saveMode); // copy this entry
                                    BaseAdd(-1, elem,true);                          // Add it 
                                } 
                                else {
                                    ConfigurationElement sourceItem = entry._value; 
                                    if (!InParent ||
                                        (saveMode == ConfigurationSaveMode.Modified && sourceItem.IsModified()) ||
                                        (saveMode == ConfigurationSaveMode.Full)) {
                                        elem.Unmerge(entry._value, parentEntrySaved._value, saveMode); 
                                        BaseAdd(-1, elem,true);                          // Add it
                                    } 
                                } 
                            }
                        } 
                    }
                }
            }
        } 

        protected internal override void Reset(ConfigurationElement parentElement) { 
            ConfigurationElementCollection parentCollection = parentElement as ConfigurationElementCollection; 
            ResetLockLists(parentElement);
 
            if (parentCollection != null) {
                foreach (Entry entry in parentCollection.Items) {
                    ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
                    elem.Reset(entry._value); 

                    if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap || 
                        CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) && 
                       (entry._entryType == EntryType.Added ||
                        entry._entryType == EntryType.Replaced)) { // do not add removed items from the parent 
                        BaseAdd(elem, true, true); // This version combines dups and throws (unless overridden)
                    }
                    else {
                        if (CollectionType == ConfigurationElementCollectionType.BasicMap || 
                            CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                            BaseAdd(-1, elem, true); // this version appends regardless of if it is a dup. 
                        } 
                    }
                } 
                _inheritedCount = Count; // After reset the count is the number of items actually inherited.
            }
        }
 
        public int Count {
            get { 
                return _items.Count - _removedItemCount; 
            }
        } 

        public bool EmitClear {
            get {
                return bEmitClearTag; 
            }
            set { 
                if (IsReadOnly()) { 
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only));
                } 
                if (value == true) {
                    CheckLockedElement(_clearElement, null);  // has clear been locked?
                    CheckLockedElement(_removeElement, null); // has remove been locked? Clear implies remove
                } 
                bModified = true;
                bEmitClearTag = value; 
            } 
        }
 
        public bool IsSynchronized {
            get {
                return false;
            } 
        }
 
        public Object SyncRoot { 
            get {
                return null; 
            }
        }

        public void CopyTo(ConfigurationElement[] array, int index) { 
            ((ICollection)this).CopyTo(array, index);
        } 
 
        void ICollection.CopyTo(Array arr, int index) {
            foreach (Entry entry in _items) { 
                if (entry._entryType != EntryType.Removed) {
                    arr.SetValue(entry._value, index++);
                }
            } 
        }
 
        public IEnumerator GetEnumerator() { 
            return GetEnumeratorImpl();
        } 

        protected virtual void BaseAdd(ConfigurationElement element) {
            BaseAdd(element, ThrowOnDuplicate);
        } 

        protected internal void BaseAdd(ConfigurationElement element, bool throwIfExists) { 
            BaseAdd(element, throwIfExists, false); 
        }
 
        private void BaseAdd(ConfigurationElement element, bool throwIfExists, bool ignoreLocks) {
            bool flagAsReplaced = false;
            bool localAddToEnd = internalAddToEnd;
 
            if (IsReadOnly()) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only)); 
            } 

            if (LockItem == true && ignoreLocks == false) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_element_locked, _addElement));
            }

            Object key = GetElementKeyInternal(element); 
            int iFoundItem = -1;
            for (int index = 0; index < _items.Count; index++) { 
                Entry entry = (Entry)_items[index]; 
                if (CompareKeys(key, entry.GetKey(this))) {
                    if (entry._value != null && entry._value.LockItem == true && ignoreLocks == false) { 
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_item_locked));
                    }
                    if (entry._entryType != EntryType.Removed && throwIfExists) {
                        if (!element.Equals(entry._value)) { 
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_already_exists, key),
                                element.PropertyFileName(""), element.PropertyLineNumber("")); 
                        } 
                        else {
                            entry._value = element; 
                        }
                        return;
                    }
                    if (entry._entryType != EntryType.Added) { 
                        if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                             CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) && 
                            entry._entryType == EntryType.Removed && 
                            _removedItemCount > 0) {
                            _removedItemCount--; // account for the value 
                        }
                        entry._entryType = EntryType.Replaced;
                        flagAsReplaced = true;
                    } 
                    if (localAddToEnd ||
                        CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                        iFoundItem = index; 
                        if (entry._entryType == EntryType.Added) {
                            // this is a special case for defect number 529517 to emulate everett behavior 
                            localAddToEnd = true;
                        }
                        break;
                    } 
                    else {
                        // check to see if the element is trying to set a locked property. 
                        if (ignoreLocks == false) { 
                            element.HandleLockedAttributes(entry._value);
                            // copy the lock from the removed element before setting the new element 
                            element.MergeLocks(entry._value);
                        }
                        entry._value = element;
                        bModified = true; 
                        return;
                    } 
                } 
            }
 
            // Brand new item.
            if (iFoundItem >= 0) {
                _items.RemoveAt(iFoundItem);
 
                // if the item being removed was inherited adjust the cout
                if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate && 
                    iFoundItem > Count + _removedItemCount - _inheritedCount) { 
                    _inheritedCount--;
                } 
            }
            BaseAddInternal(localAddToEnd ? -1 : iFoundItem, element, flagAsReplaced, ignoreLocks);
            bModified = true;
        } 

        protected int BaseIndexOf(ConfigurationElement element) { 
            int index = 0; 
            Object key = GetElementKeyInternal(element);
            foreach (Entry entry in _items) { 
                if (entry._entryType != EntryType.Removed) {
                    if (CompareKeys(key, entry.GetKey(this))) {
                        return index;
                    } 
                    index++;
                } 
            } 
            return -1;
        } 

        internal int RealIndexOf(ConfigurationElement element) {
            int index = 0;
            Object key = GetElementKeyInternal(element); 
            foreach (Entry entry in _items) {
                if (CompareKeys(key, entry.GetKey(this))) { 
                    return index; 
                }
                index++; 
            }
            return -1;
        }
 
        private void BaseAddInternal(int index, ConfigurationElement element, bool flagAsReplaced, bool ignoreLocks) {
            // Allow the element to initialize itself after its 
            // constructor has been run so that it may access 
            // virtual methods.
 
            element.AssociateContext(_configRecord);
            if (element != null) {
                element.CallInit();
            } 

            if (IsReadOnly()) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only)); 
            }
 
            if (!ignoreLocks) { // during reset we ignore locks so we can copy the elements
                if(CollectionType == ConfigurationElementCollectionType.BasicMap ||
                    CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                    if (BaseConfigurationRecord.IsReservedAttributeName(ElementName)) { 
                        throw new ArgumentException(SR.GetString(SR.Basicmap_item_name_reserved, ElementName));
                    } 
                    CheckLockedElement(ElementName, null); 
                }
                if(CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap || 
                    CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {

                    CheckLockedElement(_addElement, null);
                } 
            }
 
            if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate || 
                CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                if (index == -1) { 
                    index = Count + _removedItemCount - _inheritedCount; // insert before inherited, but after any removed
                }
                else {
                    if (index > Count + _removedItemCount - _inheritedCount && flagAsReplaced == false) { 
                        throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_add_items_below_inherited_items)));
                    } 
                } 
            }
 
            if (CollectionType == ConfigurationElementCollectionType.BasicMap &&
                index >= 0 &&
                index < _inheritedCount) {
                throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_add_items_above_inherited_items))); 
            }
 
            EntryType entryType = (flagAsReplaced == false) ? EntryType.Added : EntryType.Replaced; 

            Object key = GetElementKeyInternal(element); 

            if (index >= 0) {
                if (index > _items.Count) {
                    throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index)); 
                }
                _items.Insert(index, new Entry(entryType, key, element)); 
            } 
            else {
                _items.Add(new Entry(entryType, key, element)); 
            }

            bModified = true;
        } 

 
        protected virtual void BaseAdd(int index, ConfigurationElement element) { 
            BaseAdd(index, element, false);
        } 

        private void BaseAdd(int index, ConfigurationElement element, bool ignoreLocks) {
            if (IsReadOnly()) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only)); 
            }
            if (index < -1) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index)); 
            }
 
            if ((index != -1) &&
                (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate)) {
 
                // If it's an AddRemoveClearMap*** collection, turn the index passed into into a real internal index
                int realIndex = 0; 
 
                if (index > 0) {
                    foreach (Entry entryfound in _items) { 
                        if (entryfound._entryType != EntryType.Removed) {
                            index--;
                        }
                        if (index == 0) { 
                            break;
                        } 
                        realIndex++; 
                    }
                    index = ++realIndex; 
                }
                // check for duplicates
                Object key = GetElementKeyInternal(element);
                foreach (Entry entry in _items) { 
                    if (CompareKeys(key, entry.GetKey(this))) {
                        if (entry._entryType != EntryType.Removed) { 
                            if (!element.Equals(entry._value)) { 
                                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_already_exists, key),
                                        element.PropertyFileName(""), element.PropertyLineNumber("")); 
                            }
                            return;
                        }
                    } 
                }
 
            } 

            BaseAddInternal(index, element, false, ignoreLocks); 
        }

        protected internal void BaseRemove(Object key) {
            BaseRemove(key, false); 
        }
 
        private void BaseRemove(Object key, bool throwIfMissing) { 
            if (IsReadOnly())
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only)); 

            int index = 0;
            bool foundEntry = false;
            foreach (Entry entry in _items) { 
                if (CompareKeys(key, entry.GetKey(this))) {
                    foundEntry = true; 
 
                    if (entry._value == null) // A phoney delete is already present
                    { 
                        if (throwIfMissing) {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found, key));
                        }
                        else { 
                            return;
                        } 
                    } 

                    if (entry._value.LockItem == true) { 
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_attribute_locked, key));
                    }

                    if (entry._value.ElementPresent == false) { 
                        CheckLockedElement(_removeElement, null); // has remove been locked?
                    } 
 
                    switch (entry._entryType) {
                        case EntryType.Added: 
                            if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap &&
                                CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                                if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                                    if (index >= Count - _inheritedCount) { 
                                        throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_remove_inherited_items)));
                                    } 
                                } 
                                if (CollectionType == ConfigurationElementCollectionType.BasicMap) {
                                    if (index < _inheritedCount) { 
                                        throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_remove_inherited_items)));
                                    }
                                }
 
                                _items.RemoveAt(index);
                            } 
                            else { 
                                // don't really remove it from the collection just mark it removed
                                entry._entryType = EntryType.Removed; 
                                _removedItemCount++;
                            }
                            break;
                        case EntryType.Removed: 
                            if (throwIfMissing) {
                                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_already_removed)); 
                            } 
                            break;
                        default: 
                            if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap &&
                                CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_elements_may_not_be_removed));
                            } 
                            entry._entryType = EntryType.Removed;
                            _removedItemCount++; 
                            break; 
                    }
                    bModified = true; 
                    return;
                }
                index++;
            } 
            // Note because it is possible for removes to get orphaned by the API they will
            // not cause a throw from the base classes.  The scenerio is: 
            //  Add an item in a parent level 
            //  remove the item in a child level
            //  remove the item at the parent level. 
            //
            // throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found));
            if (foundEntry == false) {
                if (throwIfMissing) { 
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found, key));
                } 
 
                if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                    CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                    if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                        _items.Insert(Count + _removedItemCount - _inheritedCount, new Entry(EntryType.Removed, key, null));
                    }
                    else { 
                        _items.Add(new Entry(EntryType.Removed, key, null));
                    } 
                    _removedItemCount++; 
                }
 
            }
        }

        protected internal ConfigurationElement BaseGet(Object key) { 
            foreach (Entry entry in _items) {
                if (entry._entryType != EntryType.Removed) { 
                    if (CompareKeys(key, entry.GetKey(this))) { 
                        return entry._value;
                    } 
                }
            }
            return null;
        } 

        protected internal bool BaseIsRemoved(Object key) { 
            foreach (Entry entry in _items) { 
                if (CompareKeys(key, entry.GetKey(this))) {
                    if (entry._entryType == EntryType.Removed) { 
                        return true;
                    }
                    else {
                        return false; 
                    }
                } 
            } 
            return false;
        } 

        protected internal ConfigurationElement BaseGet(int index) {
            if (index < 0) {
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index)); 
            }
 
            int VirtualIndex = 0; 
            Entry entry = (Entry)null;
 
            foreach (Entry entryfound in _items) {
                if (VirtualIndex == index && (entryfound._entryType != EntryType.Removed)) {
                    entry = entryfound;
                    break; 
                }
                if (entryfound._entryType != EntryType.Removed) { 
                    VirtualIndex++; 
                }
            } 

            if (entry != null) {
                return entry._value;
            } 
            else {
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index)); 
            } 
        }
 
        protected internal object[] BaseGetAllKeys() {
            object[] keys = new object[Count];
            int index = 0;
            foreach (Entry entry in _items) { 
                if (entry._entryType != EntryType.Removed) {
                    keys[index] = entry.GetKey(this); 
                    index++; 
                }
            } 
            return keys;
        }

        protected internal object BaseGetKey(int index) { 
            int VirtualIndex = 0;
            Entry entry = (Entry)null; 
            if (index < 0) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index));
            } 

            foreach (Entry entryfound in _items) {
                if (VirtualIndex == index && (entryfound._entryType != EntryType.Removed)) {
                    entry = entryfound; 
                    break;
                } 
 
                if (entryfound._entryType != EntryType.Removed) {
                    VirtualIndex++; 
                }
            }

            // Entry entry = (Entry)_items[index]; 
            if (entry != null) {
                object key = entry.GetKey(this); 
 
                return key;
            } 
            else {
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index));
            }
        } 

        protected internal void BaseClear() { 
            if (IsReadOnly()) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only));
            } 

            CheckLockedElement(_clearElement, null);  // has clear been locked?
            CheckLockedElement(_removeElement, null); // has remove been locked? Clear implies remove
 
            bModified = true;
            bCollectionCleared = true; 
            if ((CollectionType == ConfigurationElementCollectionType.BasicMap || 
                 CollectionType == ConfigurationElementCollectionType.BasicMapAlternate)
                && _inheritedCount > 0) { 
                int RemoveIndex = 0;
                if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                    RemoveIndex = 0; // Inherited items are at the bottom and cannot be removed
                } 
                if (CollectionType == ConfigurationElementCollectionType.BasicMap) {
                    RemoveIndex = _inheritedCount; // inherited items are at the top and cannot be removed 
                } 
                while (Count - _inheritedCount > 0) {
                    _items.RemoveAt(RemoveIndex); 
                }
            }
            else {
                // do not clear any locked items 
                // _items.Clear();
                int inheritedRemoved = 0; 
                int removedRemoved = 0; 
                int initialCount = Count;
 
                // check for locks before removing any items from the collection
                for (int CheckIndex = 0; CheckIndex < _items.Count; CheckIndex++) {
                    Entry entry = (Entry)_items[CheckIndex];
                    if (entry._value != null && entry._value.LockItem == true) { 
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_item_locked_cannot_clear));
                    } 
                } 

                for (int RemoveIndex = _items.Count - 1; RemoveIndex >= 0; RemoveIndex--) { 
                    Entry entry = (Entry)_items[RemoveIndex];
                    if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap &&
                            RemoveIndex < _inheritedCount) ||
                        (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate && 
                            (RemoveIndex >= initialCount - _inheritedCount))) {
                        inheritedRemoved++; 
                    } 
                    if (entry._entryType == EntryType.Removed) {
                        removedRemoved++; 
                    }

                    _items.RemoveAt(RemoveIndex);
                } 
                _inheritedCount -= inheritedRemoved;
                _removedItemCount -= removedRemoved; 
            } 
        }
 
        protected internal void BaseRemoveAt(int index) {
            if (IsReadOnly()) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only));
            } 
            int VirtualIndex = 0;
            Entry entry = (Entry)null; 
 
            foreach (Entry entryfound in _items) {
                if (VirtualIndex == index && (entryfound._entryType != EntryType.Removed)) { 
                    entry = entryfound;
                    break;
                }
 
                if (entryfound._entryType != EntryType.Removed) {
                    VirtualIndex++; 
                } 
            }
 
            if (entry == null) {
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index));
            }
            else { 
                if (entry._value.LockItem == true) {
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_attribute_locked, entry.GetKey(this))); 
                } 

                if (entry._value.ElementPresent == false) { 
                    CheckLockedElement(_removeElement, null); // has remove been locked?
                }

                switch (entry._entryType) { 
                    case EntryType.Added:
                        if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap && 
                            CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                            if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                                if (index >= Count - _inheritedCount) { 
                                    throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_remove_inherited_items)));
                                }
                            }
 
                            if (CollectionType == ConfigurationElementCollectionType.BasicMap) {
                                if (index < _inheritedCount) { 
                                    throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_remove_inherited_items))); 
                                }
                            } 

                            _items.RemoveAt(index);

                        } 
                        else {
                            // don't really remove it from the collection just mark it removed 
                            if (entry._value.ElementPresent == false) { 
                                CheckLockedElement(_removeElement, null); // has remove been locked?
                            } 

                            entry._entryType = EntryType.Removed;
                            _removedItemCount++;
                        } 

                        break; 
 
                    case EntryType.Removed:
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_already_removed)); 

                    default:
                        if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap &&
                            CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_elements_may_not_be_removed));
                        } 
 
                        entry._entryType = EntryType.Removed;
                        _removedItemCount++; 
                        break;
                }
                bModified = true;
            } 
        }
 
 

        protected internal override bool SerializeElement(XmlWriter writer, bool serializeCollectionKey) { 
            ConfigurationElementCollectionType type = CollectionType;
            bool DataToWrite = false;

            DataToWrite |= base.SerializeElement(writer, serializeCollectionKey); 

            if (type == ConfigurationElementCollectionType.AddRemoveClearMap || 
                type == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                // it is possible that the collection only has to be cleared and contains
                // no real elements 
                if (bEmitClearTag == true && (_clearElement.Length != 0)) {
                    if (writer != null) {
                        writer.WriteStartElement(_clearElement);
                        writer.WriteEndElement(); 
                    }
                    DataToWrite = true; 
                } 
            }
 
            foreach (Entry entry in _items) {
                if (type == ConfigurationElementCollectionType.BasicMap ||
                    type == ConfigurationElementCollectionType.BasicMapAlternate) {
                    if (entry._entryType == EntryType.Added || entry._entryType == EntryType.Replaced) { 
                        if (ElementName != null && ElementName.Length != 0) {
                            if (BaseConfigurationRecord.IsReservedAttributeName(ElementName)) { 
                                throw new ArgumentException(SR.GetString(SR.Basicmap_item_name_reserved, ElementName)); 
                            }
                            DataToWrite |= entry._value.SerializeToXmlElement(writer, ElementName); 
                        }
                        else {
                            DataToWrite |= entry._value.SerializeElement(writer, false);
                        } 
                    }
                } 
                else if (type == ConfigurationElementCollectionType.AddRemoveClearMap || 
                         type == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                    if ((entry._entryType == EntryType.Removed || 
                         entry._entryType == EntryType.Replaced) &&
                        entry._value != null) {

                        if (writer != null) { 
                            writer.WriteStartElement(_removeElement);
                        } 
 
                        DataToWrite |= entry._value.SerializeElement(writer, true);
 
                        if (writer != null) {
                            writer.WriteEndElement();
                        }
 
                        DataToWrite = true;
                    } 
                    if (entry._entryType == EntryType.Added || entry._entryType == EntryType.Replaced) { 
                        DataToWrite |= entry._value.SerializeToXmlElement(writer, _addElement);
                    } 
                }
            }
            return DataToWrite;
        } 

        protected override bool OnDeserializeUnrecognizedElement(String elementName, XmlReader reader) { 
            bool handled = false; // 
            if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                if (elementName == _addElement) {
                    ConfigurationElement elem = CallCreateNewElement();
                    elem.ResetLockLists(this);
                    elem.DeserializeElement(reader, false); 
                    BaseAdd(elem);
                    handled = true; 
                } 
                else if (elementName == _removeElement) {
                    ConfigurationElement elem = CallCreateNewElement(); 
                    elem.ResetLockLists(this);
                    elem.DeserializeElement(reader, true);
                    if (IsElementRemovable(elem) == true) {
                        BaseRemove(GetElementKeyInternal(elem), false); 
                    }
 
                    handled = true; 
                }
                else if (elementName == _clearElement) { 
                    if (reader.AttributeCount > 0) {
                        while (reader.MoveToNextAttribute()) {
                            String propertyName = reader.Name;
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_unrecognized_attribute, propertyName), reader); 
                        }
                    } 
                    CheckLockedElement(elementName, reader); 
                    reader.MoveToElement();
                    BaseClear(); // 
                    bEmitClearTag = true;
                    handled = true;
                }
            } 
            else if (elementName == ElementName) {
                if (BaseConfigurationRecord.IsReservedAttributeName(elementName)) { 
                    throw new ArgumentException(SR.GetString(SR.Basicmap_item_name_reserved, elementName)); 
                }
                ConfigurationElement elem = CallCreateNewElement(); 
                elem.ResetLockLists(this);
                elem.DeserializeElement(reader, false);
                BaseAdd(elem);
 
                handled = true;
            } 
            else if (IsElementName(elementName)) {   // this section handle the collection like the allow deny senario which 
                if (BaseConfigurationRecord.IsReservedAttributeName(elementName)) {
                    throw new ArgumentException(SR.GetString(SR.Basicmap_item_name_reserved, elementName)); 
                }
                // have multiple tags for the collection
                ConfigurationElement elem = CallCreateNewElement(elementName);
                elem.ResetLockLists(this); 
                elem.DeserializeElement(reader, false);
                BaseAdd(-1, elem); 
                handled = true; 
            }
            return handled; 
        }

        private ConfigurationElement CallCreateNewElement(string elementName) {
            ConfigurationElement elem = CreateNewElement(elementName); 
            elem.AssociateContext(_configRecord);
            elem.CallInit(); 
            return elem; 
        }
 
        private ConfigurationElement CallCreateNewElement() {
            ConfigurationElement elem = CreateNewElement();
            elem.AssociateContext(_configRecord);
            elem.CallInit(); 
            return elem;
        } 
 
        protected virtual ConfigurationElement CreateNewElement(string elementName) {
            return CreateNewElement(); 
        }
        protected abstract ConfigurationElement CreateNewElement();
        protected abstract Object GetElementKey(ConfigurationElement element);
        internal Object GetElementKeyInternal(ConfigurationElement element) { 
            Object key = GetElementKey(element);
            if (key == null) 
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_invalid_element_key)); 
            return key;
        } 

        protected virtual bool IsElementRemovable(ConfigurationElement element) {
            return true;
        } 

        private bool CompareKeys(Object key1, Object key2) { 
            if (_comparer != null) { 
                return (_comparer.Compare(key1, key2) == 0);
            } 
            else {
                return key1.Equals(key2);
            }
        } 

        protected virtual String ElementName { 
            get { 
                return "";
            } 
        }

        protected virtual bool IsElementName(string elementName) {
            return false; 
        }
 
        internal bool IsLockableElement(string elementName) { 
            if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                return (elementName == AddElementName ||
                        elementName == RemoveElementName ||
                        elementName == ClearElementName);
            } 
            else {
                return (elementName == ElementName) || IsElementName(elementName); 
            } 
        }
 
        internal string LockableElements {
            get {
                if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                    CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 

                    string ElementNames = "'" + AddElementName + "'"; // Must have an add 
                    if (RemoveElementName.Length != 0) 
                        ElementNames += ", '" + RemoveElementName + "'";
                    if (ClearElementName.Length != 0) 
                        ElementNames += ", '" + ClearElementName + "'";
                    return ElementNames;
                }
                else { 
                    if (!String.IsNullOrEmpty(ElementName)) {
                        return "'" + ElementName + "'"; 
                    } 
                    return String.Empty;
                } 
            }
        }

        protected virtual bool ThrowOnDuplicate { 
            get {
                if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap || 
                    CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                    return true;
                } 
                return false;
            }
        }
 
        public virtual ConfigurationElementCollectionType CollectionType {
            get { 
                return ConfigurationElementCollectionType.AddRemoveClearMap; 
            }
        } 

        private enum EntryType {
            Inherited,
            Replaced, 
            Removed,
            Added, 
        } 

        private class Entry { 

            internal EntryType _entryType;
            internal Object _key;
            internal ConfigurationElement _value; 

            internal Object GetKey(ConfigurationElementCollection ThisCollection) { 
                // For items that have been really inserted... 
                if (_value != null) {
                    return ThisCollection.GetElementKeyInternal(_value); 
                }
                else {
                    return _key; // These are items that only have been removed
                } 

            } 
 
            internal Entry(EntryType type, Object key, ConfigurationElement value) {
                _entryType = type; 
                _key = key;
                _value = value;
            }
        } 

        private class Enumerator : IDictionaryEnumerator { 
 
            private IEnumerator _itemsEnumerator;
            private DictionaryEntry _current = new DictionaryEntry(); 
            private ConfigurationElementCollection ThisCollection;


            internal Enumerator(ArrayList items, ConfigurationElementCollection collection) { 
                _itemsEnumerator = items.GetEnumerator();
                ThisCollection = collection; 
            } 

            bool IEnumerator.MoveNext() { 
                while (_itemsEnumerator.MoveNext()) {
                    Entry entry = (Entry)_itemsEnumerator.Current;
                    if (entry._entryType != EntryType.Removed) {
                        _current.Key = (entry.GetKey(ThisCollection) != null) ? entry.GetKey(ThisCollection) : "key"; 
                        _current.Value = entry._value;
                        return true; 
                    } 
                }
                return false; 
            }

            void IEnumerator.Reset() {
                _itemsEnumerator.Reset(); 
            }
 
            Object IEnumerator.Current { 
                get {
                    return _current.Value; 
                }
            }

            DictionaryEntry IDictionaryEnumerator.Entry { 
                get {
                    return _current; 
                } 
            }
 
            Object IDictionaryEnumerator.Key {
                get {
                    return _current.Key;
                } 
            }
 
            Object IDictionaryEnumerator.Value { 
                get {
                    return _current.Value; 
                }
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Collections.Specialized;
using System.Xml; 

namespace System.Configuration {

    [System.Diagnostics.DebuggerDisplay("Count = {Count}")] 
    public abstract class ConfigurationElementCollection : ConfigurationElement, ICollection {
        internal const string DefaultAddItemName = "add"; 
        internal const string DefaultRemoveItemName = "remove"; 
        internal const string DefaultClearItemsName = "clear";
 
        private int _removedItemCount = 0;    // Number of items removed for this collection (not including parent)
        private int _inheritedCount = 0;      // Total number of inherited items
        private ArrayList _items = new ArrayList();
        private String _addElement = DefaultAddItemName; 
        private String _removeElement = DefaultRemoveItemName;
        private String _clearElement = DefaultClearItemsName; 
        private bool bEmitClearTag = false; 
        private bool bCollectionCleared = false;
        private bool bModified = false; 
        private bool bReadOnly = false;
        private IComparer _comparer;
        internal bool internalAddToEnd = false;
        internal String internalElementTagName = string.Empty; 

        protected ConfigurationElementCollection() { 
        } 

        protected ConfigurationElementCollection(IComparer comparer) { 
            if (comparer == null) {
                throw new ArgumentNullException("comparer");
            }
 
            _comparer = comparer;
        } 
 
        private ArrayList Items {
            get { 
                return _items;
            }
        }
 
        private enum InheritedType {
            inNeither = 0, 
            inParent = 1, 
            inSelf = 2,
            inBothSame = 3, 
            inBothDiff = 4,
            inBothCopyNoRemove = 5,
        }
 
        protected internal string AddElementName {
            get { 
                return _addElement; 
            }
            set { 
                _addElement = value;
                if (BaseConfigurationRecord.IsReservedAttributeName(value)) {
                    throw new ArgumentException(SR.GetString(SR.Item_name_reserved, DefaultAddItemName, value));
                } 
            }
        } 
 
        protected internal string RemoveElementName {
            get { 
                return _removeElement;
            }
            set {
                if (BaseConfigurationRecord.IsReservedAttributeName(value)) { 
                    throw new ArgumentException(SR.GetString(SR.Item_name_reserved, DefaultRemoveItemName, value));
                } 
                _removeElement = value; 
            }
        } 

        protected internal string ClearElementName {
            get {
                return _clearElement; 
            }
            set { 
                if (BaseConfigurationRecord.IsReservedAttributeName(value)) { 
                    throw new ArgumentException(SR.GetString(SR.Item_name_reserved, DefaultClearItemsName, value));
                } 
                _clearElement = value;
            }
        }
 
        // AssociateContext
        // 
        // Associate a collection of values with a configRecord 
        //
        internal override void AssociateContext(BaseConfigurationRecord configRecord) { 
            base.AssociateContext(configRecord);

            foreach (Entry entry in _items) {
                if (entry._value != null) { 
                    entry._value.AssociateContext(configRecord);
                } 
            } 
        }
 
        protected internal override bool IsModified() {
            if (bModified == true) {
                return true;
            } 

            if (base.IsModified() == true) { 
                return true; 
            }
 
            foreach (Entry entry in _items) {
                if (entry._entryType != EntryType.Removed) {
                    ConfigurationElement elem = entry._value;
                    if (elem.IsModified()) { 
                        return true;
                    } 
                } 
            }
            return false; 
        }

        protected internal override void ResetModified() {
            bModified = false; 
            base.ResetModified();
 
            foreach (Entry entry in _items) { 
                if (entry._entryType != EntryType.Removed) {
                    ConfigurationElement elem = entry._value; 
                    elem.ResetModified();
                }
            }
        } 

        public override bool IsReadOnly() { 
            return bReadOnly; 
        }
 
        protected internal override void SetReadOnly() {
            bReadOnly = true;
            foreach (Entry entry in _items) {
                if (entry._entryType != EntryType.Removed) { 
                    ConfigurationElement elem = entry._value;
                    elem.SetReadOnly(); 
                } 
            }
        } 

        internal virtual IEnumerator GetEnumeratorImpl() {
            return new Enumerator(_items, this);
        } 

        internal IEnumerator GetElementsEnumerator() { 
            // Return an enumerator over the collection's config elements. 
            // This is different then the std GetEnumerator because the second one
            // can return different set of items if overriden in a derived class 

            return new Enumerator(_items, this);
        }
 
        public override bool Equals(object compareTo) {
            if (compareTo.GetType() == this.GetType()) { 
                ConfigurationElementCollection compareToElem = (ConfigurationElementCollection)compareTo; 
                if (this.Count != compareToElem.Count) {
                    return false; 
                }

                foreach (Entry thisEntry in Items) {
                    bool found = false; 
                    foreach (Entry compareEntry in compareToElem.Items) {
                        if (Object.Equals(thisEntry._value, compareEntry._value)) { 
                            found = true; 
                            break;
                        } 
                    }
                    if (found == false) {
                        // not in the collection must be different
                        return false; 
                    }
                } 
                return true; 
            }
            return false; 
        }

        public override int GetHashCode() {
            int hHashCode = 0; 
            foreach (Entry thisEntry in Items) {
                ConfigurationElement elem = thisEntry._value; 
                hHashCode ^= elem.GetHashCode(); 
            }
            return hHashCode; 
        }


        protected internal override void Unmerge(ConfigurationElement sourceElement, 
                                                 ConfigurationElement parentElement,
                                                 ConfigurationSaveMode saveMode) { 
 
            base.Unmerge(sourceElement, parentElement, saveMode);
            if (sourceElement != null) { 
                ConfigurationElementCollection parentCollection = parentElement as ConfigurationElementCollection;
                ConfigurationElementCollection sourceCollection = sourceElement as ConfigurationElementCollection;
                Hashtable Inheritance = new Hashtable();
                _lockedAllExceptAttributesList = sourceElement._lockedAllExceptAttributesList; 
                _lockedAllExceptElementsList = sourceElement._lockedAllExceptElementsList;
                _fItemLocked = sourceElement._fItemLocked; 
                _lockedAttributesList = sourceElement._lockedAttributesList; 
                _lockedElementsList = sourceElement._lockedElementsList;
 
                AssociateContext(sourceElement._configRecord);

                if (parentElement != null) {
                    if (parentElement._lockedAttributesList != null) 
                        _lockedAttributesList = UnMergeLockList(sourceElement._lockedAttributesList,
                            parentElement._lockedAttributesList, saveMode); 
                    if (parentElement._lockedElementsList != null) 
                        _lockedElementsList = UnMergeLockList(sourceElement._lockedElementsList,
                            parentElement._lockedElementsList, saveMode); 
                    if (parentElement._lockedAllExceptAttributesList != null)
                        _lockedAllExceptAttributesList = UnMergeLockList(sourceElement._lockedAllExceptAttributesList,
                            parentElement._lockedAllExceptAttributesList, saveMode);
                    if (parentElement._lockedAllExceptElementsList != null) 
                        _lockedAllExceptElementsList = UnMergeLockList(sourceElement._lockedAllExceptElementsList,
                            parentElement._lockedAllExceptElementsList, saveMode); 
                } 

                if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap || 
                    CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                    // When writing out portable configurations the  tag should be written
                    bCollectionCleared = sourceCollection.bCollectionCleared;
                    EmitClear = (saveMode == ConfigurationSaveMode.Full && (_clearElement.Length != 0)) || 
                                (saveMode == ConfigurationSaveMode.Modified && bCollectionCleared) ?
                                    true : sourceCollection.EmitClear; 
 
                    if ((parentCollection != null) && (EmitClear != true)) {
                        foreach (Entry entry in parentCollection.Items) { 
                            if (entry._entryType != EntryType.Removed) {
                                Inheritance[entry.GetKey(this)] = InheritedType.inParent;
                            }
                        } 
                    }
 
                    foreach (Entry entry in sourceCollection.Items) { 
                        if (entry._entryType != EntryType.Removed) {
                            if (Inheritance.Contains(entry.GetKey(this))) { 
                                Entry parentEntry = (Entry)parentCollection.Items[parentCollection.RealIndexOf(entry._value)];

                                ConfigurationElement elem = entry._value;
                                if (elem.Equals(parentEntry._value)) { 
                                    // in modified mode we consider any change to be different than the parent
                                    Inheritance[entry.GetKey(this)] = InheritedType.inBothSame; 
                                    if (saveMode == ConfigurationSaveMode.Modified) { 
                                        if (elem.IsModified()) {
                                            Inheritance[entry.GetKey(this)] = InheritedType.inBothDiff; 
                                        } else
                                        if (elem.ElementPresent) {
                                            // This is when the source file contained the entry but it was an
                                            // exact copy.  We don't want to emit a remove so we treat it as 
                                            // a special case.
                                            Inheritance[entry.GetKey(this)] = InheritedType.inBothCopyNoRemove; 
                                        } 
                                    }
                                } 
                                else {
                                    Inheritance[entry.GetKey(this)] = InheritedType.inBothDiff;
                                    if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate
                                        && entry._entryType == EntryType.Added) { 
                                        // this is a special case for deailing with defect number 529517
                                        // this code allow the config to write out the same xml when no remove was 
                                        // present during deserialization. 
                                        Inheritance[entry.GetKey(this)] = InheritedType.inBothCopyNoRemove;
                                    } 
                                }
                            }
                            else { // not in parent
                                Inheritance[entry.GetKey(this)] = InheritedType.inSelf; 
                            }
                        } 
                    } 

                    // 
                    if ((parentCollection != null) && (EmitClear != true)) {
                        foreach (Entry entry in parentCollection.Items) {
                            if (entry._entryType != EntryType.Removed) {
 
                                InheritedType tp = (InheritedType)Inheritance[entry.GetKey(this)];
                                if (tp == InheritedType.inParent || tp == InheritedType.inBothDiff) { 
                                    ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString()); 

                                    elem.Reset(entry._value); // copy this entry 
                                    BaseAdd(elem,ThrowOnDuplicate,true);                          // Add it (so that is once existed in the temp
                                    BaseRemove(entry.GetKey(this), false);   // now remove it to for a remove instruction
                                }
                            } 
                        }
                    } 
 
                    foreach (Entry entry in sourceCollection.Items) {
                        if (entry._entryType != EntryType.Removed) { 
                            InheritedType tp = (InheritedType)Inheritance[entry.GetKey(this)];

                            if (tp == InheritedType.inSelf || tp == InheritedType.inBothDiff ||
                                tp == InheritedType.inBothCopyNoRemove) { 
                                ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
 
                                elem.Unmerge(entry._value, null, saveMode); 

                                if (tp == InheritedType.inSelf) { 
                                    elem.RemoveAllInheritedLocks(); // If the key changed only local locks are kept
                                }

                                BaseAdd(elem,ThrowOnDuplicate,true);                     // Add it 
                            }
                        } 
                    } 
                }
                else { 
                    if (CollectionType == ConfigurationElementCollectionType.BasicMap ||
                        CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                        foreach (Entry entry in sourceCollection.Items) {
                            bool FoundKeyInParent = false; 
                            Entry parentEntrySaved = null;
 
                            if (entry._entryType == EntryType.Added || 
                                entry._entryType == EntryType.Replaced) {
                                bool InParent = false; 

                                if (parentCollection != null) {
                                    foreach (Entry parentEntry in parentCollection.Items) {
                                        if (Object.Equals(entry.GetKey(this), parentEntry.GetKey(this))) { 
                                            // for basic map collection where the key is actually an element
                                            // we do not want the merging behavior or data will not get written 
                                            // out for the properties if they match the first element deamed to be a parent 
                                            // For example  will loose the users because
                                            // an entry exists in the root element. 
                                            if (!IsElementName(entry.GetKey(this).ToString())) {
                                                // For elements which are not keyed by the element name
                                                // need to be unmerged
                                                FoundKeyInParent = true; 
                                                parentEntrySaved = parentEntry;
                                            } 
                                        } 

                                        if (Object.Equals(entry._value, parentEntry._value)) { 
                                            FoundKeyInParent = true;
                                            InParent = true;  // in parent and the same exact values
                                            parentEntrySaved = parentEntry;
                                            break; 
                                        }
                                    } 
                                } 

                                ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString()); 

                                if (!FoundKeyInParent) {   // Unmerge is similar to a reset when used like this
                                    // except that it handles the different update modes
                                    // which Reset does not understand 
                                    elem.Unmerge(entry._value, null, saveMode); // copy this entry
                                    BaseAdd(-1, elem,true);                          // Add it 
                                } 
                                else {
                                    ConfigurationElement sourceItem = entry._value; 
                                    if (!InParent ||
                                        (saveMode == ConfigurationSaveMode.Modified && sourceItem.IsModified()) ||
                                        (saveMode == ConfigurationSaveMode.Full)) {
                                        elem.Unmerge(entry._value, parentEntrySaved._value, saveMode); 
                                        BaseAdd(-1, elem,true);                          // Add it
                                    } 
                                } 
                            }
                        } 
                    }
                }
            }
        } 

        protected internal override void Reset(ConfigurationElement parentElement) { 
            ConfigurationElementCollection parentCollection = parentElement as ConfigurationElementCollection; 
            ResetLockLists(parentElement);
 
            if (parentCollection != null) {
                foreach (Entry entry in parentCollection.Items) {
                    ConfigurationElement elem = CallCreateNewElement(entry.GetKey(this).ToString());
                    elem.Reset(entry._value); 

                    if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap || 
                        CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) && 
                       (entry._entryType == EntryType.Added ||
                        entry._entryType == EntryType.Replaced)) { // do not add removed items from the parent 
                        BaseAdd(elem, true, true); // This version combines dups and throws (unless overridden)
                    }
                    else {
                        if (CollectionType == ConfigurationElementCollectionType.BasicMap || 
                            CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                            BaseAdd(-1, elem, true); // this version appends regardless of if it is a dup. 
                        } 
                    }
                } 
                _inheritedCount = Count; // After reset the count is the number of items actually inherited.
            }
        }
 
        public int Count {
            get { 
                return _items.Count - _removedItemCount; 
            }
        } 

        public bool EmitClear {
            get {
                return bEmitClearTag; 
            }
            set { 
                if (IsReadOnly()) { 
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only));
                } 
                if (value == true) {
                    CheckLockedElement(_clearElement, null);  // has clear been locked?
                    CheckLockedElement(_removeElement, null); // has remove been locked? Clear implies remove
                } 
                bModified = true;
                bEmitClearTag = value; 
            } 
        }
 
        public bool IsSynchronized {
            get {
                return false;
            } 
        }
 
        public Object SyncRoot { 
            get {
                return null; 
            }
        }

        public void CopyTo(ConfigurationElement[] array, int index) { 
            ((ICollection)this).CopyTo(array, index);
        } 
 
        void ICollection.CopyTo(Array arr, int index) {
            foreach (Entry entry in _items) { 
                if (entry._entryType != EntryType.Removed) {
                    arr.SetValue(entry._value, index++);
                }
            } 
        }
 
        public IEnumerator GetEnumerator() { 
            return GetEnumeratorImpl();
        } 

        protected virtual void BaseAdd(ConfigurationElement element) {
            BaseAdd(element, ThrowOnDuplicate);
        } 

        protected internal void BaseAdd(ConfigurationElement element, bool throwIfExists) { 
            BaseAdd(element, throwIfExists, false); 
        }
 
        private void BaseAdd(ConfigurationElement element, bool throwIfExists, bool ignoreLocks) {
            bool flagAsReplaced = false;
            bool localAddToEnd = internalAddToEnd;
 
            if (IsReadOnly()) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only)); 
            } 

            if (LockItem == true && ignoreLocks == false) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_element_locked, _addElement));
            }

            Object key = GetElementKeyInternal(element); 
            int iFoundItem = -1;
            for (int index = 0; index < _items.Count; index++) { 
                Entry entry = (Entry)_items[index]; 
                if (CompareKeys(key, entry.GetKey(this))) {
                    if (entry._value != null && entry._value.LockItem == true && ignoreLocks == false) { 
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_item_locked));
                    }
                    if (entry._entryType != EntryType.Removed && throwIfExists) {
                        if (!element.Equals(entry._value)) { 
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_already_exists, key),
                                element.PropertyFileName(""), element.PropertyLineNumber("")); 
                        } 
                        else {
                            entry._value = element; 
                        }
                        return;
                    }
                    if (entry._entryType != EntryType.Added) { 
                        if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                             CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) && 
                            entry._entryType == EntryType.Removed && 
                            _removedItemCount > 0) {
                            _removedItemCount--; // account for the value 
                        }
                        entry._entryType = EntryType.Replaced;
                        flagAsReplaced = true;
                    } 
                    if (localAddToEnd ||
                        CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                        iFoundItem = index; 
                        if (entry._entryType == EntryType.Added) {
                            // this is a special case for defect number 529517 to emulate everett behavior 
                            localAddToEnd = true;
                        }
                        break;
                    } 
                    else {
                        // check to see if the element is trying to set a locked property. 
                        if (ignoreLocks == false) { 
                            element.HandleLockedAttributes(entry._value);
                            // copy the lock from the removed element before setting the new element 
                            element.MergeLocks(entry._value);
                        }
                        entry._value = element;
                        bModified = true; 
                        return;
                    } 
                } 
            }
 
            // Brand new item.
            if (iFoundItem >= 0) {
                _items.RemoveAt(iFoundItem);
 
                // if the item being removed was inherited adjust the cout
                if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate && 
                    iFoundItem > Count + _removedItemCount - _inheritedCount) { 
                    _inheritedCount--;
                } 
            }
            BaseAddInternal(localAddToEnd ? -1 : iFoundItem, element, flagAsReplaced, ignoreLocks);
            bModified = true;
        } 

        protected int BaseIndexOf(ConfigurationElement element) { 
            int index = 0; 
            Object key = GetElementKeyInternal(element);
            foreach (Entry entry in _items) { 
                if (entry._entryType != EntryType.Removed) {
                    if (CompareKeys(key, entry.GetKey(this))) {
                        return index;
                    } 
                    index++;
                } 
            } 
            return -1;
        } 

        internal int RealIndexOf(ConfigurationElement element) {
            int index = 0;
            Object key = GetElementKeyInternal(element); 
            foreach (Entry entry in _items) {
                if (CompareKeys(key, entry.GetKey(this))) { 
                    return index; 
                }
                index++; 
            }
            return -1;
        }
 
        private void BaseAddInternal(int index, ConfigurationElement element, bool flagAsReplaced, bool ignoreLocks) {
            // Allow the element to initialize itself after its 
            // constructor has been run so that it may access 
            // virtual methods.
 
            element.AssociateContext(_configRecord);
            if (element != null) {
                element.CallInit();
            } 

            if (IsReadOnly()) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only)); 
            }
 
            if (!ignoreLocks) { // during reset we ignore locks so we can copy the elements
                if(CollectionType == ConfigurationElementCollectionType.BasicMap ||
                    CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                    if (BaseConfigurationRecord.IsReservedAttributeName(ElementName)) { 
                        throw new ArgumentException(SR.GetString(SR.Basicmap_item_name_reserved, ElementName));
                    } 
                    CheckLockedElement(ElementName, null); 
                }
                if(CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap || 
                    CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {

                    CheckLockedElement(_addElement, null);
                } 
            }
 
            if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate || 
                CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                if (index == -1) { 
                    index = Count + _removedItemCount - _inheritedCount; // insert before inherited, but after any removed
                }
                else {
                    if (index > Count + _removedItemCount - _inheritedCount && flagAsReplaced == false) { 
                        throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_add_items_below_inherited_items)));
                    } 
                } 
            }
 
            if (CollectionType == ConfigurationElementCollectionType.BasicMap &&
                index >= 0 &&
                index < _inheritedCount) {
                throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_add_items_above_inherited_items))); 
            }
 
            EntryType entryType = (flagAsReplaced == false) ? EntryType.Added : EntryType.Replaced; 

            Object key = GetElementKeyInternal(element); 

            if (index >= 0) {
                if (index > _items.Count) {
                    throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index)); 
                }
                _items.Insert(index, new Entry(entryType, key, element)); 
            } 
            else {
                _items.Add(new Entry(entryType, key, element)); 
            }

            bModified = true;
        } 

 
        protected virtual void BaseAdd(int index, ConfigurationElement element) { 
            BaseAdd(index, element, false);
        } 

        private void BaseAdd(int index, ConfigurationElement element, bool ignoreLocks) {
            if (IsReadOnly()) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only)); 
            }
            if (index < -1) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index)); 
            }
 
            if ((index != -1) &&
                (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate)) {
 
                // If it's an AddRemoveClearMap*** collection, turn the index passed into into a real internal index
                int realIndex = 0; 
 
                if (index > 0) {
                    foreach (Entry entryfound in _items) { 
                        if (entryfound._entryType != EntryType.Removed) {
                            index--;
                        }
                        if (index == 0) { 
                            break;
                        } 
                        realIndex++; 
                    }
                    index = ++realIndex; 
                }
                // check for duplicates
                Object key = GetElementKeyInternal(element);
                foreach (Entry entry in _items) { 
                    if (CompareKeys(key, entry.GetKey(this))) {
                        if (entry._entryType != EntryType.Removed) { 
                            if (!element.Equals(entry._value)) { 
                                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_already_exists, key),
                                        element.PropertyFileName(""), element.PropertyLineNumber("")); 
                            }
                            return;
                        }
                    } 
                }
 
            } 

            BaseAddInternal(index, element, false, ignoreLocks); 
        }

        protected internal void BaseRemove(Object key) {
            BaseRemove(key, false); 
        }
 
        private void BaseRemove(Object key, bool throwIfMissing) { 
            if (IsReadOnly())
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only)); 

            int index = 0;
            bool foundEntry = false;
            foreach (Entry entry in _items) { 
                if (CompareKeys(key, entry.GetKey(this))) {
                    foundEntry = true; 
 
                    if (entry._value == null) // A phoney delete is already present
                    { 
                        if (throwIfMissing) {
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found, key));
                        }
                        else { 
                            return;
                        } 
                    } 

                    if (entry._value.LockItem == true) { 
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_attribute_locked, key));
                    }

                    if (entry._value.ElementPresent == false) { 
                        CheckLockedElement(_removeElement, null); // has remove been locked?
                    } 
 
                    switch (entry._entryType) {
                        case EntryType.Added: 
                            if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap &&
                                CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                                if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                                    if (index >= Count - _inheritedCount) { 
                                        throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_remove_inherited_items)));
                                    } 
                                } 
                                if (CollectionType == ConfigurationElementCollectionType.BasicMap) {
                                    if (index < _inheritedCount) { 
                                        throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_remove_inherited_items)));
                                    }
                                }
 
                                _items.RemoveAt(index);
                            } 
                            else { 
                                // don't really remove it from the collection just mark it removed
                                entry._entryType = EntryType.Removed; 
                                _removedItemCount++;
                            }
                            break;
                        case EntryType.Removed: 
                            if (throwIfMissing) {
                                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_already_removed)); 
                            } 
                            break;
                        default: 
                            if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap &&
                                CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_elements_may_not_be_removed));
                            } 
                            entry._entryType = EntryType.Removed;
                            _removedItemCount++; 
                            break; 
                    }
                    bModified = true; 
                    return;
                }
                index++;
            } 
            // Note because it is possible for removes to get orphaned by the API they will
            // not cause a throw from the base classes.  The scenerio is: 
            //  Add an item in a parent level 
            //  remove the item in a child level
            //  remove the item at the parent level. 
            //
            // throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found));
            if (foundEntry == false) {
                if (throwIfMissing) { 
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_not_found, key));
                } 
 
                if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                    CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                    if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                        _items.Insert(Count + _removedItemCount - _inheritedCount, new Entry(EntryType.Removed, key, null));
                    }
                    else { 
                        _items.Add(new Entry(EntryType.Removed, key, null));
                    } 
                    _removedItemCount++; 
                }
 
            }
        }

        protected internal ConfigurationElement BaseGet(Object key) { 
            foreach (Entry entry in _items) {
                if (entry._entryType != EntryType.Removed) { 
                    if (CompareKeys(key, entry.GetKey(this))) { 
                        return entry._value;
                    } 
                }
            }
            return null;
        } 

        protected internal bool BaseIsRemoved(Object key) { 
            foreach (Entry entry in _items) { 
                if (CompareKeys(key, entry.GetKey(this))) {
                    if (entry._entryType == EntryType.Removed) { 
                        return true;
                    }
                    else {
                        return false; 
                    }
                } 
            } 
            return false;
        } 

        protected internal ConfigurationElement BaseGet(int index) {
            if (index < 0) {
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index)); 
            }
 
            int VirtualIndex = 0; 
            Entry entry = (Entry)null;
 
            foreach (Entry entryfound in _items) {
                if (VirtualIndex == index && (entryfound._entryType != EntryType.Removed)) {
                    entry = entryfound;
                    break; 
                }
                if (entryfound._entryType != EntryType.Removed) { 
                    VirtualIndex++; 
                }
            } 

            if (entry != null) {
                return entry._value;
            } 
            else {
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index)); 
            } 
        }
 
        protected internal object[] BaseGetAllKeys() {
            object[] keys = new object[Count];
            int index = 0;
            foreach (Entry entry in _items) { 
                if (entry._entryType != EntryType.Removed) {
                    keys[index] = entry.GetKey(this); 
                    index++; 
                }
            } 
            return keys;
        }

        protected internal object BaseGetKey(int index) { 
            int VirtualIndex = 0;
            Entry entry = (Entry)null; 
            if (index < 0) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index));
            } 

            foreach (Entry entryfound in _items) {
                if (VirtualIndex == index && (entryfound._entryType != EntryType.Removed)) {
                    entry = entryfound; 
                    break;
                } 
 
                if (entryfound._entryType != EntryType.Removed) {
                    VirtualIndex++; 
                }
            }

            // Entry entry = (Entry)_items[index]; 
            if (entry != null) {
                object key = entry.GetKey(this); 
 
                return key;
            } 
            else {
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index));
            }
        } 

        protected internal void BaseClear() { 
            if (IsReadOnly()) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only));
            } 

            CheckLockedElement(_clearElement, null);  // has clear been locked?
            CheckLockedElement(_removeElement, null); // has remove been locked? Clear implies remove
 
            bModified = true;
            bCollectionCleared = true; 
            if ((CollectionType == ConfigurationElementCollectionType.BasicMap || 
                 CollectionType == ConfigurationElementCollectionType.BasicMapAlternate)
                && _inheritedCount > 0) { 
                int RemoveIndex = 0;
                if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                    RemoveIndex = 0; // Inherited items are at the bottom and cannot be removed
                } 
                if (CollectionType == ConfigurationElementCollectionType.BasicMap) {
                    RemoveIndex = _inheritedCount; // inherited items are at the top and cannot be removed 
                } 
                while (Count - _inheritedCount > 0) {
                    _items.RemoveAt(RemoveIndex); 
                }
            }
            else {
                // do not clear any locked items 
                // _items.Clear();
                int inheritedRemoved = 0; 
                int removedRemoved = 0; 
                int initialCount = Count;
 
                // check for locks before removing any items from the collection
                for (int CheckIndex = 0; CheckIndex < _items.Count; CheckIndex++) {
                    Entry entry = (Entry)_items[CheckIndex];
                    if (entry._value != null && entry._value.LockItem == true) { 
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_item_locked_cannot_clear));
                    } 
                } 

                for (int RemoveIndex = _items.Count - 1; RemoveIndex >= 0; RemoveIndex--) { 
                    Entry entry = (Entry)_items[RemoveIndex];
                    if ((CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap &&
                            RemoveIndex < _inheritedCount) ||
                        (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate && 
                            (RemoveIndex >= initialCount - _inheritedCount))) {
                        inheritedRemoved++; 
                    } 
                    if (entry._entryType == EntryType.Removed) {
                        removedRemoved++; 
                    }

                    _items.RemoveAt(RemoveIndex);
                } 
                _inheritedCount -= inheritedRemoved;
                _removedItemCount -= removedRemoved; 
            } 
        }
 
        protected internal void BaseRemoveAt(int index) {
            if (IsReadOnly()) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_read_only));
            } 
            int VirtualIndex = 0;
            Entry entry = (Entry)null; 
 
            foreach (Entry entryfound in _items) {
                if (VirtualIndex == index && (entryfound._entryType != EntryType.Removed)) { 
                    entry = entryfound;
                    break;
                }
 
                if (entryfound._entryType != EntryType.Removed) {
                    VirtualIndex++; 
                } 
            }
 
            if (entry == null) {
                throw new ConfigurationErrorsException(SR.GetString(SR.IndexOutOfRange, index));
            }
            else { 
                if (entry._value.LockItem == true) {
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_attribute_locked, entry.GetKey(this))); 
                } 

                if (entry._value.ElementPresent == false) { 
                    CheckLockedElement(_removeElement, null); // has remove been locked?
                }

                switch (entry._entryType) { 
                    case EntryType.Added:
                        if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap && 
                            CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                            if (CollectionType == ConfigurationElementCollectionType.BasicMapAlternate) {
                                if (index >= Count - _inheritedCount) { 
                                    throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_remove_inherited_items)));
                                }
                            }
 
                            if (CollectionType == ConfigurationElementCollectionType.BasicMap) {
                                if (index < _inheritedCount) { 
                                    throw (new ConfigurationErrorsException(SR.GetString(SR.Config_base_cannot_remove_inherited_items))); 
                                }
                            } 

                            _items.RemoveAt(index);

                        } 
                        else {
                            // don't really remove it from the collection just mark it removed 
                            if (entry._value.ElementPresent == false) { 
                                CheckLockedElement(_removeElement, null); // has remove been locked?
                            } 

                            entry._entryType = EntryType.Removed;
                            _removedItemCount++;
                        } 

                        break; 
 
                    case EntryType.Removed:
                        throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_entry_already_removed)); 

                    default:
                        if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap &&
                            CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_collection_elements_may_not_be_removed));
                        } 
 
                        entry._entryType = EntryType.Removed;
                        _removedItemCount++; 
                        break;
                }
                bModified = true;
            } 
        }
 
 

        protected internal override bool SerializeElement(XmlWriter writer, bool serializeCollectionKey) { 
            ConfigurationElementCollectionType type = CollectionType;
            bool DataToWrite = false;

            DataToWrite |= base.SerializeElement(writer, serializeCollectionKey); 

            if (type == ConfigurationElementCollectionType.AddRemoveClearMap || 
                type == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                // it is possible that the collection only has to be cleared and contains
                // no real elements 
                if (bEmitClearTag == true && (_clearElement.Length != 0)) {
                    if (writer != null) {
                        writer.WriteStartElement(_clearElement);
                        writer.WriteEndElement(); 
                    }
                    DataToWrite = true; 
                } 
            }
 
            foreach (Entry entry in _items) {
                if (type == ConfigurationElementCollectionType.BasicMap ||
                    type == ConfigurationElementCollectionType.BasicMapAlternate) {
                    if (entry._entryType == EntryType.Added || entry._entryType == EntryType.Replaced) { 
                        if (ElementName != null && ElementName.Length != 0) {
                            if (BaseConfigurationRecord.IsReservedAttributeName(ElementName)) { 
                                throw new ArgumentException(SR.GetString(SR.Basicmap_item_name_reserved, ElementName)); 
                            }
                            DataToWrite |= entry._value.SerializeToXmlElement(writer, ElementName); 
                        }
                        else {
                            DataToWrite |= entry._value.SerializeElement(writer, false);
                        } 
                    }
                } 
                else if (type == ConfigurationElementCollectionType.AddRemoveClearMap || 
                         type == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) {
                    if ((entry._entryType == EntryType.Removed || 
                         entry._entryType == EntryType.Replaced) &&
                        entry._value != null) {

                        if (writer != null) { 
                            writer.WriteStartElement(_removeElement);
                        } 
 
                        DataToWrite |= entry._value.SerializeElement(writer, true);
 
                        if (writer != null) {
                            writer.WriteEndElement();
                        }
 
                        DataToWrite = true;
                    } 
                    if (entry._entryType == EntryType.Added || entry._entryType == EntryType.Replaced) { 
                        DataToWrite |= entry._value.SerializeToXmlElement(writer, _addElement);
                    } 
                }
            }
            return DataToWrite;
        } 

        protected override bool OnDeserializeUnrecognizedElement(String elementName, XmlReader reader) { 
            bool handled = false; // 
            if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                if (elementName == _addElement) {
                    ConfigurationElement elem = CallCreateNewElement();
                    elem.ResetLockLists(this);
                    elem.DeserializeElement(reader, false); 
                    BaseAdd(elem);
                    handled = true; 
                } 
                else if (elementName == _removeElement) {
                    ConfigurationElement elem = CallCreateNewElement(); 
                    elem.ResetLockLists(this);
                    elem.DeserializeElement(reader, true);
                    if (IsElementRemovable(elem) == true) {
                        BaseRemove(GetElementKeyInternal(elem), false); 
                    }
 
                    handled = true; 
                }
                else if (elementName == _clearElement) { 
                    if (reader.AttributeCount > 0) {
                        while (reader.MoveToNextAttribute()) {
                            String propertyName = reader.Name;
                            throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_unrecognized_attribute, propertyName), reader); 
                        }
                    } 
                    CheckLockedElement(elementName, reader); 
                    reader.MoveToElement();
                    BaseClear(); // 
                    bEmitClearTag = true;
                    handled = true;
                }
            } 
            else if (elementName == ElementName) {
                if (BaseConfigurationRecord.IsReservedAttributeName(elementName)) { 
                    throw new ArgumentException(SR.GetString(SR.Basicmap_item_name_reserved, elementName)); 
                }
                ConfigurationElement elem = CallCreateNewElement(); 
                elem.ResetLockLists(this);
                elem.DeserializeElement(reader, false);
                BaseAdd(elem);
 
                handled = true;
            } 
            else if (IsElementName(elementName)) {   // this section handle the collection like the allow deny senario which 
                if (BaseConfigurationRecord.IsReservedAttributeName(elementName)) {
                    throw new ArgumentException(SR.GetString(SR.Basicmap_item_name_reserved, elementName)); 
                }
                // have multiple tags for the collection
                ConfigurationElement elem = CallCreateNewElement(elementName);
                elem.ResetLockLists(this); 
                elem.DeserializeElement(reader, false);
                BaseAdd(-1, elem); 
                handled = true; 
            }
            return handled; 
        }

        private ConfigurationElement CallCreateNewElement(string elementName) {
            ConfigurationElement elem = CreateNewElement(elementName); 
            elem.AssociateContext(_configRecord);
            elem.CallInit(); 
            return elem; 
        }
 
        private ConfigurationElement CallCreateNewElement() {
            ConfigurationElement elem = CreateNewElement();
            elem.AssociateContext(_configRecord);
            elem.CallInit(); 
            return elem;
        } 
 
        protected virtual ConfigurationElement CreateNewElement(string elementName) {
            return CreateNewElement(); 
        }
        protected abstract ConfigurationElement CreateNewElement();
        protected abstract Object GetElementKey(ConfigurationElement element);
        internal Object GetElementKeyInternal(ConfigurationElement element) { 
            Object key = GetElementKey(element);
            if (key == null) 
                throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_invalid_element_key)); 
            return key;
        } 

        protected virtual bool IsElementRemovable(ConfigurationElement element) {
            return true;
        } 

        private bool CompareKeys(Object key1, Object key2) { 
            if (_comparer != null) { 
                return (_comparer.Compare(key1, key2) == 0);
            } 
            else {
                return key1.Equals(key2);
            }
        } 

        protected virtual String ElementName { 
            get { 
                return "";
            } 
        }

        protected virtual bool IsElementName(string elementName) {
            return false; 
        }
 
        internal bool IsLockableElement(string elementName) { 
            if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                return (elementName == AddElementName ||
                        elementName == RemoveElementName ||
                        elementName == ClearElementName);
            } 
            else {
                return (elementName == ElementName) || IsElementName(elementName); 
            } 
        }
 
        internal string LockableElements {
            get {
                if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap ||
                    CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 

                    string ElementNames = "'" + AddElementName + "'"; // Must have an add 
                    if (RemoveElementName.Length != 0) 
                        ElementNames += ", '" + RemoveElementName + "'";
                    if (ClearElementName.Length != 0) 
                        ElementNames += ", '" + ClearElementName + "'";
                    return ElementNames;
                }
                else { 
                    if (!String.IsNullOrEmpty(ElementName)) {
                        return "'" + ElementName + "'"; 
                    } 
                    return String.Empty;
                } 
            }
        }

        protected virtual bool ThrowOnDuplicate { 
            get {
                if (CollectionType == ConfigurationElementCollectionType.AddRemoveClearMap || 
                    CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate) { 
                    return true;
                } 
                return false;
            }
        }
 
        public virtual ConfigurationElementCollectionType CollectionType {
            get { 
                return ConfigurationElementCollectionType.AddRemoveClearMap; 
            }
        } 

        private enum EntryType {
            Inherited,
            Replaced, 
            Removed,
            Added, 
        } 

        private class Entry { 

            internal EntryType _entryType;
            internal Object _key;
            internal ConfigurationElement _value; 

            internal Object GetKey(ConfigurationElementCollection ThisCollection) { 
                // For items that have been really inserted... 
                if (_value != null) {
                    return ThisCollection.GetElementKeyInternal(_value); 
                }
                else {
                    return _key; // These are items that only have been removed
                } 

            } 
 
            internal Entry(EntryType type, Object key, ConfigurationElement value) {
                _entryType = type; 
                _key = key;
                _value = value;
            }
        } 

        private class Enumerator : IDictionaryEnumerator { 
 
            private IEnumerator _itemsEnumerator;
            private DictionaryEntry _current = new DictionaryEntry(); 
            private ConfigurationElementCollection ThisCollection;


            internal Enumerator(ArrayList items, ConfigurationElementCollection collection) { 
                _itemsEnumerator = items.GetEnumerator();
                ThisCollection = collection; 
            } 

            bool IEnumerator.MoveNext() { 
                while (_itemsEnumerator.MoveNext()) {
                    Entry entry = (Entry)_itemsEnumerator.Current;
                    if (entry._entryType != EntryType.Removed) {
                        _current.Key = (entry.GetKey(ThisCollection) != null) ? entry.GetKey(ThisCollection) : "key"; 
                        _current.Value = entry._value;
                        return true; 
                    } 
                }
                return false; 
            }

            void IEnumerator.Reset() {
                _itemsEnumerator.Reset(); 
            }
 
            Object IEnumerator.Current { 
                get {
                    return _current.Value; 
                }
            }

            DictionaryEntry IDictionaryEnumerator.Entry { 
                get {
                    return _current; 
                } 
            }
 
            Object IDictionaryEnumerator.Key {
                get {
                    return _current.Key;
                } 
            }
 
            Object IDictionaryEnumerator.Value { 
                get {
                    return _current.Value; 
                }
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK