diff --git a/src/Spring/Spring.Core/Collections/HybridSet.cs b/src/Spring/Spring.Core/Collections/HybridSet.cs index b9a6237d..d95e3d10 100644 --- a/src/Spring/Spring.Core/Collections/HybridSet.cs +++ b/src/Spring/Spring.Core/Collections/HybridSet.cs @@ -57,9 +57,18 @@ namespace Spring.Collections public HybridSet() { InternalDictionary = new HybridDictionary(); - } + } + + /// + /// Initializes a new instance of the class with a given capacity + /// + /// The size. + public HybridSet(int size) + { + InternalDictionary = new HybridDictionary(size); + } - /// + /// /// Creates a new set instance based on either a list or a hash table, /// depending on which will be more efficient based on the data-set /// size, and initializes it based on a collection of elements. diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ManagedDictionary.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ManagedDictionary.cs index 4583497e..ca8bb81c 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/ManagedDictionary.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/ManagedDictionary.cs @@ -1,171 +1,238 @@ -#region License - -/* - * Copyright © 2002-2005 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#endregion - -#region Imports - -using System; -using System.Collections; -#if NET_2_0 -using System.Collections.Generic; -#endif -using System.Collections.Specialized; -using System.Globalization; - -using Spring.Core; -using Spring.Core.TypeConversion; -using Spring.Core.TypeResolution; +#region License + +/* + * Copyright © 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; +using System.Collections; +#if NET_2_0 +using System.Collections.Generic; +#endif +using System.Collections.Specialized; +using System.Globalization; + +using Spring.Core; +using Spring.Core.TypeConversion; +using Spring.Core.TypeResolution; using Spring.Objects.Factory.Config; -using Spring.Util; - -#endregion - -namespace Spring.Objects.Factory.Support -{ - /// - /// Tag subclass used to hold a dictionary of managed elements. - /// - /// Juergen Hoeller - /// Rick Evans (.NET) - [Serializable] - public class ManagedDictionary : Hashtable, IManagedCollection - { - private string keyTypeName; - private string valueTypeName; - - /// - /// Gets or sets the unresolved name for the - /// of the keys of this managed dictionary. - /// - /// The unresolved name for the type of the keys of this managed dictionary. - public string KeyTypeName - { - get { return this.keyTypeName; } - set { this.keyTypeName = value; } - } - - /// - /// Gets or sets the unresolved name for the - /// of the values of this managed dictionary. - /// - /// The unresolved name for the type of the values of this managed dictionary. - public string ValueTypeName - { - get { return this.valueTypeName; } - set { this.valueTypeName = value; } - } - - /// - /// Resolves this managed collection at runtime. - /// - /// - /// The name of the top level object that is having the value of one of it's - /// collection properties resolved. - /// - /// - /// The definition of the named top level object. - /// - /// - /// The name of the property the value of which is being resolved. - /// - /// - /// The callback that will actually do the donkey work of resolving - /// this managed collection. - /// - /// A fully resolved collection. - public ICollection Resolve( - string objectName, IObjectDefinition definition, - string propertyName, ManagedCollectionElementResolver resolver) - { - IDictionary dictionary; - - Type keyType = null; - if (StringUtils.HasText(this.keyTypeName)) - { - keyType = TypeResolutionUtils.ResolveType(this.keyTypeName); - } - - Type valueType = null; - if (StringUtils.HasText(this.valueTypeName)) - { - valueType = TypeResolutionUtils.ResolveType(this.valueTypeName); - } -#if NET_2_0 - if ((keyType == null) && (valueType == null)) - { - dictionary = new HybridDictionary(); - } - else - { - Type type = typeof(Dictionary<,>); - Type[] genericArgs = new Type[2] { - (keyType == null) ? typeof(object) : keyType, - (valueType == null) ? typeof(object) : valueType }; - type = type.MakeGenericType(genericArgs); - - dictionary = (IDictionary)ObjectUtils.InstantiateType(type); - } -#else - dictionary = new HybridDictionary(); -#endif - foreach (object key in this.Keys) - { - string elementName = string.Format(CultureInfo.InvariantCulture, "{0}[{1}]", propertyName, key); - object resolvedKey = resolver(objectName, definition, elementName, key); - object resolvedValue = resolver(objectName, definition, elementName, this[key]); - - if (keyType != null) - { - try - { - resolvedKey = TypeConversionUtils.ConvertValueIfNecessary(keyType, resolvedKey, propertyName); - } - catch (TypeMismatchException) - { - throw new TypeMismatchException( - String.Format( - "Unable to convert managed dictionary key '{0}' from [{1}] into [{2}] during initialization" - + " of property '{3}' for object '{4}'. Do you have an appropriate type converter registered?", - resolvedKey, resolvedKey.GetType(), keyType, propertyName, objectName)); - } - } - - if (valueType != null) - { - try - { - resolvedValue = TypeConversionUtils.ConvertValueIfNecessary(valueType, resolvedValue, propertyName + "[" + resolvedKey + "]"); - } - catch (TypeMismatchException) - { - throw new TypeMismatchException( - String.Format( - "Unable to convert managed dictionary value '{0}' from [{1}] into [{2}] during initialization" - + " of property '{3}' for object '{4}'. Do you have an appropriate type converter registered?", - resolvedValue, resolvedValue.GetType(), valueType, propertyName, objectName)); - } - } - - dictionary.Add(resolvedKey, resolvedValue); - } - - return dictionary; - } - } +using Spring.Util; + +#endregion + +namespace Spring.Objects.Factory.Support +{ + /// + /// Tag subclass used to hold a dictionary of managed elements. + /// + /// Juergen Hoeller + /// Rick Evans (.NET) + [Serializable] + public class ManagedDictionary : Hashtable, IManagedCollection, IMergable + { + private string keyTypeName; + private string valueTypeName; + private bool mergeEnabled; + + /// + /// Initializes a new, empty instance of the class using the default initial capacity, load factor, hash code provider, and comparer. + /// + public ManagedDictionary() + { + } + + /// + /// Initializes a new, empty instance of the class using the specified initial capacity, and the default load factor, hash code provider, and comparer. + /// + /// The approximate number of elements that the object can initially contain. is less than zero. + public ManagedDictionary(int capacity) : base(capacity) + { + } + + /// + /// Gets or sets the unresolved name for the + /// of the keys of this managed dictionary. + /// + /// The unresolved name for the type of the keys of this managed dictionary. + public string KeyTypeName + { + get { return this.keyTypeName; } + set { this.keyTypeName = value; } + } + + /// + /// Gets or sets the unresolved name for the + /// of the values of this managed dictionary. + /// + /// The unresolved name for the type of the values of this managed dictionary. + public string ValueTypeName + { + get { return this.valueTypeName; } + set { this.valueTypeName = value; } + } + + /// + /// Resolves this managed collection at runtime. + /// + /// + /// The name of the top level object that is having the value of one of it's + /// collection properties resolved. + /// + /// + /// The definition of the named top level object. + /// + /// + /// The name of the property the value of which is being resolved. + /// + /// + /// The callback that will actually do the donkey work of resolving + /// this managed collection. + /// + /// A fully resolved collection. + public ICollection Resolve( + string objectName, IObjectDefinition definition, + string propertyName, ManagedCollectionElementResolver resolver) + { + IDictionary dictionary; + + Type keyType = null; + if (StringUtils.HasText(this.keyTypeName)) + { + keyType = TypeResolutionUtils.ResolveType(this.keyTypeName); + } + + Type valueType = null; + if (StringUtils.HasText(this.valueTypeName)) + { + valueType = TypeResolutionUtils.ResolveType(this.valueTypeName); + } +#if NET_2_0 + if ((keyType == null) && (valueType == null)) + { + dictionary = new HybridDictionary(); + } + else + { + Type type = typeof(Dictionary<,>); + Type[] genericArgs = new Type[2] { + (keyType == null) ? typeof(object) : keyType, + (valueType == null) ? typeof(object) : valueType }; + type = type.MakeGenericType(genericArgs); + + dictionary = (IDictionary)ObjectUtils.InstantiateType(type); + } +#else + dictionary = new HybridDictionary(); +#endif + foreach (object key in this.Keys) + { + string elementName = string.Format(CultureInfo.InvariantCulture, "{0}[{1}]", propertyName, key); + object resolvedKey = resolver(objectName, definition, elementName, key); + object resolvedValue = resolver(objectName, definition, elementName, this[key]); + + if (keyType != null) + { + try + { + resolvedKey = TypeConversionUtils.ConvertValueIfNecessary(keyType, resolvedKey, propertyName); + } + catch (TypeMismatchException) + { + throw new TypeMismatchException( + String.Format( + "Unable to convert managed dictionary key '{0}' from [{1}] into [{2}] during initialization" + + " of property '{3}' for object '{4}'. Do you have an appropriate type converter registered?", + resolvedKey, resolvedKey.GetType(), keyType, propertyName, objectName)); + } + } + + if (valueType != null) + { + try + { + resolvedValue = TypeConversionUtils.ConvertValueIfNecessary(valueType, resolvedValue, propertyName + "[" + resolvedKey + "]"); + } + catch (TypeMismatchException) + { + throw new TypeMismatchException( + String.Format( + "Unable to convert managed dictionary value '{0}' from [{1}] into [{2}] during initialization" + + " of property '{3}' for object '{4}'. Do you have an appropriate type converter registered?", + resolvedValue, resolvedValue.GetType(), valueType, propertyName, objectName)); + } + } + + dictionary.Add(resolvedKey, resolvedValue); + } + + return dictionary; + } + + /// + /// Gets a value indicating whether this instance is merge enabled for this instance + /// + /// + /// true if this instance is merge enabled; otherwise, false. + /// + public bool MergeEnabled + { + get { return this.mergeEnabled; } + set { this.mergeEnabled = value; } + } + + /// + /// Merges the current value set with that of the supplied object. + /// + /// The supplied object is considered the parent, and values in the + /// callee's value set must override those of the supplied object. + /// + /// The parent object to merge with + /// The result of the merge operation + /// If the supplied parent is null + /// If merging is not enabled for this instance, + /// (i.e. MergeEnabled equals false. + public object Merge(object parent) + { + if (!this.mergeEnabled) + { + throw new InvalidOperationException( + "Not allowed to merge when the 'MergeEnabled' property is set to 'false'"); + } + if (parent == null) + { + return this; + } + IDictionary pDict = parent as IDictionary; + if (pDict == null) + { + throw new InvalidOperationException("Cannot merge with object of type [" + parent.GetType() + "]"); + } + IDictionary merged = new ManagedDictionary(); + foreach (DictionaryEntry dictionaryEntry in pDict) + { + merged[dictionaryEntry.Key] = dictionaryEntry.Value; + } + foreach (DictionaryEntry entry in this) + { + merged[entry.Key] = entry.Value; + } + return merged; + } + } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ManagedList.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ManagedList.cs index 89aeeb45..c253a975 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/ManagedList.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/ManagedList.cs @@ -1,134 +1,203 @@ -#region License - -/* - * Copyright © 2002-2005 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#endregion - -#region Imports - -using System; -using System.Collections; -#if NET_2_0 -using System.Collections.Generic; -#endif -using System.Globalization; - -using Spring.Core; -using Spring.Core.TypeConversion; -using Spring.Core.TypeResolution; +#region License + +/* + * Copyright © 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; +using System.Collections; +#if NET_2_0 +using System.Collections.Generic; +#endif +using System.Globalization; + +using Spring.Core; +using Spring.Core.TypeConversion; +using Spring.Core.TypeResolution; using Spring.Objects.Factory.Config; -using Spring.Util; - -#endregion - -namespace Spring.Objects.Factory.Support -{ - /// - /// Tag subclass used to hold a list of managed elements. - /// - /// Rod Johnson - /// Rick Evans (.NET) - [Serializable] - public class ManagedList : ArrayList, IManagedCollection - { - private string elementTypeName; - - /// - /// Gets or sets the unresolved name for the - /// of the elements of this managed list. - /// - /// The unresolved name for the type of the elements of this managed list. - public string ElementTypeName - { - get { return this.elementTypeName; } - set { this.elementTypeName = value; } - } - - /// - /// Resolves this managed collection at runtime. - /// - /// - /// The name of the top level object that is having the value of one of it's - /// collection properties resolved. - /// - /// - /// The definition of the named top level object. - /// - /// - /// The name of the property the value of which is being resolved. - /// - /// - /// The callback that will actually do the donkey work of resolving - /// this managed collection. - /// - /// A fully resolved collection. - public ICollection Resolve(string objectName, IObjectDefinition definition, string propertyName, ManagedCollectionElementResolver resolver) - { - IList list; - - Type elementType = null; - if (StringUtils.HasText(this.elementTypeName)) - { - elementType = TypeResolutionUtils.ResolveType(this.elementTypeName); - } -#if NET_2_0 - if (elementType == null) - { - list = new ArrayList(); - } - else - { - // CLOVER:ON - Type type = typeof(List<>); - Type[] genericArgs = new Type[1] { elementType }; - type = type.MakeGenericType(genericArgs); - - list = (IList)ObjectUtils.InstantiateType(type); - // CLOVER:OFF - } -#else - list = new ArrayList(); -#endif - for (int i = 0; i < Count; ++i) - { - object element = this[i]; - object resolvedElement = - resolver(objectName, definition, String.Format(CultureInfo.InvariantCulture, "{0}[{1}]", propertyName, i), element); - - if (elementType != null) - { - try - { - resolvedElement = TypeConversionUtils.ConvertValueIfNecessary(elementType, resolvedElement, propertyName + "[" + i + "]"); - } - catch (TypeMismatchException) - { - throw new TypeMismatchException( - String.Format( - "Unable to convert managed list element '{0}' from [{1}] into [{2}] during initialization" - + " of property '{3}' for object '{4}'. Do you have an appropriate type converter registered?", - resolvedElement, resolvedElement.GetType(), elementType, propertyName, objectName)); - } - } - - list.Add(resolvedElement); - } - - return list; - } - } +using Spring.Util; + +#endregion + +namespace Spring.Objects.Factory.Support +{ + /// + /// Tag subclass used to hold a list of managed elements. + /// + /// Rod Johnson + /// Rick Evans (.NET) + [Serializable] + public class ManagedList : ArrayList, IManagedCollection, IMergable + { + private string elementTypeName; + private bool mergeEnabled; + + /// + /// Initializes a new instance of the ManagedList class that is empty and has the default initial capacity. + /// + public ManagedList() + { + } + + /// + /// Initializes a new instance of the ManagedList class that is empty and has the specified initial capacity. + /// + /// The number of elements that the new list can initially store. is less than zero. + public ManagedList(int capacity) + : base(capacity) + { + } + + + /// + /// Gets or sets the unresolved name for the + /// of the elements of this managed list. + /// + /// The unresolved name for the type of the elements of this managed list. + public string ElementTypeName + { + get { return this.elementTypeName; } + set { this.elementTypeName = value; } + } + + /// + /// Resolves this managed collection at runtime. + /// + /// + /// The name of the top level object that is having the value of one of it's + /// collection properties resolved. + /// + /// + /// The definition of the named top level object. + /// + /// + /// The name of the property the value of which is being resolved. + /// + /// + /// The callback that will actually do the donkey work of resolving + /// this managed collection. + /// + /// A fully resolved collection. + public ICollection Resolve(string objectName, IObjectDefinition definition, string propertyName, ManagedCollectionElementResolver resolver) + { + IList list; + + Type elementType = null; + if (StringUtils.HasText(this.elementTypeName)) + { + elementType = TypeResolutionUtils.ResolveType(this.elementTypeName); + } +#if NET_2_0 + if (elementType == null) + { + list = new ArrayList(); + } + else + { + // CLOVER:ON + Type type = typeof(List<>); + Type[] genericArgs = new Type[1] { elementType }; + type = type.MakeGenericType(genericArgs); + + list = (IList)ObjectUtils.InstantiateType(type); + // CLOVER:OFF + } +#else + list = new ArrayList(); +#endif + for (int i = 0; i < Count; ++i) + { + object element = this[i]; + object resolvedElement = + resolver(objectName, definition, String.Format(CultureInfo.InvariantCulture, "{0}[{1}]", propertyName, i), element); + + if (elementType != null) + { + try + { + resolvedElement = TypeConversionUtils.ConvertValueIfNecessary(elementType, resolvedElement, propertyName + "[" + i + "]"); + } + catch (TypeMismatchException) + { + throw new TypeMismatchException( + String.Format( + "Unable to convert managed list element '{0}' from [{1}] into [{2}] during initialization" + + " of property '{3}' for object '{4}'. Do you have an appropriate type converter registered?", + resolvedElement, resolvedElement.GetType(), elementType, propertyName, objectName)); + } + } + + list.Add(resolvedElement); + } + + return list; + } + + /// + /// Gets a value indicating whether this instance is merge enabled for this instance + /// + /// + /// true if this instance is merge enabled; otherwise, false. + /// + public bool MergeEnabled + { + get { return this.mergeEnabled; } + set { this.mergeEnabled = value; } + } + + /// + /// Merges the current value set with that of the supplied object. + /// + /// The supplied object is considered the parent, and values in the + /// callee's value set must override those of the supplied object. + /// + /// The parent object to merge with + /// The result of the merge operation + /// If the supplied parent is null + /// If merging is not enabled for this instance, + /// (i.e. MergeEnabled equals false. + public object Merge(object parent) + { + if (!this.mergeEnabled) + { + throw new InvalidOperationException( + "Not allowed to merge when the 'MergeEnabled' property is set to 'false'"); + } + if (parent == null) + { + return this; + } + IList plist = parent as IList; + if (plist == null) + { + throw new InvalidOperationException("Cannot merge with object of type [" + parent.GetType() + "]"); + } + IList merged = new ManagedList(); + foreach (object element in plist) + { + merged.Add(element); + } + foreach (object o in this) + { + merged.Add(o); + } + return merged; + } + } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ManagedNameValueCollection.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ManagedNameValueCollection.cs new file mode 100644 index 00000000..fa68adee --- /dev/null +++ b/src/Spring/Spring.Core/Objects/Factory/Support/ManagedNameValueCollection.cs @@ -0,0 +1,101 @@ +#region License + +/* + * Copyright © 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +using System; +using System.Collections; +using System.Collections.Specialized; + +namespace Spring.Objects.Factory.Support +{ + /// + /// Tag class which represent a Spring-managed instance that + /// supports merging of parent/child definitions. + /// + public class ManagedNameValueCollection: NameValueCollection, IMergable + { + private bool mergeEnabled; + + /// + /// Initializes a new instance of the class that is empty, has the default initial capacity and uses the default case-insensitive hash code provider and the default case-insensitive comparer. + /// + public ManagedNameValueCollection() + { + } + + /// + /// Initializes a new instance of the class that is empty, has the specified initial capacity and uses the default case-insensitive hash code provider and the default case-insensitive comparer. + /// + /// The initial number of entries that the can contain. is less than zero. + public ManagedNameValueCollection(int capacity) : base(capacity) + { + } + + /// + /// Gets a value indicating whether this instance is merge enabled for this instance + /// + /// + /// true if this instance is merge enabled; otherwise, false. + /// + public bool MergeEnabled + { + get { return this.mergeEnabled; } + set { this.mergeEnabled = value; } + } + + /// + /// Merges the current value set with that of the supplied object. + /// + /// The supplied object is considered the parent, and values in the + /// callee's value set must override those of the supplied object. + /// + /// The parent object to merge with + /// The result of the merge operation + /// If the supplied parent is null + /// If merging is not enabled for this instance, + /// (i.e. MergeEnabled equals false. + public object Merge(object parent) + { + if (!this.mergeEnabled) + { + throw new InvalidOperationException( + "Not allowed to merge when the 'MergeEnabled' property is set to 'false'"); + } + if (parent == null) + { + return this; + } + NameValueCollection pDict = parent as NameValueCollection; + if (pDict == null) + { + throw new InvalidOperationException("Cannot merge with object of type [" + parent.GetType() + "]"); + } + NameValueCollection merged = new ManagedNameValueCollection(); + foreach (string s in pDict.AllKeys) + { + merged[s] = pDict.Get(s); + } + foreach (string s in this.AllKeys) + { + merged[s] = this.Get(s); + } + return merged; + } + } +} \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ManagedSet.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ManagedSet.cs index 7641de59..5f2d4e77 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/ManagedSet.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/ManagedSet.cs @@ -40,10 +40,30 @@ namespace Spring.Objects.Factory.Support /// Juergen Hoeller /// Rick Evans (.NET) [Serializable] - public class ManagedSet : HybridSet, IManagedCollection + public class ManagedSet : HybridSet, IManagedCollection, IMergable { - private string elementTypeName; + private string elementTypeName; + + private bool mergeEnabled; + + /// + /// Creates a new set instance based on either a list or a hash table, + /// depending on which will be more efficient based on the data-set + /// size. + /// + public ManagedSet() + { + } + + /// + /// Initializes a new instance of the class with a given capacity + /// + /// The size. + public ManagedSet(int size) : base(size) + { + } + /// /// Gets or sets the unresolved name for the /// of the elements of this managed set. @@ -108,6 +128,57 @@ namespace Spring.Objects.Factory.Support } return set; - } + } + + /// + /// Gets a value indicating whether this instance is merge enabled for this instance + /// + /// + /// true if this instance is merge enabled; otherwise, false. + /// + public bool MergeEnabled + { + get { return this.mergeEnabled; } + set { this.mergeEnabled = value; } + } + + /// + /// Merges the current value set with that of the supplied object. + /// + /// The supplied object is considered the parent, and values in the + /// callee's value set must override those of the supplied object. + /// + /// The parent object to merge with + /// The result of the merge operation + /// If the supplied parent is null + /// If merging is not enabled for this instance, + /// (i.e. MergeEnabled equals false. + public object Merge(object parent) + { + if (!this.mergeEnabled) + { + throw new InvalidOperationException( + "Not allowed to merge when the 'MergeEnabled' property is set to 'false'"); + } + if (parent == null) + { + return this; + } + ISet pSet = parent as ISet; + if (pSet == null) + { + throw new InvalidOperationException("Cannot merge with object of type [" + parent.GetType() + "]"); + } + ISet merged = new ManagedSet(); + foreach (object element in pSet) + { + merged.Add(element); + } + foreach (object o in this) + { + merged.Add(o); + } + return merged; + } } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/DocumentDefaultsDefinition.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/DocumentDefaultsDefinition.cs index 12df0f32..1a4f3532 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/DocumentDefaultsDefinition.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/DocumentDefaultsDefinition.cs @@ -31,7 +31,8 @@ namespace Spring.Objects.Factory.Xml { private string autowire; private string dependencyCheck; - private string lazyInit; + private string lazyInit; + private string merge; /// /// Gets or sets the autowire setting for the document that's currently parsed. @@ -61,6 +62,16 @@ namespace Spring.Objects.Factory.Xml { get { return lazyInit; } set { lazyInit = value; } + } + + /// + /// Gets or sets the merge setting for the document that's currently parsed. + /// + /// The merge. + public string Merge + { + get { return merge; } + set { merge = value; } } } } diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionConstants.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionConstants.cs index 20855dc0..f0920b49 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionConstants.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionConstants.cs @@ -88,7 +88,13 @@ namespace Spring.Objects.Factory.Xml /// /// Specifies the default autowire mode. /// - public const string DefaultAutowireAttribute = "default-autowire"; + public const string DefaultAutowireAttribute = "default-autowire"; + + /// + /// Specifies the default collection merge mode. + /// + public const string DefaultMergeAttribute = "default-merge"; + /// /// Defines a single named object. @@ -585,7 +591,12 @@ namespace Spring.Objects.Factory.Xml /// Shortcut alternative to specifying a value element in a /// dictionary entry element with <ref object="..."/>. /// - public const string DictionaryValueRefShortcutAttribute = "value-ref"; + public const string DictionaryValueRefShortcutAttribute = "value-ref"; + + /// + /// Specify if the collection values should be merged with the parent. + /// + public const string MergeAttribute = "merge"; /// /// The string of characters that delimit object names. diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs index 22c080e5..4f5ab5b2 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs @@ -161,6 +161,20 @@ namespace Spring.Objects.Factory.Xml #endregion + ddd.Merge = GetAttributeValue(root, ObjectDefinitionConstants.DefaultMergeAttribute); + + #region Instrumentation + + if (log.IsDebugEnabled) + { + log.Debug( + string.Format( + "Default merge '{0}'.", + ddd.Merge)); + } + + #endregion + defaults = ddd; } diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs index c21db336..c0b9ce8f 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs @@ -62,7 +62,7 @@ namespace Spring.Objects.Factory.Xml NamespaceParser( Namespace = "http://www.springframework.net", SchemaLocationAssemblyHint = typeof(ObjectsNamespaceParser), - SchemaLocation = "/Spring.Objects.Factory.Xml/spring-objects-1.1.xsd" + SchemaLocation = "/Spring.Objects.Factory.Xml/spring-objects-1.3.xsd" ) ] // [Obsolete("ObjectsNamespaceParser will be dropped with 2.x, use ObjectDefinitionParserHelper instead", false)] @@ -93,20 +93,20 @@ namespace Spring.Objects.Factory.Xml #endregion - /// - /// Parse the specified XmlElement and register the resulting - /// ObjectDefinitions with the IObjectDefinitionRegistry - /// embedded in the supplied - /// - /// The element to be parsed. - /// TThe object encapsulating the current state of the parsing process. - /// Provides access to a IObjectDefinitionRegistry - /// The primary object definition. - /// - ///

