2010-01-09 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Configuration / System.Configuration / ConfigurationElementCollection.cs
index 319eae20b68ef6e13b5ed2044eeba821e2c33cd6..db98f4c4067d25ffe4617febe9cbdcfd4d3c0504 100644 (file)
@@ -38,7 +38,7 @@ using System.Xml;
 namespace System.Configuration 
 {
        [DebuggerDisplayAttribute ("Count = {Count}")]
-       public abstract class ConfigurationElementCollection : ConfigurationElement, ICollection, IEnumerable
+       public abstract partial class ConfigurationElementCollection : ConfigurationElement, ICollection, IEnumerable
        {
                ArrayList list = new ArrayList ();
                ArrayList removed;
@@ -66,8 +66,10 @@ namespace System.Configuration
                internal override void InitFromProperty (PropertyInformation propertyInfo)
                {
                        ConfigurationCollectionAttribute colat = propertyInfo.Property.CollectionAttribute;
+       
                        if (colat == null)
-                               colat = ElementMap.GetMap (GetType ()).CollectionAttribute;
+                               colat = Attribute.GetCustomAttribute (propertyInfo.Type, typeof (ConfigurationCollectionAttribute)) as ConfigurationCollectionAttribute;
+
                        if (colat != null) {
                                addElementName = colat.AddItemName;
                                clearElementName = colat.ClearItemsName;
@@ -80,7 +82,7 @@ namespace System.Configuration
 
                #region Properties
                
-               protected virtual ConfigurationElementCollectionType CollectionType {
+               public virtual ConfigurationElementCollectionType CollectionType {
                        get { return ConfigurationElementCollectionType.AddRemoveClearMap; }
                }
                
@@ -98,7 +100,7 @@ namespace System.Configuration
                        }
                }
 
-               public virtual int Count {
+               public int Count {
                        get { return list.Count; }
                }
 
@@ -120,7 +122,13 @@ namespace System.Configuration
                }
 
                protected virtual bool ThrowOnDuplicate {
-                       get { return true; }
+                       get {
+                               if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap &&
+                                   CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate)
+                                       return false;
+                               
+                               return true;
+                       }
                }
                
                protected internal string AddElementName {
@@ -147,10 +155,8 @@ namespace System.Configuration
                        BaseAdd (element, ThrowOnDuplicate);
                }
 
-               protected virtual void BaseAdd (ConfigurationElement element, bool throwIfExists)
+               protected void BaseAdd (ConfigurationElement element, bool throwIfExists)
                {
-//                     if (throwIfExists && BaseIndexOf (element) != -1)
-//                             throw new ConfigurationException ("Duplicate element in collection");
                        if (IsReadOnly ())
                                throw new ConfigurationErrorsException ("Collection is read only.");
                        
@@ -158,15 +164,25 @@ namespace System.Configuration
                                list.Insert (inheritedLimitIndex, element);
                                inheritedLimitIndex++;
                        }
-                       else
+                       else {
+                               int old_index = IndexOfKey (GetElementKey (element));
+                               if (old_index >= 0) {
+                                       if (element.Equals (list [old_index]))
+                                               return;
+                                       if (throwIfExists)
+                                               throw new ConfigurationException ("Duplicate element in collection");
+                                       list.RemoveAt (old_index);
+                               }
                                list.Add (element);
+                       }
+
                        modified = true;
                }
 
                protected virtual void BaseAdd (int index, ConfigurationElement element)
                {
-//                     if (ThrowOnDuplicate && BaseIndexOf (element) != -1)
-//                             throw new ConfigurationException ("Duplicate element in collection");
+                       if (ThrowOnDuplicate && BaseIndexOf (element) != -1)
+                               throw new ConfigurationException ("Duplicate element in collection");
                        if (IsReadOnly ())
                                throw new ConfigurationErrorsException ("Collection is read only.");
                        
@@ -174,7 +190,7 @@ namespace System.Configuration
                                throw new ConfigurationErrorsException ("Can't insert new elements below the inherited elements.");
                        if (!IsAlternate && (index <= inheritedLimitIndex))
                                throw new ConfigurationErrorsException ("Can't insert new elements above the inherited elements.");
-                               
+                       
                        list.Insert (index, element);
                        modified = true;
                }
@@ -210,6 +226,9 @@ namespace System.Configuration
 
                protected internal object BaseGetKey (int index)
                {
+                       if (index < 0 || index >= list.Count)
+                               throw new ConfigurationErrorsException (String.Format ("Index {0} is out of range", index));
+
                        return GetElementKey ((ConfigurationElement) list[index]).ToString ();
                }
 
@@ -346,6 +365,12 @@ namespace System.Configuration
                        return modified;
                }
 
