Merge pull request #4621 from alexanderkyte/strdup_env
[mono.git] / mcs / class / System.Configuration / System.Configuration / ConfigurationElementCollection.cs
index ceff8e0b27f3e10df81a657c0537e168dcc02e61..c5a87877276f5cfd6de8e2f343b7fd986a4ca21b 100644 (file)
@@ -3,8 +3,10 @@
 //
 // Authors:
 //     Tim Coleman (tim@timcoleman.com)
+//     Martin Baulig <martin.baulig@xamarin.com>
 //
 // Copyright (C) Tim Coleman, 2004
+// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
 
 //
 // Permission is hereby granted, free of charge, to any person obtaining
@@ -29,8 +31,6 @@
 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
 //
 
-#if NET_2_0
-
 using System.Collections;
 using System.Diagnostics;
 using System.Xml;
@@ -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;
@@ -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 {
@@ -149,28 +157,32 @@ namespace System.Configuration
 
                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.");
                        
-                       int old_index = IndexOfKey (GetElementKey (element));
                        if (IsAlternate) {
                                list.Insert (inheritedLimitIndex, element);
                                inheritedLimitIndex++;
                        }
                        else {
+                               int old_index = IndexOfKey (GetElementKey (element));
+                               if (old_index >= 0) {
+                                       if (element.Equals (list [old_index]))
+                                               return;
+                                       if (throwIfExists)
+                                               throw new ConfigurationErrorsException ("Duplicate element in collection");
+                                       list.RemoveAt (old_index);
+                               }
                                list.Add (element);
                        }
-                       if (!IsAlternate && old_index != -1)
-                               list.RemoveAt (old_index);
+
                        modified = true;
                }
 
                protected virtual void BaseAdd (int index, ConfigurationElement element)
                {
                        if (ThrowOnDuplicate && BaseIndexOf (element) != -1)
-                               throw new ConfigurationException ("Duplicate element in collection");
+                               throw new ConfigurationErrorsException ("Duplicate element in collection");
                        if (IsReadOnly ())
                                throw new ConfigurationErrorsException ("Collection is read only.");
                        
@@ -270,6 +282,12 @@ namespace System.Configuration
                                throw new ConfigurationErrorsException ("Inherited items can't be removed.");
                        
                        list.RemoveAt (index);
+                       
+                       if (IsAlternate) {
+                               if (inheritedLimitIndex > 0)
+                                       inheritedLimitIndex--;
+                       }
+
                        modified = true;
                }
 
@@ -350,6 +368,17 @@ namespace System.Configuration
 
                protected internal override bool IsModified ()
                {
+                       if (modified)
+                               return true;
+
+                       for (int n=0; n<list.Count; n++) {
+                               ConfigurationElement elem = (ConfigurationElement) list [n];
+                               if (!elem.IsModified ())
+                                       continue;
+                               modified = true;
+                               break;
+                       }
+
                        return modified;
                }
 
@@ -359,9 +388,37 @@ namespace System.Configuration
                        return base.IsReadOnly ();
                }
 
-               internal override bool HasValues ()
+               internal override void PrepareSave (ConfigurationElement parentElement, ConfigurationSaveMode mode)
+               {
+                       var parent = (ConfigurationElementCollection)parentElement;
+                       base.PrepareSave (parentElement, mode);
+
+                       for (int n=0; n<list.Count; n++) {
+                               ConfigurationElement elem = (ConfigurationElement) list [n];
+                               object key = GetElementKey (elem);
+                               ConfigurationElement pitem = parent != null ? parent.BaseGet (key) as ConfigurationElement : null;
+
+                               elem.PrepareSave (pitem, mode);
+                       }
+               }
+
+               internal override bool HasValues (ConfigurationElement parentElement, ConfigurationSaveMode mode)
                {
-                       return list.Count > 0;
+                       var parent = (ConfigurationElementCollection)parentElement;
+
+                       if (mode == ConfigurationSaveMode.Full)
+                               return list.Count > 0;
+
+                       for (int n=0; n<list.Count; n++) {
+                               ConfigurationElement elem = (ConfigurationElement) list [n];
+                               object key = GetElementKey (elem);
+                               ConfigurationElement pitem = parent != null ? parent.BaseGet (key) as ConfigurationElement : null;
+
+                               if (elem.HasValues (pitem, mode))
+                                       return true;
+                       }
+
+                       return false;
                }
 
                protected internal override void Reset (ConfigurationElement parentElement)
@@ -392,6 +449,10 @@ namespace System.Configuration
                protected internal override void ResetModified ()
                {
                        modified = false;
+                       for (int n=0; n<list.Count; n++) {
+                               ConfigurationElement elem = (ConfigurationElement) list [n];
+                               elem.ResetModified ();
+                       }
                }
 
                [MonoTODO]
@@ -475,9 +536,10 @@ namespace System.Configuration
                                        return true;
                                }
                                else if (elementName == removeElementName) {
-                                       ConfigurationElement elem = CreateNewElementInternal (removeElementName);
-                                       elem.DeserializeElement (reader, true);
-                                       BaseRemove (GetElementKey (elem));
+                                       ConfigurationElement elem = CreateNewElementInternal (null);
+                                       ConfigurationRemoveElement removeElem = new ConfigurationRemoveElement (elem, this);
+                                       removeElem.DeserializeElement (reader, true);
+                                       BaseRemove (removeElem.KeyValue);
                                        modified = false;
                                        return true;
                                }
@@ -493,7 +555,7 @@ namespace System.Configuration
                        return false;
                }
                
-               protected internal override void Unmerge (ConfigurationElement sourceElement, ConfigurationElement parentElement, ConfigurationSaveMode updateMode)
+               protected internal override void Unmerge (ConfigurationElement sourceElement, ConfigurationElement parentElement, ConfigurationSaveMode saveMode)
                {
                        ConfigurationElementCollection source = (ConfigurationElementCollection) sourceElement;
                        ConfigurationElementCollection parent = (ConfigurationElementCollection) parentElement;
@@ -502,20 +564,18 @@ namespace System.Configuration
                                ConfigurationElement sitem = source.BaseGet (n);
                                object key = source.GetElementKey (sitem);
                                ConfigurationElement pitem = parent != null ? parent.BaseGet (key) as ConfigurationElement : null;
-                               if (pitem != null && updateMode != ConfigurationSaveMode.Full) {
-                                       ConfigurationElement nitem = CreateNewElementInternal (null);
-                                       nitem.Unmerge (sitem, pitem, ConfigurationSaveMode.Minimal);
-                                       if (nitem.HasValues ())
+                               ConfigurationElement nitem = CreateNewElementInternal (null);
+                               if (pitem != null && saveMode != ConfigurationSaveMode.Full) {
+                                       nitem.Unmerge (sitem, pitem, saveMode);
+                                       if (nitem.HasValues (pitem, saveMode))
                                                BaseAdd (nitem);
-                               }
-                               else {
-                                       ConfigurationElement nitem = CreateNewElementInternal (null);
+                               } else {
                                        nitem.Unmerge (sitem, null, ConfigurationSaveMode.Full);
                                        BaseAdd (nitem);
                                }
                        }
                        
-                       if (updateMode == ConfigurationSaveMode.Full)
+                       if (saveMode == ConfigurationSaveMode.Full)
                                EmitClear = true;
                        else if (parent != null) {
                                for (int n=0; n<parent.Count; n++) {
@@ -533,4 +593,3 @@ namespace System.Configuration
         }
 }
 
-#endif