- /// This method is never invoked if the parser is namespace aware - /// and was called to process the root node. - ///

+ /// + /// Parse the specified XmlElement and register the resulting + /// ObjectDefinitions with the IObjectDefinitionRegistry + /// embedded in the supplied + /// + /// The element to be parsed. + /// TThe object encapsulating the current state of the parsing process. + /// Provides access to a IObjectDefinitionRegistry + /// The primary object definition. + /// + ///

+ /// This method is never invoked if the parser is namespace aware + /// and was called to process the root node. + ///

///
// [Obsolete("not used anymore - ObjectsNamespaceParser will be dropped with 2.x, use ObjectDefinitionParserHelper instead", false)] public override IObjectDefinition ParseElement(XmlElement element, ParserContext parserContext) @@ -895,7 +895,7 @@ namespace Spring.Objects.Factory.Xml } case ObjectDefinitionConstants.NameValuesElement: { - return ParseNameValueCollectionElement(element, name); + return ParseNameValueCollectionElement(element, name, parserContext); } case ObjectDefinitionConstants.ValueElement: { @@ -1026,7 +1026,7 @@ namespace Spring.Objects.Factory.Xml /// /// Gets a list definition. /// - /// + /// /// The element describing the list definition. /// /// @@ -1036,31 +1036,43 @@ namespace Spring.Objects.Factory.Xml /// The namespace-aware parser. /// /// The list definition. - protected virtual IList ParseListElement(XmlElement element, string name, ParserContext parserContext) + protected virtual IList ParseListElement(XmlElement collectionEle, string name, ParserContext parserContext) { - ManagedList list = new ManagedList(); + string elementTypeName = GetAttributeValue(collectionEle, "element-type"); + XmlNodeList nl = collectionEle.ChildNodes; + ManagedList target = new ManagedList(nl.Count); - string elementTypeName = GetAttributeValue(element, "element-type"); if (StringUtils.HasText(elementTypeName)) { - list.ElementTypeName = elementTypeName; + target.ElementTypeName = elementTypeName; } + target.MergeEnabled = ParseMergeAttribute(collectionEle, parserContext.ParserHelper); - foreach (XmlNode node in element.ChildNodes) + foreach (XmlNode node in collectionEle.ChildNodes) { XmlElement ele = node as XmlElement; if (ele != null) { - list.Add(ParsePropertySubElement(ele, name, parserContext)); + target.Add(ParsePropertySubElement(ele, name, parserContext)); } } - return list; + return target; + } + + private bool ParseMergeAttribute(XmlElement collectionElement, ObjectDefinitionParserHelper helper) + { + string val = collectionElement.GetAttribute(ObjectDefinitionConstants.MergeAttribute); + if (ObjectDefinitionConstants.DefaultValue.Equals(val)) + { + val = helper.Defaults.Merge; + } + return ObjectDefinitionConstants.TrueValue.Equals(val); } /// /// Gets a set definition. /// - /// + /// /// The element describing the set definition. /// /// @@ -1070,44 +1082,42 @@ namespace Spring.Objects.Factory.Xml /// The namespace-aware parser. /// /// The set definition. - protected Set ParseSetElement(XmlElement element, string name, ParserContext parserContext) - { - ManagedSet theSet = new ManagedSet(); - string elementTypeName = GetAttributeValue(element, "element-type"); + protected Set ParseSetElement(XmlElement collectionEle, string name, ParserContext parserContext) + { + string elementTypeName = GetAttributeValue(collectionEle, "element-type"); + XmlNodeList nl = collectionEle.ChildNodes; + ManagedSet target = new ManagedSet(nl.Count); + if (StringUtils.HasText(elementTypeName)) { - theSet.ElementTypeName = elementTypeName; + target.ElementTypeName = elementTypeName; } - foreach (XmlNode node in element.ChildNodes) + target.MergeEnabled = ParseMergeAttribute(collectionEle, parserContext.ParserHelper); + + foreach (XmlNode node in collectionEle.ChildNodes) { XmlElement ele = node as XmlElement; if (ele != null) { object sub = ParsePropertySubElement(ele, name, parserContext); - theSet.Add(sub); + target.Add(sub); } } - return theSet; + return target; } /// /// Gets a dictionary definition. /// - /// - /// The element describing the dictionary definition. - /// - /// - /// The name of the object (definition) associated with the dictionary definition. - /// - /// - /// The namespace-aware parser. - /// + /// The element describing the dictionary definition. + /// The name of the object (definition) associated with the dictionary definition. + /// The namespace-aware parser. /// The dictionary definition. - protected IDictionary ParseDictionaryElement(XmlElement element, string name, ParserContext parserContext) + protected IDictionary ParseDictionaryElement(XmlElement mapEle, string name, ParserContext parserContext) { ManagedDictionary dictionary = new ManagedDictionary(); - string keyTypeName = GetAttributeValue(element, "key-type"); - string valueTypeName = GetAttributeValue(element, "value-type"); + string keyTypeName = GetAttributeValue(mapEle, "key-type"); + string valueTypeName = GetAttributeValue(mapEle, "value-type"); if (StringUtils.HasText(keyTypeName)) { dictionary.KeyTypeName = keyTypeName; @@ -1116,8 +1126,9 @@ namespace Spring.Objects.Factory.Xml { dictionary.ValueTypeName = valueTypeName; } + dictionary.MergeEnabled = ParseMergeAttribute(mapEle, parserContext.ParserHelper); - XmlNodeList entryElements = SelectNodes(element, ObjectDefinitionConstants.EntryElement); + XmlNodeList entryElements = SelectNodes(mapEle, ObjectDefinitionConstants.EntryElement); foreach (XmlElement entryEle in entryElements) { #region Key @@ -1274,7 +1285,7 @@ namespace Spring.Objects.Factory.Xml /// /// Gets a name value collection mapping definition. /// - /// + /// /// The element describing the name value collection mapping definition. /// /// @@ -1282,10 +1293,12 @@ namespace Spring.Objects.Factory.Xml /// name value collection mapping definition. /// /// The name value collection definition. - protected NameValueCollection ParseNameValueCollectionElement(XmlElement element, string name) + protected NameValueCollection ParseNameValueCollectionElement(XmlElement nameValueEle, string name, ParserContext parserContext) { - NameValueCollection nvc = new NameValueCollection(); - XmlNodeList addElements = element.GetElementsByTagName(ObjectDefinitionConstants.AddElement); + ManagedNameValueCollection nvc = new ManagedNameValueCollection(); + nvc.MergeEnabled = ParseMergeAttribute(nameValueEle, parserContext.ParserHelper); + + XmlNodeList addElements = nameValueEle.GetElementsByTagName(ObjectDefinitionConstants.AddElement); foreach (XmlElement addElement in addElements) { string key = GetAttributeValue(addElement, ObjectDefinitionConstants.KeyAttribute); diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ReplacedMethodOverride.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ReplacedMethodOverride.cs similarity index 100% rename from src/Spring/Spring.Core/Objects/Factory/Support/ReplacedMethodOverride.cs rename to src/Spring/Spring.Core/Objects/Factory/Xml/ReplacedMethodOverride.cs diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-1.3.xsd b/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-1.3.xsd new file mode 100644 index 00000000..41c1eee9 --- /dev/null +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-1.3.xsd @@ -0,0 +1,550 @@ + + + + + + + + + + + + + + + + + + + + + + + Defines a base type for any required string. Defines a string with a minimum length of 0 + + + + + + + + + Element containing informative text describing the purpose of the enclosing + element. Always optional. + Used primarily for user documentation of XML object definition documents. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Import an external file containing object definitions into this file. + + + + + + Defines an additional alias name for an object definition. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines constructor argument. + + + + + + + + + + + + + + + + Defines property. + + + + + + + + + + + + Defines a single named object. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The document root. At least one object definition is required. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-1.3.xsx b/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-1.3.xsx new file mode 100644 index 00000000..d79bfd40 --- /dev/null +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/spring-objects-1.3.xsx @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + <_x0028_group1_x0029__XmlChoice left="7243" top="43376" width="5292" height="3757" selected="0" zOrder="15" index="1" expanded="1"> + + + + + <_x0028_group1_x0029__XmlChoice left="19095" top="39111" width="5292" height="3757" selected="0" zOrder="25" index="1" expanded="0" /> + + + <_x0028_group1_x0029__XmlChoice left="19095" top="43376" width="5292" height="3757" selected="0" zOrder="29" index="1" expanded="0" /> + + + + + + + + + + + + + + + + + + + + + <_x0028_group1_x0029__XmlChoice left="7243" top="90291" width="5292" height="3757" selected="0" zOrder="53" index="1" expanded="0" /> + + + + <_x0028_group1_x0029__XmlChoice left="7243" top="98821" width="5292" height="3757" selected="0" zOrder="57" index="1" expanded="0" /> + + + <_x0028_group1_x0029__XmlChoice left="7243" top="103086" width="5292" height="3757" selected="0" zOrder="60" index="1" expanded="0" /> + + + + + + + + + + + + + <_x0028_scope_x0029__XmlSimpleType left="13169" top="128676" width="5292" height="3757" selected="0" zOrder="79" index="0" expanded="1" /> + + + <_x0028_lazy-init_x0029__XmlSimpleType left="13169" top="132941" width="5292" height="3757" selected="0" zOrder="83" index="0" expanded="1" /> + + + <_x0028_autowire_x0029__XmlSimpleType left="13169" top="137206" width="5292" height="3757" selected="0" zOrder="87" index="0" expanded="1" /> + + + <_x0028_dependency-check_x0029__XmlSimpleType left="13169" top="141471" width="5292" height="3757" selected="0" zOrder="91" index="0" expanded="1" /> + + + + <_x0028_group1_x0029__XmlChoice left="7243" top="150001" width="5292" height="3757" selected="0" zOrder="94" index="1" expanded="1"> + + + + + + <_x0028_default-dependency-check_x0029__XmlSimpleType left="13169" top="158531" width="5292" height="3757" selected="0" zOrder="104" index="0" expanded="1" /> + + + <_x0028_default-autowire_x0029__XmlSimpleType left="13169" top="162796" width="5292" height="3757" selected="0" zOrder="108" index="0" expanded="1" /> + + + \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/IMergable.cs b/src/Spring/Spring.Core/Objects/IMergable.cs new file mode 100644 index 00000000..bb6fe7da --- /dev/null +++ b/src/Spring/Spring.Core/Objects/IMergable.cs @@ -0,0 +1,55 @@ +#region License + +/* + * Copyright © 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +using System; + +namespace Spring.Objects +{ + /// + /// Interface representing an object whose value set can be merged with that of a parent object. + /// + /// Rob Harrop + /// Mark Pollack (.NET) + public interface IMergable + { + /// + /// Gets a value indicating whether this instance is merge enabled for this instance + /// + /// + /// true if this instance is merge enabled; otherwise, false. + /// + bool MergeEnabled { + get; + } + + /// + /// Merges the current value set with that of the supplied object. + /// + /// The supplied object is considered the parent, and values in the + /// callee's value set must override those of the supplied object. + /// + /// The parent object to merge with + /// The result of the merge operation + /// If the supplied parent is null + /// If merging is not enabled for this instance, + /// (i.e. MergeEnabled equals false. + object Merge(object parent); + } +} \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/MutablePropertyValues.cs b/src/Spring/Spring.Core/Objects/MutablePropertyValues.cs index df757c77..65d09d79 100644 --- a/src/Spring/Spring.Core/Objects/MutablePropertyValues.cs +++ b/src/Spring/Spring.Core/Objects/MutablePropertyValues.cs @@ -1,347 +1,371 @@ -#region License - -/* - * Copyright © 2002-2005 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#endregion - -#region Imports - -using System; -using System.Collections; -using System.Globalization; -using System.Text; -using Spring.Util; - -#endregion - -namespace Spring.Objects -{ - /// - /// Default implementation of the - /// interface. - /// - /// - ///