+               [MonoTODO]
+               public override bool IsReadOnly ()
+               {
+                       return base.IsReadOnly ();
+               }
+
                internal override bool HasValues ()
                {
                        return list.Count > 0;
@@ -359,7 +384,7 @@ namespace System.Configuration
                        for (int n=0; n<parent.Count; n++)
                        {
                                ConfigurationElement parentItem = parent.BaseGet (n);
-                               ConfigurationElement item = CreateNewElementInternal (parentItem.GetType().FullName);
+                               ConfigurationElement item = CreateNewElementInternal (null);
                                item.Reset (parentItem);
                                BaseAdd (item);
                                
@@ -381,6 +406,12 @@ namespace System.Configuration
                        modified = false;
                }
 
+               [MonoTODO]
+               protected internal override void SetReadOnly ()
+               {
+                       base.SetReadOnly ();
+               }
+
                protected internal override bool SerializeElement (XmlWriter writer, bool serializeCollectionKey)
                {
                        if (serializeCollectionKey) {
@@ -445,8 +476,11 @@ namespace System.Configuration
                        }
                        else {
                                if (elementName == clearElementName) {
-                                       ConfigurationElement elem = CreateNewElementInternal (null);
-                                       elem.DeserializeElement (reader, true);
+                                       reader.MoveToContent ();
+                                       if (reader.MoveToNextAttribute ())
+                                               throw new ConfigurationErrorsException ("Unrecognized attribute '" + reader.LocalName + "'.");
+                                       reader.MoveToElement ();
+                                       reader.Skip ();
                                        BaseClear ();
                                        emitClear = true;
                                        modified = false;
@@ -454,8 +488,9 @@ namespace System.Configuration
                                }
                                else if (elementName == removeElementName) {
                                        ConfigurationElement elem = CreateNewElementInternal (null);
-                                       elem.DeserializeElement (reader, true);
-                                       BaseRemove (GetElementKey (elem));
+                                       ConfigurationRemoveElement removeElem = new ConfigurationRemoveElement (elem, this);
+                                       removeElem.DeserializeElement (reader, true);
+                                       BaseRemove (removeElem.KeyValue);
                                        modified = false;
                                        return true;
                                }
@@ -481,13 +516,13 @@ namespace System.Configuration
                                object key = source.GetElementKey (sitem);
                                ConfigurationElement pitem = parent != null ? parent.BaseGet (key) as ConfigurationElement : null;
                                if (pitem != null && updateMode != ConfigurationSaveMode.Full) {
-                                       ConfigurationElement nitem = CreateNewElementInternal (pitem.GetType().FullName);
+                                       ConfigurationElement nitem = CreateNewElementInternal (null);
                                        nitem.Unmerge (sitem, pitem, ConfigurationSaveMode.Minimal);
                                        if (nitem.HasValues ())
                                                BaseAdd (nitem);
                                }
                                else {
-                                       ConfigurationElement nitem = CreateNewElementInternal (sitem.GetType().FullName);
+                                       ConfigurationElement nitem = CreateNewElementInternal (null);
                                        nitem.Unmerge (sitem, null, ConfigurationSaveMode.Full);
                                        BaseAdd (nitem);
                                }