+2004-11-09 Lluis Sanchez Gual <lluis@novell.com>
+
+ * ConfigurationElement.cs: Implemented Equals and GetHashCode.
+ Only reflect properties from type's members if the type does not
+ override Properties.
+ * ConfigurationElementCollection.cs: Implemented Equals and GetHashCode.
+ Other minor fixes.
+ * ConfigurationProperty.cs: It is not a subclass of ConfigurationElement.
+ * NonEmptyStringConfigurationProperty.cs, NonEmptyStringFlags.cs:
+ Implemented.
+
2004-11-09 Lluis Sanchez Gual <lluis@novell.com>
* AppSettingsSection.cs: Mostly implemented (missing support for
string rawXml;
bool modified;
ElementMap map;
+ ConfigurationPropertyCollection keyProps;
protected ConfigurationElement ()
{
- map = GetMap (GetType());
}
internal string RawXml {
protected internal virtual ConfigurationPropertyCollection CollectionKeyProperties {
get {
- return map.KeyProperties;
+ return null;
}
}
+
+ internal ConfigurationPropertyCollection GetKeyProperties ()
+ {
+ if (keyProps != null) return keyProps;
+ keyProps = CollectionKeyProperties;
+ if (keyProps != null) return keyProps;
+
+ if (map.Properties == Properties)
+ keyProps = map.KeyProperties;
+ else {
+ keyProps = new ConfigurationPropertyCollection ();
+ foreach (ConfigurationProperty prop in Properties) {
+ if (prop.IsKey)
+ keyProps.Add (prop);
+ }
+ }
+ return keyProps;
+ }
protected internal object this [ConfigurationProperty property] {
get {
protected internal object this [string property_name] {
get {
- ConfigurationProperty prop = map.Properties [property_name];
+ ConfigurationProperty prop = Properties [property_name];
if (prop == null) throw new InvalidOperationException ("Property '" + property_name + "' not found in configuration section");
return this [prop];
}
set {
- ConfigurationProperty prop = map.Properties [property_name];
+ ConfigurationProperty prop = Properties [property_name];
if (prop == null) throw new InvalidOperationException ("Property '" + property_name + "' not found in configuration section");
this [prop] = value;
}
protected internal virtual ConfigurationPropertyCollection Properties {
get {
+ if (map == null)
+ map = GetMap (GetType());
return map.Properties;
}
}
- [MonoTODO]
public override bool Equals (object compareTo)
{
- return base.Equals (compareTo);
+ ConfigurationElement other = compareTo as ConfigurationElement;
+ if (other == null) return false;
+ if (GetType() != other.GetType()) return false;
+
+ foreach (ConfigurationProperty prop in Properties) {
+ if (!object.Equals (this [prop], other [prop]))
+ return false;
+ }
+ return true;
}
- [MonoTODO]
public override int GetHashCode ()
{
- return base.GetHashCode ();
+ int code = 0;
+ foreach (ConfigurationProperty prop in Properties)
+ code += this [prop].GetHashCode ();
+ return code;
}
public bool HasValue (string key)
{
if (values == null) return false;
- ConfigurationProperty prop = map.Properties [key];
+ ConfigurationProperty prop = Properties [key];
if (prop == null) return false;
return values.ContainsKey (prop);
}
- internal bool HasValues ()
+ internal virtual bool HasValues ()
{
return values != null && values.Count > 0;
}
Hashtable readProps = new Hashtable ();
reader.MoveToContent ();
- if (!map.HasProperties) {
- reader.Skip ();
- return;
- }
-
while (reader.MoveToNextAttribute ())
{
- ConfigurationProperty prop = map.Properties [reader.LocalName];
+ ConfigurationProperty prop = Properties [reader.LocalName];
if (prop == null || (serializeCollectionKey && !prop.IsKey)) {
if (!HandleUnrecognizedAttribute (reader.LocalName, reader.Value))
throw new ConfigurationException ("Unrecognized attribute '" + reader.LocalName + "'.");
continue;
}
- if (readProps.Contains (prop))
+ if (readProps.ContainsKey (prop))
throw new ConfigurationException ("The attribute '" + prop.Name + "' may only appear once in this element.");
object val = prop.ConvertFromString (reader.Value);
continue;
}
- ConfigurationProperty prop = map.Properties [reader.LocalName];
+ ConfigurationProperty prop = Properties [reader.LocalName];
if (prop == null || (serializeCollectionKey && !prop.IsKey)) {
if (!HandleUnrecognizedElement (reader.LocalName, reader))
throw new ConfigurationException ("Unrecognized element '" + reader.LocalName + "'.");
protected internal virtual void Reset (ConfigurationElement parentElement, object context)
{
if (parentElement != null) {
- if (!map.HasProperties) return;
values = null;
- foreach (ConfigurationProperty prop in map.Properties) {
+ foreach (ConfigurationProperty prop in Properties) {
if (parentElement.HasValue (prop.Name)) {
if (prop.IsElement) {
ConfigurationElement parentValue = parentElement [prop.Name] as ConfigurationElement;
[MonoTODO ("Return value?")]
protected internal virtual bool Serialize (XmlWriter writer, bool serializeCollectionKey)
{
- if (values == null || !map.HasProperties) return true;
+ if (values == null) return true;
+
+ if (serializeCollectionKey) {
+ foreach (ConfigurationProperty prop in GetKeyProperties ())
+ writer.WriteAttributeString (prop.Name, prop.ConvertToString (this[prop]));
+ return true;
+ }
ArrayList elems = new ArrayList ();
foreach (DictionaryEntry entry in values)
{
ConfigurationProperty prop = (ConfigurationProperty) entry.Key;
- if (serializeCollectionKey && !prop.IsKey) continue;
if (prop.IsElement) continue;
if (!object.Equals (entry.Value, prop.DefaultValue))
writer.WriteAttributeString (prop.Name, prop.ConvertToString (entry.Value));
}
- if (serializeCollectionKey) return true;
foreach (DictionaryEntry entry in values)
{
bool serializeCollectionKey, object context,
ConfigurationUpdateMode updateMode)
{
- if (source.map != parent.map)
+ if (source.GetType() != parent.GetType())
throw new ConfigurationException ("Can't unmerge two elements of different type");
- ElementMap map = source.map;
- if (!map.HasProperties) return;
-
- foreach (ConfigurationProperty prop in map.Properties)
+ foreach (ConfigurationProperty prop in source.Properties)
{
if (!source.HasValue (prop.Name)) continue;
object sourceValue = source [prop];
- if (!parent.HasValue (prop.Name) || updateMode == ConfigurationUpdateMode.Full) {
+ if (!parent.HasValue (prop.Name)) {
this [prop] = sourceValue;
continue;
}
}
else {
if (!object.Equals (sourceValue, parentValue) ||
+ (updateMode == ConfigurationUpdateMode.Full) ||
(updateMode == ConfigurationUpdateMode.Modified && source.IsReadFromConfig (prop.Name)))
this [prop] = sourceValue;
}
lock (elementMaps) {
ElementMap map = elementMaps [t] as ElementMap;
if (map != null) return map;
-
- if (typeof(ConfigurationElementCollection).IsAssignableFrom (t))
- map = new CollectionElementMap (t);
- else
- map = new ElementMap (t);
+ map = new ElementMap (t);
elementMaps [t] = map;
return map;
}
}
}
}
-
- internal class CollectionElementMap: ElementMap
- {
- public CollectionElementMap (Type t): base (t)
- {
- }
- }
}
#endif
protected virtual void BaseAdd (ConfigurationElement element, bool throwIfExists)
{
- if (throwIfExists && BaseIndexOf (element) != -1)
- throw new ConfigurationException ("Duplicate element in collection");
+// if (throwIfExists && BaseIndexOf (element) != -1)
+// throw new ConfigurationException ("Duplicate element in collection");
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");
list.Insert (index, element);
modified = true;
}
return CreateNewElement ();
}
- [MonoTODO]
public override bool Equals (object compareTo)
{
- return base.Equals (compareTo);
+ ConfigurationElementCollection other = compareTo as ConfigurationElementCollection;
+ if (other == null) return false;
+ if (GetType() != other.GetType()) return false;
+ if (Count != other.Count) return false;
+
+ for (int n=0; n<Count; n++) {
+ if (!BaseGet (n).Equals (other.BaseGet (n)))
+ return false;
+ }
+ return true;
}
-
protected abstract object GetElementKey (ConfigurationElement element);
- [MonoTODO]
public override int GetHashCode ()
{
- return base.GetHashCode ();
+ int code = 0;
+ for (int n=0; n<Count; n++)
+ code += BaseGet (n).GetHashCode ();
+ return code;
}
void ICollection.CopyTo (Array arr, int index)
return modified;
}
+ internal override bool HasValues ()
+ {
+ return list.Count > 0;
+ }
+
[MonoTODO ("parentItem.GetType().Name ??")]
protected internal override void Reset (ConfigurationElement parentElement, object context)
{
[MonoTODO ("Support for BasicMap. Return value.")]
protected internal override bool Serialize (XmlWriter writer, bool serializeCollectionKey)
{
+ if (serializeCollectionKey) {
+ return base.Serialize (writer, serializeCollectionKey);
+ }
+
if (emitClear)
writer.WriteElementString ("clear","");
{
if (elementName == "clear") {
BaseClear ();
+ emitClear = true;
modified = false;
return true;
}
if (updateMode == ConfigurationUpdateMode.Full)
EmitClear = true;
+ else {
+ for (int n=0; n<parent.Count; n++) {
+ ConfigurationElement pitem = parent.BaseGet (n);
+ object key = parent.GetElementKey (pitem);
+ if (source.IndexOfKey (key) == -1) {
+ if (removed == null) removed = new ArrayList ();
+ removed.Add (pitem);
+ }
+ }
+ }
}
#endregion // Methods
namespace System.Configuration
{
- public class ConfigurationProperty : ConfigurationElement
+ public class ConfigurationProperty
{
string name;
Type type;
--- /dev/null
+//
+// System.Configuration.NonEmptyStringConfigurationProperty.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+
+#if NET_2_0
+using System;
+
+namespace System.Configuration
+{
+ public sealed class NonEmptyStringConfigurationProperty : ConfigurationProperty
+ {
+ NonEmptyStringFlags stringFlags;
+
+ public NonEmptyStringConfigurationProperty (string name, string defaultValue, ConfigurationPropertyFlags flags)
+ : base (name, typeof(string), defaultValue, flags)
+ {
+ }
+
+ public NonEmptyStringConfigurationProperty (string name, string defaultValue, ConfigurationPropertyFlags flags, NonEmptyStringFlags nonEmptyStringFlags)
+ : base (name, typeof(string), defaultValue, flags)
+ {
+ stringFlags = nonEmptyStringFlags;
+ }
+
+ protected internal override object ConvertFromString (string value)
+ {
+ return Check (value);
+ }
+
+ protected internal override string ConvertToString (object value)
+ {
+ return Check (value as string);
+ }
+
+ string Check (string s)
+ {
+ if (s == string.Empty || s == null)
+ throw new ConfigurationException ("The property '" + Name + "' can't be empty");
+
+ if (stringFlags == NonEmptyStringFlags.TrimWhitespace)
+ return s.Trim ();
+ else
+ return s;
+ }
+ }
+}
+#endif
--- /dev/null
+//
+// System.Configuration.NonEmptyStringFlags.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+
+#if NET_2_0
+
+namespace System.Configuration
+{
+ public enum NonEmptyStringFlags
+ {
+ None,
+ TrimWhitespace
+ }
+}
+#endif