- /// Allows simple manipulation of properties, and provides constructors to - /// support deep copy and construction from a number of collection types such as - /// and - /// . - ///

- ///
- /// Rod Johnson - /// Mark Pollack (.NET) - /// Rick Evans (.NET) - [Serializable] - public class MutablePropertyValues : IPropertyValues - { - #region Fields - - /// - /// The list of objects. - /// - private IList propertyValuesList = new ArrayList(); - - #endregion - - #region Constructor (s) / Destructor - - /// - /// Creates a new instance of the - /// class. - /// - /// - ///

- /// The returned instance is initially empty... - /// s can be added with the various - /// overloaded , - /// , - /// , - /// and - /// methods. - ///

- ///
- /// - /// - public MutablePropertyValues () - { - } - - /// - /// Creates a new instance of the - /// class. - /// - /// - ///

- /// Deep copy constructor. Guarantees - /// references are independent, although it can't deep copy objects currently - /// referenced by individual objects. - ///

- ///
- public MutablePropertyValues (IPropertyValues other) - { - if (other != null) - { - AddAll (other.PropertyValues); - } - } - - /// - /// Creates a new instance of the - /// class. - /// - /// - /// The with property values - /// keyed by property name, which must be a . - /// - public MutablePropertyValues (IDictionary map) - { - AddAll (map); - } - - #endregion - - #region Properties - - /// - /// Property to retrieve the array of property values. - /// - public PropertyValue[] PropertyValues - { - get { return (PropertyValue[]) ArrayList.Adapter (propertyValuesList).ToArray (typeof (PropertyValue)); } - } - - #endregion - - #region Methods - - /// - /// Overloaded version of Add that takes a property name and a property value. - /// - /// - /// The name of the property. - /// - /// - /// The value of the property. - /// - public void Add (string propertyName, object propertyValue) - { - Add (new PropertyValue (propertyName, propertyValue)); - } - - /// - /// Add the supplied object, - /// replacing any existing one for the respective property. - /// - /// - /// The object to add. - /// - public void Add (PropertyValue pv) - { - for (int i = 0; i < propertyValuesList.Count; ++i) - { - PropertyValue currentPv = (PropertyValue) propertyValuesList [i]; - if (currentPv.Name.Equals (pv.Name)) - { - propertyValuesList[i] = pv; - return ; - } - } - propertyValuesList.Add (pv); - } - - /// - /// Add all property values from the given - /// . - /// - /// - /// The map of property values, the keys of which must be - /// s. - /// - public void AddAll (IDictionary map) - { - if (map != null) - { - foreach (string key in map.Keys) - { - Add (new PropertyValue (key, map [key])); - } - } - } - - /// - /// Add all property values from the given - /// . - /// - /// - /// The list of s to be added. - /// - public void AddAll (IList values) - { - if (values != null) - { - foreach (PropertyValue value in values) - { - Add (value); - } - } - } - - /// - /// Remove the given , if contained. - /// - /// - /// The to remove. - /// - public void Remove (PropertyValue pv) - { - propertyValuesList.Remove (pv); - } - - /// - /// Removes the named , if contained. - /// - /// - /// The name of the property. - /// - public void Remove (string propertyName) - { - Remove (GetPropertyValue (propertyName)); - } - - /// - /// Modify a object held in this object. Indexed from 0. - /// - public void SetPropertyValueAt (PropertyValue pv, int i) - { - propertyValuesList [i] = pv; - } - - /// - /// Return the property value given the name. - /// - /// - /// The property name is checked in a case-insensitive fashion. - /// - /// - /// The name of the property. - /// - /// - /// The property value. - /// - public PropertyValue GetPropertyValue (string propertyName) - { - string propertyNameLowered = propertyName.ToLower (CultureInfo.CurrentCulture); - foreach (PropertyValue pv in propertyValuesList) - { - if (pv.Name.ToLower(CultureInfo.CurrentCulture).Equals (propertyNameLowered)) - { - return pv; - } - } - return null; - } - - /// - /// Does the container of properties contain one of this name. - /// - /// The name of the property to search for. - /// - /// True if the property is contained in this collection, false otherwise. - /// - public bool Contains (string propertyName) - { - return GetPropertyValue (propertyName) != null; - } - - /// - /// Return the difference (changes, additions, but not removals) of - /// property values between the supplied argument and the values - /// contained in the collection. - /// - /// Another property values collection. - /// - /// The collection of property values that are different than the supplied one. - /// - public IPropertyValues ChangesSince (IPropertyValues old) - { - MutablePropertyValues changes = new MutablePropertyValues (); - if (old == this) - { - return changes; - } - // for each property value in this (the newer set) - foreach (PropertyValue newProperty in propertyValuesList) - { - PropertyValue oldProperty = old.GetPropertyValue (newProperty.Name); - if (oldProperty == null) - { - // if there wasn't an old one, add it - changes.Add (newProperty); - } - else if (!oldProperty.Equals (newProperty)) - { - // it's changed - changes.Add (newProperty); - } - } - return changes; - } - - /// - /// Returns an that can iterate - /// through a collection. - /// - /// - ///

- /// The returned is the - /// exposed by the - /// - /// property. - ///

- ///
- /// - /// An that can iterate through a - /// collection. - /// - public IEnumerator GetEnumerator () - { - return PropertyValues.GetEnumerator (); - } - - // CLOVER:OFF - - /// - /// Convert the object to a string representation. - /// - /// - /// A string representation of the object. - /// - public override string ToString () - { - PropertyValue[] pvs = PropertyValues; - StringBuilder sb - = new StringBuilder ( - "MutablePropertyValues: length=").Append (pvs.Length).Append ("; "); - sb.Append (StringUtils.ArrayToDelimitedString (pvs, ",")); - return sb.ToString (); - } - - // CLOVER:ON - - #endregion - } +#region License + +/* + * Copyright © 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; +using System.Collections; +using System.Globalization; +using System.Text; +using Spring.Util; + +#endregion + +namespace Spring.Objects +{ + /// + /// Default implementation of the + /// interface. + /// + /// + ///

+ /// Allows simple manipulation of properties, and provides constructors to + /// support deep copy and construction from a number of collection types such as + /// and + /// . + ///

+ ///
+ /// Rod Johnson + /// Mark Pollack (.NET) + /// Rick Evans (.NET) + [Serializable] + public class MutablePropertyValues : IPropertyValues + { + #region Fields + + /// + /// The list of objects. + /// + private IList propertyValuesList = new ArrayList(); + + #endregion + + #region Constructor (s) / Destructor + + /// + /// Creates a new instance of the + /// class. + /// + /// + ///

+ /// The returned instance is initially empty... + /// s can be added with the various + /// overloaded , + /// , + /// , + /// and + /// methods. + ///

+ ///
+ /// + /// + public MutablePropertyValues () + { + } + + /// + /// Creates a new instance of the + /// class. + /// + /// + ///

+ /// Deep copy constructor. Guarantees + /// references are independent, although it can't deep copy objects currently + /// referenced by individual objects. + ///

+ ///
+ public MutablePropertyValues (IPropertyValues other) + { + if (other != null) + { + AddAll (other.PropertyValues); + } + } + + /// + /// Creates a new instance of the + /// class. + /// + /// + /// The with property values + /// keyed by property name, which must be a . + /// + public MutablePropertyValues (IDictionary map) + { + AddAll (map); + } + + #endregion + + #region Properties + + /// + /// Property to retrieve the array of property values. + /// + public PropertyValue[] PropertyValues + { + get { return (PropertyValue[]) ArrayList.Adapter (propertyValuesList).ToArray (typeof (PropertyValue)); } + } + + #endregion + + #region Methods + + /// + /// Overloaded version of Add that takes a property name and a property value. + /// + /// + /// The name of the property. + /// + /// + /// The value of the property. + /// + public void Add (string propertyName, object propertyValue) + { + Add (new PropertyValue (propertyName, propertyValue)); + } + + /// + /// Add the supplied object, + /// replacing any existing one for the respective property. + /// + /// + /// The object to add. + /// + public void Add (PropertyValue pv) + { + for (int i = 0; i < propertyValuesList.Count; ++i) + { + PropertyValue currentPv = (PropertyValue) propertyValuesList [i]; + if (currentPv.Name.Equals (pv.Name)) + { + pv = MergeIfRequired(pv, currentPv); + propertyValuesList[i] = pv; + return ; + } + } + propertyValuesList.Add (pv); + } + + /// + /// Merges the value of the supplied 'new' with that of + /// the current if merging is supported and enabled. + /// + /// + /// The new pv. + /// The current pv. + /// The possibly merged PropertyValue + private PropertyValue MergeIfRequired(PropertyValue newPv, PropertyValue currentPv) + { + object val = newPv.Value; + IMergable mergable = val as IMergable; + if (mergable != null) + { + if (mergable.MergeEnabled) + { + object merged = mergable.Merge(currentPv.Value); + return new PropertyValue(newPv.Name, merged); + } + } + return newPv; + } + + /// + /// Add all property values from the given + /// . + /// + /// + /// The map of property values, the keys of which must be + /// s. + /// + public void AddAll (IDictionary map) + { + if (map != null) + { + foreach (string key in map.Keys) + { + Add (new PropertyValue (key, map [key])); + } + } + } + + /// + /// Add all property values from the given + /// . + /// + /// + /// The list of s to be added. + /// + public void AddAll (IList values) + { + if (values != null) + { + foreach (PropertyValue value in values) + { + Add (value); + } + } + } + + /// + /// Remove the given , if contained. + /// + /// + /// The to remove. + /// + public void Remove (PropertyValue pv) + { + propertyValuesList.Remove (pv); + } + + /// + /// Removes the named , if contained. + /// + /// + /// The name of the property. + /// + public void Remove (string propertyName) + { + Remove (GetPropertyValue (propertyName)); + } + + /// + /// Modify a object held in this object. Indexed from 0. + /// + public void SetPropertyValueAt (PropertyValue pv, int i) + { + propertyValuesList [i] = pv; + } + + /// + /// Return the property value given the name. + /// + /// + /// The property name is checked in a case-insensitive fashion. + /// + /// + /// The name of the property. + /// + /// + /// The property value. + /// + public PropertyValue GetPropertyValue (string propertyName) + { + string propertyNameLowered = propertyName.ToLower (CultureInfo.CurrentCulture); + foreach (PropertyValue pv in propertyValuesList) + { + if (pv.Name.ToLower(CultureInfo.CurrentCulture).Equals (propertyNameLowered)) + { + return pv; + } + } + return null; + } + + /// + /// Does the container of properties contain one of this name. + /// + /// The name of the property to search for. + /// + /// True if the property is contained in this collection, false otherwise. + /// + public bool Contains (string propertyName) + { + return GetPropertyValue (propertyName) != null; + } + + /// + /// Return the difference (changes, additions, but not removals) of + /// property values between the supplied argument and the values + /// contained in the collection. + /// + /// Another property values collection. + /// + /// The collection of property values that are different than the supplied one. + /// + public IPropertyValues ChangesSince (IPropertyValues old) + { + MutablePropertyValues changes = new MutablePropertyValues (); + if (old == this) + { + return changes; + } + // for each property value in this (the newer set) + foreach (PropertyValue newProperty in propertyValuesList) + { + PropertyValue oldProperty = old.GetPropertyValue (newProperty.Name); + if (oldProperty == null) + { + // if there wasn't an old one, add it + changes.Add (newProperty); + } + else if (!oldProperty.Equals (newProperty)) + { + // it's changed + changes.Add (newProperty); + } + } + return changes; + } + + /// + /// Returns an that can iterate + /// through a collection. + /// + /// + ///

+ /// The returned is the + /// exposed by the + /// + /// property. + ///

+ ///
+ /// + /// An that can iterate through a + /// collection. + /// + public IEnumerator GetEnumerator () + { + return PropertyValues.GetEnumerator (); + } + + // CLOVER:OFF + + /// + /// Convert the object to a string representation. + /// + /// + /// A string representation of the object. + /// + public override string ToString () + { + PropertyValue[] pvs = PropertyValues; + StringBuilder sb + = new StringBuilder ( + "MutablePropertyValues: length=").Append (pvs.Length).Append ("; "); + sb.Append (StringUtils.ArrayToDelimitedString (pvs, ",")); + return sb.ToString (); + } + + // CLOVER:ON + + #endregion + } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Spring.Core.2008.csproj b/src/Spring/Spring.Core/Spring.Core.2008.csproj index bebc4b1d..e92ec427 100644 --- a/src/Spring/Spring.Core/Spring.Core.2008.csproj +++ b/src/Spring/Spring.Core/Spring.Core.2008.csproj @@ -1,7 +1,7 @@  Local - 9.0.30729 + 9.0.21022 2.0 {710961A3-0DF4-49E4-A26E-F5B9C044AC84} Debug @@ -672,7 +672,6 @@ - @@ -692,6 +691,7 @@ + @@ -710,6 +710,7 @@ + @@ -958,7 +959,7 @@ Code - + Code @@ -1196,6 +1197,7 @@ + diff --git a/test/Spring/Spring.Core.Tests/Data/Spring/Objects/Factory/Xml/collectionMerging.xml b/test/Spring/Spring.Core.Tests/Data/Spring/Objects/Factory/Xml/collectionMerging.xml new file mode 100644 index 00000000..910c627c --- /dev/null +++ b/test/Spring/Spring.Core.Tests/Data/Spring/Objects/Factory/Xml/collectionMerging.xml @@ -0,0 +1,75 @@ + + + + + + + + Rob Harrop + Rod Johnson + + + + + + + + Juergen Hoeller + + + + + + + + + Rob Harrop + + + + + + + + Sally Greenwood + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedDictionaryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedDictionaryTests.cs index c48f9808..c2862402 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedDictionaryTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedDictionaryTests.cs @@ -30,11 +30,77 @@ using Spring.Objects.Factory.Config; namespace Spring.Objects.Factory.Support { /// + /// Integration tests for ManagedDictionary /// /// Erich Eichinger + /// Mark Pollack [TestFixture] public class ManagedDictionaryTests { + [Test] + public void MergeSunnyDay() + { + ManagedDictionary parent = new ManagedDictionary(); + parent.Add("one", "one"); + parent.Add("two", "two"); + ManagedDictionary child = new ManagedDictionary(); + child.Add("three", "three"); + child.MergeEnabled = true; + IDictionary mergedList = (IDictionary)child.Merge(parent); + Assert.AreEqual(3, mergedList.Count); + } + + [Test] + public void MergeWithNullParent() + { + ManagedDictionary child = new ManagedDictionary(); + child.MergeEnabled = true; + Assert.AreSame(child, child.Merge(null)); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException), ExpectedMessage = @"Not allowed to merge when the 'MergeEnabled' property is set to 'false'")] + public void MergeNotAllowedWhenMergeNotEnabled() + { + ManagedDictionary child = new ManagedDictionary(); + child.Merge(null); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException))] + public void MergeWithNonCompatibleParentType() + { + ManagedDictionary child = new ManagedDictionary(); + child.MergeEnabled = true; + child.Merge("hello"); + } + + [Test] + public void MergeEmptyChild() + { + ManagedDictionary parent = new ManagedDictionary(); + parent.Add("one", "one"); + parent.Add("two", "two"); + ManagedDictionary child = new ManagedDictionary(); + child.MergeEnabled = true; + IDictionary mergedMap = (IDictionary)child.Merge(parent); + Assert.AreEqual(2, mergedMap.Count); + } + + [Test] + public void MergeChildValueOverrideTheParents() + { + ManagedDictionary parent = new ManagedDictionary(); + parent.Add("one", "one"); + parent.Add("two", "two"); + ManagedDictionary child = new ManagedDictionary(); + child.Add("one", "fork"); + child.MergeEnabled = true; + IDictionary mergedMap = (IDictionary)child.Merge(parent); + Assert.AreEqual(2, mergedMap.Count); + Assert.AreEqual("fork", mergedMap["one"]); + } + #if NET_2_0 internal class InternalType { diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedListTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedListTests.cs new file mode 100644 index 00000000..b9f1d83a --- /dev/null +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedListTests.cs @@ -0,0 +1,96 @@ +#region License + +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +using System; +using System.Collections; +using NUnit.Framework; + +namespace Spring.Objects.Factory.Support +{ + [TestFixture] + public class ManagedListTests + { + [Test] + public void MergeSunnyDay() + { + ManagedList parent = new ManagedList(); + parent.Add("one"); + parent.Add("two"); + ManagedList child = new ManagedList(); + child.Add("three"); + child.MergeEnabled = true; + IList mergedList = (IList) child.Merge(parent); + Assert.AreEqual(3, mergedList.Count); + } + + [Test] + public void MergeWithNullParent() + { + ManagedList child = new ManagedList(); + child.Add("one"); + child.MergeEnabled = true; + Assert.AreSame(child, child.Merge(null)); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException), ExpectedMessage = @"Not allowed to merge when the 'MergeEnabled' property is set to 'false'")] + public void MergeNotAllowedWhenMergeNotEnabled() + { + ManagedList child = new ManagedList(); + child.Merge(null); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException))] + public void MergeWithNonCompatibleParentType() + { + ManagedList child = new ManagedList(); + child.Add("one"); + child.MergeEnabled = true; + child.Merge("hello"); + } + + [Test] + public void MergeEmptyChild() + { + ManagedList parent = new ManagedList(); + parent.Add("one"); + parent.Add("two"); + ManagedList child = new ManagedList(); + child.MergeEnabled = true; + IList mergedList = (IList) child.Merge(parent); + Assert.AreEqual(2, mergedList.Count); + } + + [Test] + public void MergeChildValueOverrideTheParents() + { + //doesn't make much sense in the context of a list... + ManagedList parent = new ManagedList(); + parent.Add("one"); + parent.Add("two"); + ManagedList child = new ManagedList(); + child.Add("one"); + child.MergeEnabled = true; + IList mergedList = (IList) child.Merge(parent); + Assert.AreEqual(3, mergedList.Count); + } + } +} \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedNameValueCollectionTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedNameValueCollectionTests.cs new file mode 100644 index 00000000..c5819cfd --- /dev/null +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedNameValueCollectionTests.cs @@ -0,0 +1,99 @@ +#region License + +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +using System; +using System.Collections; +using System.Collections.Specialized; +using NUnit.Framework; + +namespace Spring.Objects.Factory.Support +{ + /// + /// Integration tests for ManagedNameValueCollectionTests + /// + /// Mark Pollack + [TestFixture] + public class ManagedNameValueCollectionTests + { + [Test] + public void MergeSunnyDay() + { + ManagedNameValueCollection parent = new ManagedNameValueCollection(); + parent.Add("one", "one"); + parent.Add("two", "two"); + ManagedNameValueCollection child = new ManagedNameValueCollection(); + child.Add("three", "three"); + child.MergeEnabled = true; + NameValueCollection mergedList = (NameValueCollection)child.Merge(parent); + Assert.AreEqual(3, mergedList.Count); + } + + [Test] + public void MergeWithNullParent() + { + ManagedNameValueCollection child = new ManagedNameValueCollection(); + child.MergeEnabled = true; + Assert.AreSame(child, child.Merge(null)); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException), ExpectedMessage = @"Not allowed to merge when the 'MergeEnabled' property is set to 'false'")] + public void MergeNotAllowedWhenMergeNotEnabled() + { + ManagedNameValueCollection child = new ManagedNameValueCollection(); + child.Merge(null); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException))] + public void MergeWithNonCompatibleParentType() + { + ManagedNameValueCollection child = new ManagedNameValueCollection(); + child.MergeEnabled = true; + child.Merge("hello"); + } + + [Test] + public void MergeEmptyChild() + { + ManagedNameValueCollection parent = new ManagedNameValueCollection(); + parent.Add("one", "one"); + parent.Add("two", "two"); + ManagedNameValueCollection child = new ManagedNameValueCollection(); + child.MergeEnabled = true; + NameValueCollection mergedMap = (NameValueCollection)child.Merge(parent); + Assert.AreEqual(2, mergedMap.Count); + } + + [Test] + public void MergeChildValueOverrideTheParents() + { + ManagedNameValueCollection parent = new ManagedNameValueCollection(); + parent.Add("one", "one"); + parent.Add("two", "two"); + ManagedNameValueCollection child = new ManagedNameValueCollection(); + child.Add("one", "fork"); + child.MergeEnabled = true; + NameValueCollection mergedMap = (NameValueCollection)child.Merge(parent); + Assert.AreEqual(2, mergedMap.Count); + Assert.AreEqual("fork", mergedMap["one"]); + } + } +} \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedSetTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedSetTests.cs new file mode 100644 index 00000000..ad3e62b7 --- /dev/null +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ManagedSetTests.cs @@ -0,0 +1,96 @@ +#region License + +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +using System; +using System.Collections; +using NUnit.Framework; +using Spring.Collections; + +namespace Spring.Objects.Factory.Support +{ + [TestFixture] + public class ManagedSetTests + { + [Test] + public void MergeSunnyDay() + { + ManagedSet parent = new ManagedSet(); + parent.Add("one"); + parent.Add("two"); + ManagedSet child = new ManagedSet(); + child.Add("three"); + child.MergeEnabled = true; + ISet mergedList = (ISet) child.Merge(parent); + Assert.AreEqual(3, mergedList.Count); + } + + [Test] + public void MergeWithNullParent() + { + ManagedSet child = new ManagedSet(); + child.Add("one"); + child.MergeEnabled = true; + Assert.AreSame(child, child.Merge(null)); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException), ExpectedMessage = @"Not allowed to merge when the 'MergeEnabled' property is set to 'false'")] + public void MergeNotAllowedWhenMergeNotEnabled() + { + ManagedSet child = new ManagedSet(); + child.Merge(null); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException))] + public void MergeWithNonCompatibleParentType() + { + ManagedSet child = new ManagedSet(); + child.Add("one"); + child.MergeEnabled = true; + child.Merge("hello"); + } + + [Test] + public void MergeEmptyChild() + { + ManagedSet parent = new ManagedSet(); + parent.Add("one"); + parent.Add("two"); + ManagedSet child = new ManagedSet(); + child.MergeEnabled = true; + ISet mergedSet = (ISet) child.Merge(parent); + Assert.AreEqual(2, mergedSet.Count); + } + + [Test] + public void MergeChildValueOverrideTheParents() + { + ManagedSet parent = new ManagedSet(); + parent.Add("one"); + parent.Add("two"); + ManagedSet child = new ManagedSet(); + child.Add("one"); + child.MergeEnabled = true; + ISet mergedList = (ISet) child.Merge(parent); + Assert.AreEqual(2, mergedList.Count); + } + } +} \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/CollectionMergingTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/CollectionMergingTests.cs new file mode 100644 index 00000000..5c8e4395 --- /dev/null +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/CollectionMergingTests.cs @@ -0,0 +1,96 @@ +#region License + +/* + * Copyright © 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; +using System.Collections; +using System.Collections.Specialized; +using NUnit.Framework; +using Spring.Collections; +using Spring.Objects.Factory.Support; + +#endregion + +namespace Spring.Objects.Factory.Xml +{ + /// + /// Unit and integration tests for the collection merging support + /// + /// Rod Johnson + /// Rick Evans + /// Mark Pollack (.NET) + [TestFixture] + public class CollectionMergingTests + { + private DefaultListableObjectFactory objectFactory; + + [SetUp] + public void SetUp() + { + this.objectFactory = new DefaultListableObjectFactory(); + IObjectDefinitionReader reader = new XmlObjectDefinitionReader(this.objectFactory); + reader.LoadObjectDefinitions(new ReadOnlyXmlTestResource("collectionMerging.xml", GetType())); + } + + [Test] + public void MergeList() + { + TestObject to = (TestObject) this.objectFactory.GetObject("childWithList"); + IList list = to.SomeList; + Assert.That(3, Is.EqualTo(list.Count)); + Assert.That("Rob Harrop", Is.EqualTo(list[0])); + Assert.That("Rod Johnson", Is.EqualTo(list[1])); + Assert.That("Juergen Hoeller", Is.EqualTo(list[2])); + } + + [Test] + public void MergeSet() + { + TestObject to = (TestObject)this.objectFactory.GetObject("childWithSet"); + ISet set = to.SomeSet; + Assert.AreEqual(2, set.Count); + Assert.IsTrue(set.Contains("Rob Harrop")); + Assert.IsTrue(set.Contains("Sally Greenwood")); + } + + [Test] + public void MergeDictionary() + { + TestObject to = (TestObject)this.objectFactory.GetObject("childWithMap"); + IDictionary map = to.SomeMap; + Assert.AreEqual(3, map.Count); + Assert.AreEqual("Sally", map["Rob"]); + Assert.AreEqual("Kerry", map["Rod"]); + Assert.AreEqual("Eva", map["Juergen"]); + } + + [Test] + public void MergeNameValueCollection() + { + TestObject to = (TestObject)this.objectFactory.GetObject("childWithNameValues"); + NameValueCollection map = to.SomeNameValueCollection; + Assert.AreEqual(3, map.Count); + Assert.AreEqual("Sally", map["Rob"]); + Assert.AreEqual("Kerry", map["Rod"]); + Assert.AreEqual("Eva", map["Juergen"]); + } + } +} \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Objects/TestObject.cs b/test/Spring/Spring.Core.Tests/Objects/TestObject.cs index 53360d70..5731c6b9 100644 --- a/test/Spring/Spring.Core.Tests/Objects/TestObject.cs +++ b/test/Spring/Spring.Core.Tests/Objects/TestObject.cs @@ -22,6 +22,7 @@ using System; using System.Collections; +using System.Collections.Specialized; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Drawing; @@ -259,6 +260,18 @@ namespace Spring.Objects set { this.someMap = value; } } + public virtual IList SomeList + { + get { return someList; } + set { this.someList = value;} + } + + public virtual NameValueCollection SomeNameValueCollection + { + get { return someNameValueCollection; } + set { this.someNameValueCollection = value;} + } + protected virtual string HappyPlace { get { return _happyPlace; } @@ -360,6 +373,7 @@ namespace Spring.Objects private Set computers = new HybridSet(); private Set someSet = new HybridSet(); private IDictionary someMap = new Hashtable(); + private IList someList = new ArrayList(); private DateTime date = DateTime.Now; private Single myFloat = (float) 0.0; private CultureInfo myCulture = CultureInfo.InvariantCulture; @@ -382,6 +396,8 @@ namespace Spring.Objects private bool initCompleted; private IDictionary sharedState; + private NameValueCollection someNameValueCollection; + #endregion #region Constructor (s) / Destructor diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2003.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2003.csproj index 05a0aebc..567713fa 100644 --- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2003.csproj +++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2003.csproj @@ -948,6 +948,26 @@ SubType = "Code" BuildAction = "Compile" /> + + + + Local - 9.0.30729 + 9.0.21022 2.0 {44B16BAA-6DF8-447C-9D7F-3AD3D854D904} Debug @@ -331,9 +331,13 @@ + + + + @@ -806,6 +810,7 @@ + diff --git a/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests.cs b/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests.cs index df317c2d..97f4ba1c 100644 --- a/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests.cs +++ b/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests.cs @@ -111,7 +111,7 @@ namespace Spring.Validation private XmlDocument GetValidatedXmlResource(string resourceExtension) { AssemblyResource validationSchema = new AssemblyResource("assembly://Spring.Core/Spring.Validation.Config/spring-validation-1.1.xsd"); - AssemblyResource objectsSchema = new AssemblyResource("assembly://Spring.Core/Spring.Objects.Factory.Xml/spring-objects-1.1.xsd"); + AssemblyResource objectsSchema = new AssemblyResource("assembly://Spring.Core/Spring.Objects.Factory.Xml/spring-objects-1.3.xsd"); return TestResourceLoader.GetXmlValidated(this, resourceExtension, objectsSchema, validationSchema); }