diff --git a/src/Spring/Spring.Core/Objects/Support/PropertyComparator.cs b/src/Spring/Spring.Core/Objects/Support/PropertyComparator.cs
index cc15bf93..c28618a6 100644
--- a/src/Spring/Spring.Core/Objects/Support/PropertyComparator.cs
+++ b/src/Spring/Spring.Core/Objects/Support/PropertyComparator.cs
@@ -191,7 +191,15 @@ namespace Spring.Objects.Support
///
public static void Sort(IList source, ISortDefinition sortDefinition)
{
- ArrayList.Adapter(source).Sort(new PropertyComparator(sortDefinition));
+// ArrayList.Adapter(source).Sort(new PropertyComparator(sortDefinition));
+ ICollection coll = CollectionUtils.StableSort(source, new PropertyComparator(sortDefinition));
+ int index = 0;
+ IEnumerator it = coll.GetEnumerator();
+ while(it.MoveNext())
+ {
+ source[index] = it.Current;
+ index++;
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Core/Util/CollectionUtils.cs b/src/Spring/Spring.Core/Util/CollectionUtils.cs
index 394e9b5e..106f8efc 100644
--- a/src/Spring/Spring.Core/Util/CollectionUtils.cs
+++ b/src/Spring/Spring.Core/Util/CollectionUtils.cs
@@ -1,5 +1,5 @@
-#region License
-
+#region License
+
/*
* Copyright © 2002-2005 the original author or authors.
*
@@ -14,206 +14,204 @@
* 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.Reflection;
-
-#endregion
-
-namespace Spring.Util
-{
- ///
- /// Miscellaneous collection utility methods.
- ///
- ///
- /// Mainly for internal use within the framework.
- ///
- /// Mark Pollack (.NET)
- public sealed class CollectionUtils
- {
- #region Methods
-
- ///
- /// Determine whether a given collection only contains
- /// a single unique object
- ///
- ///
- ///
- public static bool HasUniqueObject(ICollection coll)
- {
- if (coll.Count == 0)
- {
- return false;
- }
- object candidate = null;
- foreach (object elem in coll)
- {
- if (candidate == null)
- {
- candidate = elem;
- }
- else if (candidate != elem)
- {
- return false;
- }
- }
- return true;
- }
-
- ///
- /// Determines whether the contains the specified .
- ///
- /// The collection to check.
- /// The object to locate in the collection.
- /// if the element is in the collection, otherwise.
- public static bool Contains(ICollection collection, Object element)
- {
- if (collection == null)
- {
- throw new ArgumentNullException("Collection cannot be null.");
- }
- MethodInfo method;
- method = collection.GetType().GetMethod("contains", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
- if (null == method)
- {
- throw new InvalidOperationException("Collection type " + collection.GetType() + " does not implement a Contains() method.");
- }
- return (bool) method.Invoke(collection, new Object[] {element});
- }
-
- ///
- /// Adds the specified to the specified .
- ///
- /// The collection to add the element to.
- /// The object to add to the collection.
- public static void Add(ICollection collection, object element)
- {
- if (collection == null)
- {
- throw new ArgumentNullException("Collection cannot be null.");
- }
- MethodInfo method;
- method = collection.GetType().GetMethod("add", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
- if (null == method)
- {
- throw new InvalidOperationException("Collection type " + collection.GetType() + " does not implement a Add() method.");
- }
- method.Invoke(collection, new Object[] {element});
- }
-
- ///
- /// Determines whether the collection contains all the elements in the specified collection.
- ///
- /// The collection to check.
- /// Collection whose elements would be checked for containment.
- /// true if the target collection contains all the elements of the specified collection.
- public static bool ContainsAll(ICollection targetCollection, ICollection sourceCollection)
- {
- if (targetCollection == null || sourceCollection == null)
- {
- throw new ArgumentNullException("Collection cannot be null.");
- }
- if ( sourceCollection.Count == 0 && targetCollection.Count > 1 )
- return true;
-
- IEnumerator sourceCollectionEnumerator = sourceCollection.GetEnumerator();
-
- bool contains = false;
-
- MethodInfo method;
- method = targetCollection.GetType().GetMethod("containsAll", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
-
- if (method != null)
- contains = (bool) method.Invoke(targetCollection, new Object[] {sourceCollection});
- else
- {
- method = targetCollection.GetType().GetMethod("Contains", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
- if (method == null)
- {
- throw new InvalidOperationException("Target collection does not implment a Contains() or ContainsAll() method.");
- }
- while (sourceCollectionEnumerator.MoveNext() == true)
- {
- if ((contains = (bool) method.Invoke(targetCollection, new Object[] {sourceCollectionEnumerator.Current})) == false)
- break;
- }
- }
- return contains;
- }
-
- ///
- /// Removes all the elements from the target collection that are contained in the source collection.
- ///
- /// Collection where the elements will be removed.
- /// Elements to remove from the target collection.
- public static void RemoveAll(ICollection targetCollection, ICollection sourceCollection)
- {
- if (targetCollection == null || sourceCollection == null)
- {
- throw new ArgumentNullException("Collection cannot be null.");
- }
- ArrayList al = ToArrayList(sourceCollection);
-
- MethodInfo method;
- method = targetCollection.GetType().GetMethod("removeAll", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
-
- if (method != null)
- method.Invoke(targetCollection, new Object[] {al});
- else
- {
- method = targetCollection.GetType().GetMethod("Remove", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, new Type[1] {typeof(object)}, null );
- MethodInfo methodContains = targetCollection.GetType().GetMethod("Contains", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
- if ( method == null )
- {
- throw new InvalidOperationException("Target Collection must implement either a RemoveAll() or Remove() method.");
- }
- if ( methodContains == null )
- {
- throw new InvalidOperationException("TargetCollection must implement a Contains() method.");
- }
- IEnumerator e = al.GetEnumerator();
- while (e.MoveNext() == true)
- {
- while ((bool) methodContains.Invoke(targetCollection, new Object[] {e.Current}) == true)
- method.Invoke(targetCollection, new Object[] {e.Current});
- }
- }
- }
-
- ///
- /// Converts an instance to an instance.
- ///
- /// The instance to be converted.
- /// An instance in which its elements are the elements of the instance.
- /// if the is null.
- public static ArrayList ToArrayList(ICollection inputCollection)
- {
- if ( inputCollection == null )
- {
- throw new ArgumentNullException("Collection cannot be null.");
- }
- return new ArrayList(inputCollection);
- }
+ */
+
+#endregion
+
+#region Imports
+
+using System;
+using System.Collections;
+using System.Reflection;
+
+#endregion
+
+namespace Spring.Util
+{
+ ///
+ /// Miscellaneous collection utility methods.
+ ///
+ ///
+ /// Mainly for internal use within the framework.
+ ///
+ /// Mark Pollack (.NET)
+ public sealed class CollectionUtils
+ {
+ ///
+ /// Determine whether a given collection only contains
+ /// a single unique object
+ ///
+ ///
+ ///
+ public static bool HasUniqueObject(ICollection coll)
+ {
+ if (coll.Count == 0)
+ {
+ return false;
+ }
+ object candidate = null;
+ foreach (object elem in coll)
+ {
+ if (candidate == null)
+ {
+ candidate = elem;
+ }
+ else if (candidate != elem)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Determines whether the contains the specified .
+ ///
+ /// The collection to check.
+ /// The object to locate in the collection.
+ /// if the element is in the collection, otherwise.
+ public static bool Contains(ICollection collection, Object element)
+ {
+ if (collection == null)
+ {
+ throw new ArgumentNullException("Collection cannot be null.");
+ }
+ MethodInfo method;
+ method = collection.GetType().GetMethod("contains", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
+ if (null == method)
+ {
+ throw new InvalidOperationException("Collection type " + collection.GetType() + " does not implement a Contains() method.");
+ }
+ return (bool)method.Invoke(collection, new Object[] { element });
+ }
+
+ ///
+ /// Adds the specified to the specified .
+ ///
+ /// The collection to add the element to.
+ /// The object to add to the collection.
+ public static void Add(ICollection collection, object element)
+ {
+ if (collection == null)
+ {
+ throw new ArgumentNullException("Collection cannot be null.");
+ }
+ MethodInfo method;
+ method = collection.GetType().GetMethod("add", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
+ if (null == method)
+ {
+ throw new InvalidOperationException("Collection type " + collection.GetType() + " does not implement a Add() method.");
+ }
+ method.Invoke(collection, new Object[] { element });
+ }
+
+ ///
+ /// Determines whether the collection contains all the elements in the specified collection.
+ ///
+ /// The collection to check.
+ /// Collection whose elements would be checked for containment.
+ /// true if the target collection contains all the elements of the specified collection.
+ public static bool ContainsAll(ICollection targetCollection, ICollection sourceCollection)
+ {
+ if (targetCollection == null || sourceCollection == null)
+ {
+ throw new ArgumentNullException("Collection cannot be null.");
+ }
+ if (sourceCollection.Count == 0 && targetCollection.Count > 1)
+ return true;
+
+ IEnumerator sourceCollectionEnumerator = sourceCollection.GetEnumerator();
+
+ bool contains = false;
+
+ MethodInfo method;
+ method = targetCollection.GetType().GetMethod("containsAll", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
+
+ if (method != null)
+ contains = (bool)method.Invoke(targetCollection, new Object[] { sourceCollection });
+ else
+ {
+ method = targetCollection.GetType().GetMethod("Contains", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
+ if (method == null)
+ {
+ throw new InvalidOperationException("Target collection does not implment a Contains() or ContainsAll() method.");
+ }
+ while (sourceCollectionEnumerator.MoveNext() == true)
+ {
+ if ((contains = (bool)method.Invoke(targetCollection, new Object[] { sourceCollectionEnumerator.Current })) == false)
+ break;
+ }
+ }
+ return contains;
+ }
+
+ ///
+ /// Removes all the elements from the target collection that are contained in the source collection.
+ ///
+ /// Collection where the elements will be removed.
+ /// Elements to remove from the target collection.
+ public static void RemoveAll(ICollection targetCollection, ICollection sourceCollection)
+ {
+ if (targetCollection == null || sourceCollection == null)
+ {
+ throw new ArgumentNullException("Collection cannot be null.");
+ }
+ ArrayList al = ToArrayList(sourceCollection);
+
+ MethodInfo method;
+ method = targetCollection.GetType().GetMethod("removeAll", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
+
+ if (method != null)
+ method.Invoke(targetCollection, new Object[] { al });
+ else
+ {
+ method = targetCollection.GetType().GetMethod("Remove", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(object) }, null);
+ MethodInfo methodContains = targetCollection.GetType().GetMethod("Contains", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
+ if (method == null)
+ {
+ throw new InvalidOperationException("Target Collection must implement either a RemoveAll() or Remove() method.");
+ }
+ if (methodContains == null)
+ {
+ throw new InvalidOperationException("TargetCollection must implement a Contains() method.");
+ }
+ IEnumerator e = al.GetEnumerator();
+ while (e.MoveNext() == true)
+ {
+ while ((bool)methodContains.Invoke(targetCollection, new Object[] { e.Current }) == true)
+ method.Invoke(targetCollection, new Object[] { e.Current });
+ }
+ }
+ }
+
+ ///
+ /// Converts an instance to an instance.
+ ///
+ /// The instance to be converted.
+ /// An instance in which its elements are the elements of the instance.
+ /// if the is null.
+ public static ArrayList ToArrayList(ICollection inputCollection)
+ {
+ if (inputCollection == null)
+ {
+ throw new ArgumentNullException("Collection cannot be null.");
+ }
+ return new ArrayList(inputCollection);
+ }
///
/// Copies the elements of the to a
/// new array of the specified element type.
///
- /// The instance to be converted.
+ /// The instance to be converted.
/// The element of the destination array to create and copy elements to
- /// An array of the specified element type containing copies of the elements of the .
- public static Array ToArray(ICollection inputCollection, Type elementType)
+ /// An array of the specified element type containing copies of the elements of the .
+ public static Array ToArray(ICollection inputCollection, Type elementType)
{
Array array = Array.CreateInstance(elementType, inputCollection.Count);
inputCollection.CopyTo(array, 0);
return array;
- }
+ }
///
/// Finds a value of the given type in the given collection.
@@ -222,13 +220,13 @@ namespace Spring.Util
/// The type to look for.
/// a value of the given type found, or null if none.
/// If more than one value of the given type is found
- public static object FindValueOfType(ICollection collection, Type type)
+ public static object FindValueOfType(ICollection collection, Type type)
{
if (IsEmpty(collection))
{
return null;
}
- Type typeToUse = (type != null ? type : typeof (object));
+ Type typeToUse = (type != null ? type : typeof(object));
object val = null;
foreach (object obj in collection)
{
@@ -277,7 +275,7 @@ namespace Spring.Util
///
/// true if the specified collection is empty or null; otherwise, false.
///
- public static bool IsEmpty(ICollection collection)
+ public static bool IsEmpty(ICollection collection)
{
return (collection == null || collection.Count == 0);
}
@@ -289,11 +287,162 @@ namespace Spring.Util
///
/// true if the specified dictionary is empty or null; otherwise, false.
///
- public static bool IsEmpty(IDictionary dictionary)
+ public static bool IsEmpty(IDictionary dictionary)
{
return (dictionary == null || dictionary.Count == 0);
- }
-
- #endregion
- }
+ }
+
+ ///
+ /// A callback method used for comparing to items.
+ ///
+ ///
+ ///
+ /// the first object to compare
+ /// the second object to compare
+ /// Value Condition Less than zero x is less than y. Zero x equals y. Greater than zero x is greater than y.
+ ///
+ ///
+ public delegate int CompareCallback(object left, object right);
+
+ ///
+ /// A simple stable sorting routine - far from being efficient, only for small collections.
+ ///
+ ///
+ ///
+ ///
+ public static ICollection StableSort(IEnumerable input, IComparer comparer)
+ {
+ return StableSort(input, new CompareCallback(comparer.Compare));
+ }
+
+ ///
+ /// A simple stable sorting routine - far from being efficient, only for small collections.
+ ///
+ ///
+ /// Sorting is not(!) done in-place. Instead a sorted copy of the original input is returned.
+ ///
+ /// input collection of items to sort
+ /// the for comparing 2 items in .
+ /// a new collection of stable sorted items.
+ public static ICollection StableSort(IEnumerable input, CompareCallback comparer)
+ {
+ ArrayList ehancedInput = new ArrayList();
+ IEnumerator it = input.GetEnumerator();
+ int index = 0;
+ while (it.MoveNext())
+ {
+ ehancedInput.Add(new Entry(index, it.Current));
+ index++;
+ }
+
+ ehancedInput.Sort(Entry.GetComparer(comparer));
+
+ for (int i = 0; i < ehancedInput.Count; i++ )
+ {
+ ehancedInput[i] = ((Entry) ehancedInput[i]).Value;
+ }
+
+ return ehancedInput;
+ }
+
+ ///
+ /// A simple stable sorting routine - far from being efficient, only for small collections.
+ ///
+ ///
+ /// Sorting is not(!) done in-place. Instead a sorted copy of the original input is returned.
+ ///
+ /// input collection of items to sort
+ /// the for comparing 2 items in .
+ /// a new collection of stable sorted items.
+ public static void StableSortInPlace(IList input, CompareCallback comparer)
+ {
+ ArrayList ehancedInput = new ArrayList();
+ IEnumerator it = input.GetEnumerator();
+ int index = 0;
+ while (it.MoveNext())
+ {
+ ehancedInput.Add(new Entry(index, it.Current));
+ index++;
+ }
+
+ ehancedInput.Sort(Entry.GetComparer(comparer));
+
+ for (int i = 0; i < ehancedInput.Count; i++)
+ {
+ input[i] = ((Entry)ehancedInput[i]).Value;
+ }
+ }
+
+ ///
+ /// A simple stable sorting routine - far from being efficient, only for small collections.
+ ///
+ ///
+ /// Sorting is not(!) done in-place. Instead a sorted copy of the original input is returned.
+ ///
+ /// input collection of items to sort
+ /// the for comparing 2 items in .
+ /// a new collection of stable sorted items.
+ public static void StableSortInPlace(Array input, CompareCallback comparer)
+ {
+ ArrayList ehancedInput = new ArrayList();
+ IEnumerator it = input.GetEnumerator();
+ int index = 0;
+ while (it.MoveNext())
+ {
+ ehancedInput.Add(new Entry(index, it.Current));
+ index++;
+ }
+
+ ehancedInput.Sort(Entry.GetComparer(comparer));
+
+ for (int i = 0; i < ehancedInput.Count; i++)
+ {
+ throw new NotImplementedException();
+// input[i] = ((Entry)ehancedInput[i]).Value;
+ }
+ }
+
+ #region StableSort Utility Classes
+
+ private class Entry
+ {
+ private class EntryComparer : IComparer
+ {
+ private readonly CompareCallback innerComparer;
+
+ public EntryComparer(CompareCallback innerComparer)
+ {
+ this.innerComparer = innerComparer;
+ }
+
+ public int Compare(object x, object y)
+ {
+ Entry ex = (Entry)x;
+ Entry ey = (Entry)y;
+ int result = innerComparer(ex.Value, ey.Value);
+ if (result == 0)
+ {
+ result = ex.Index.CompareTo(ey.Index);
+ }
+ return result;
+ }
+ }
+
+ public static IComparer GetComparer(CompareCallback innerComparer)
+ {
+ return new EntryComparer(innerComparer);
+ }
+
+ public readonly int Index;
+ public readonly object Value;
+
+ public Entry(int index, object value)
+ {
+ Index = index;
+ Value = value;
+ }
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Data/Transaction/Support/TransactionSynchronizationManager.cs b/src/Spring/Spring.Data/Transaction/Support/TransactionSynchronizationManager.cs
index c2c48230..437797dd 100644
--- a/src/Spring/Spring.Data/Transaction/Support/TransactionSynchronizationManager.cs
+++ b/src/Spring/Spring.Data/Transaction/Support/TransactionSynchronizationManager.cs
@@ -336,8 +336,13 @@ namespace Spring.Transaction.Support
object root = syncs.SyncRoot;
lock (root)
{
- syncs.Sort(syncComparer);
- }
+// syncs.Sort(syncComparer);
+
+ // StableSort
+ ICollection sorted = CollectionUtils.StableSort(syncs, syncComparer);
+ syncs = new ArrayList( sorted );
+ }
+
// Return unmodifiable snapshot, to avoid exceptions
// while iterating and invoking synchronization callbacks that in turn
// might register further synchronizations.
diff --git a/test/Spring/Spring.Core.Tests/Objects/Support/PropertyComparatorTests.cs b/test/Spring/Spring.Core.Tests/Objects/Support/PropertyComparatorTests.cs
index 0e5e4eb1..c585c814 100644
--- a/test/Spring/Spring.Core.Tests/Objects/Support/PropertyComparatorTests.cs
+++ b/test/Spring/Spring.Core.Tests/Objects/Support/PropertyComparatorTests.cs
@@ -140,7 +140,7 @@ namespace Spring.Objects.Support
}
[Test]
- [Ignore("Sort ordering is not preserved (unstable) with equal elements (c.f. System.Array.Sort (Array, IComparer)))")]
+// [Ignore("Sort ordering is not preserved (unstable) with equal elements (c.f. System.Array.Sort (Array, IComparer)))")]
public void OrderingIsUnperturbedWithEqualProps()
{
ISortDefinition definition = new MutableSortDefinition("Age", false, true);
diff --git a/test/Spring/Spring.Core.Tests/Util/CollectionUtilsTests.cs b/test/Spring/Spring.Core.Tests/Util/CollectionUtilsTests.cs
index 33c5f4f3..28062de8 100644
--- a/test/Spring/Spring.Core.Tests/Util/CollectionUtilsTests.cs
+++ b/test/Spring/Spring.Core.Tests/Util/CollectionUtilsTests.cs
@@ -5,303 +5,303 @@ using Spring.Objects;
namespace Spring.Util
{
- [TestFixture]
- public class CollectionUtilsTests
- {
- internal class NoContainsNoAddCollection : ICollection
- {
- internal class Iterator : IEnumerator
- {
- #region IEnumerator Members
+ [TestFixture]
+ public class CollectionUtilsTests
+ {
+ internal class NoContainsNoAddCollection : ICollection
+ {
+ internal class Iterator : IEnumerator
+ {
+ #region IEnumerator Members
- public void Reset()
- {
- // TODO: Add Iterator.Reset implementation
- }
+ public void Reset()
+ {
+ // TODO: Add Iterator.Reset implementation
+ }
- public object Current
- {
- get
- {
- // TODO: Add Iterator.Current getter implementation
- return null;
- }
- }
+ public object Current
+ {
+ get
+ {
+ // TODO: Add Iterator.Current getter implementation
+ return null;
+ }
+ }
- public bool MoveNext()
- {
- // TODO: Add Iterator.MoveNext implementation
- return false;
- }
+ public bool MoveNext()
+ {
+ // TODO: Add Iterator.MoveNext implementation
+ return false;
+ }
- #endregion
+ #endregion
- }
+ }
- public void CopyTo(Array array, int index)
- {
- throw new NotImplementedException();
- }
+ public void CopyTo(Array array, int index)
+ {
+ throw new NotImplementedException();
+ }
- public int Count
- {
- get { return 0; }
- }
+ public int Count
+ {
+ get { return 0; }
+ }
- public object SyncRoot
- {
- get { throw new NotImplementedException(); }
- }
+ public object SyncRoot
+ {
+ get { throw new NotImplementedException(); }
+ }
- public bool IsSynchronized
- {
- get { throw new NotImplementedException(); }
- }
+ public bool IsSynchronized
+ {
+ get { throw new NotImplementedException(); }
+ }
- public IEnumerator GetEnumerator()
- {
- return new Iterator();
- }
- }
- [Test]
- [ExpectedException(typeof(ArgumentNullException))]
- public void ContainsNullCollection()
- {
- CollectionUtils.Contains(null, null);
- }
- [Test]
- public void ContainsNullObject()
- {
- ArrayList list = new ArrayList();
- list.Add(null);
- Assert.IsTrue(CollectionUtils.Contains(list, null));
- }
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ContainsCollectionDoesNotImplementContains()
- {
- NoContainsNoAddCollection noAddCollection = new NoContainsNoAddCollection();
- CollectionUtils.Contains(noAddCollection, new object());
- }
- [Test]
- public void ContainsValidElement()
- {
- ArrayList list = new ArrayList();
- list.Add(1);
- list.Add(2);
- list.Add(3);
- list.Add(4);
-
- Assert.IsTrue(CollectionUtils.Contains(list, 3));
- }
- [Test]
- public void ContainsDoesNotContainElement()
- {
- ArrayList list = new ArrayList();
- list.Add(1);
- list.Add(2);
- list.Add(3);
- list.Add(4);
+ public IEnumerator GetEnumerator()
+ {
+ return new Iterator();
+ }
+ }
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void ContainsNullCollection()
+ {
+ CollectionUtils.Contains(null, null);
+ }
+ [Test]
+ public void ContainsNullObject()
+ {
+ ArrayList list = new ArrayList();
+ list.Add(null);
+ Assert.IsTrue(CollectionUtils.Contains(list, null));
+ }
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void ContainsCollectionDoesNotImplementContains()
+ {
+ NoContainsNoAddCollection noAddCollection = new NoContainsNoAddCollection();
+ CollectionUtils.Contains(noAddCollection, new object());
+ }
+ [Test]
+ public void ContainsValidElement()
+ {
+ ArrayList list = new ArrayList();
+ list.Add(1);
+ list.Add(2);
+ list.Add(3);
+ list.Add(4);
- Assert.IsFalse(CollectionUtils.Contains(list, 5));
- }
- [Test]
- [ExpectedException(typeof(ArgumentNullException))]
- public void AddNullCollection()
- {
- CollectionUtils.Add(null, null);
- }
- [Test]
- public void AddNullObject()
- {
- ArrayList list = new ArrayList();
- CollectionUtils.Add(list, null);
- Assert.IsTrue(list.Count == 1);
- }
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void AddCollectionDoesNotImplementAdd()
- {
- NoContainsNoAddCollection noAddCollection = new NoContainsNoAddCollection();
- CollectionUtils.Add(noAddCollection, null);
- }
- [Test]
- public void AddValidElement()
- {
- ArrayList list = new ArrayList();
- object obj1 = new object();
- CollectionUtils.Add(list, obj1);
- Assert.IsTrue(list.Count == 1);
- }
- [Test]
- [ExpectedException(typeof(ArgumentNullException))]
- public void ContainsAllNullTargetCollection()
- {
- CollectionUtils.ContainsAll(null, new ArrayList());
- }
+ Assert.IsTrue(CollectionUtils.Contains(list, 3));
+ }
+ [Test]
+ public void ContainsDoesNotContainElement()
+ {
+ ArrayList list = new ArrayList();
+ list.Add(1);
+ list.Add(2);
+ list.Add(3);
+ list.Add(4);
- [Test]
- [ExpectedException(typeof(ArgumentNullException))]
- public void ContainsAllSourceNullCollection()
- {
- CollectionUtils.ContainsAll(new ArrayList(), null);
- }
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void ContainsAllDoesNotImplementContains()
- {
- CollectionUtils.ContainsAll(new NoContainsNoAddCollection(), new ArrayList());
- }
- [Test]
- public void DoesNotContainAllElements()
- {
- ArrayList target = new ArrayList();
- target.Add(1);
- target.Add(2);
- target.Add(3);
+ Assert.IsFalse(CollectionUtils.Contains(list, 5));
+ }
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void AddNullCollection()
+ {
+ CollectionUtils.Add(null, null);
+ }
+ [Test]
+ public void AddNullObject()
+ {
+ ArrayList list = new ArrayList();
+ CollectionUtils.Add(list, null);
+ Assert.IsTrue(list.Count == 1);
+ }
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void AddCollectionDoesNotImplementAdd()
+ {
+ NoContainsNoAddCollection noAddCollection = new NoContainsNoAddCollection();
+ CollectionUtils.Add(noAddCollection, null);
+ }
+ [Test]
+ public void AddValidElement()
+ {
+ ArrayList list = new ArrayList();
+ object obj1 = new object();
+ CollectionUtils.Add(list, obj1);
+ Assert.IsTrue(list.Count == 1);
+ }
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void ContainsAllNullTargetCollection()
+ {
+ CollectionUtils.ContainsAll(null, new ArrayList());
+ }
- ArrayList source = new ArrayList();
- source.Add(1);
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void ContainsAllSourceNullCollection()
+ {
+ CollectionUtils.ContainsAll(new ArrayList(), null);
+ }
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void ContainsAllDoesNotImplementContains()
+ {
+ CollectionUtils.ContainsAll(new NoContainsNoAddCollection(), new ArrayList());
+ }
+ [Test]
+ public void DoesNotContainAllElements()
+ {
+ ArrayList target = new ArrayList();
+ target.Add(1);
+ target.Add(2);
+ target.Add(3);
- Assert.IsTrue(CollectionUtils.ContainsAll(target, source));
- }
- [Test]
- public void ContainsAllElements()
- {
- ArrayList target = new ArrayList();
- target.Add(1);
- target.Add(2);
- target.Add(3);
+ ArrayList source = new ArrayList();
+ source.Add(1);
- ArrayList source = new ArrayList();
- source.Add(1);
- source.Add(2);
- source.Add(3);
+ Assert.IsTrue(CollectionUtils.ContainsAll(target, source));
+ }
+ [Test]
+ public void ContainsAllElements()
+ {
+ ArrayList target = new ArrayList();
+ target.Add(1);
+ target.Add(2);
+ target.Add(3);
- Assert.IsTrue(CollectionUtils.ContainsAll(target, source));
- }
- [Test]
- public void ContainsAllElementsWithNoElementsInSourceCollection()
- {
- ArrayList target = new ArrayList();
- target.Add(1);
- target.Add(2);
- target.Add(3);
+ ArrayList source = new ArrayList();
+ source.Add(1);
+ source.Add(2);
+ source.Add(3);
- ArrayList source = new ArrayList();
- Assert.IsTrue(CollectionUtils.ContainsAll(target, source));
- }
- [Test]
- public void ContainsAllElementsWithNoElementsEitherCollection()
- {
- ArrayList target = new ArrayList();
- ArrayList source = new ArrayList();
- Assert.IsFalse(CollectionUtils.ContainsAll(target, source));
- }
- [Test]
- [ExpectedException(typeof(ArgumentNullException))]
- public void ToArrayNullTargetCollection()
- {
- CollectionUtils.ToArrayList(null);
- }
- [Test]
- public void ToArrayAllElements()
- {
- ArrayList target = new ArrayList();
- target.Add(1);
- target.Add(2);
- target.Add(3);
+ Assert.IsTrue(CollectionUtils.ContainsAll(target, source));
+ }
+ [Test]
+ public void ContainsAllElementsWithNoElementsInSourceCollection()
+ {
+ ArrayList target = new ArrayList();
+ target.Add(1);
+ target.Add(2);
+ target.Add(3);
- ArrayList source = CollectionUtils.ToArrayList(target);
+ ArrayList source = new ArrayList();
+ Assert.IsTrue(CollectionUtils.ContainsAll(target, source));
+ }
+ [Test]
+ public void ContainsAllElementsWithNoElementsEitherCollection()
+ {
+ ArrayList target = new ArrayList();
+ ArrayList source = new ArrayList();
+ Assert.IsFalse(CollectionUtils.ContainsAll(target, source));
+ }
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void ToArrayNullTargetCollection()
+ {
+ CollectionUtils.ToArrayList(null);
+ }
+ [Test]
+ public void ToArrayAllElements()
+ {
+ ArrayList target = new ArrayList();
+ target.Add(1);
+ target.Add(2);
+ target.Add(3);
- Assert.AreEqual(target.Count, source.Count);
- }
- [Test]
- public void EmptyArrayElements()
- {
- ArrayList source = CollectionUtils.ToArrayList(new NoContainsNoAddCollection());
- Assert.AreEqual(0, source.Count);
- }
+ ArrayList source = CollectionUtils.ToArrayList(target);
- [Test]
- [ExpectedException(typeof(ArgumentNullException))]
- public void RemoveAllTargetNullCollection()
- {
- CollectionUtils.RemoveAll(null, new ArrayList());
- }
- [Test]
- [ExpectedException(typeof(ArgumentNullException))]
- public void RemoveAllSourceNullCollection()
- {
- CollectionUtils.RemoveAll(new ArrayList(), null);
- }
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void RemoveAllTargetCollectionDoesNotImplementContains()
- {
- CollectionUtils.RemoveAll(new NoContainsNoAddCollection(), new ArrayList());
- }
- [Test]
- [ExpectedException(typeof(InvalidOperationException))]
- public void RemoveAllTargetCollectionDoesNotImplementRemove()
- {
- CollectionUtils.RemoveAll(new NoContainsNoAddCollection(), new ArrayList());
- }
- [Test]
- public void RemoveAllNoElements()
- {
- ArrayList target = new ArrayList();
- target.Add(1);
- target.Add(2);
- target.Add(3);
+ Assert.AreEqual(target.Count, source.Count);
+ }
+ [Test]
+ public void EmptyArrayElements()
+ {
+ ArrayList source = CollectionUtils.ToArrayList(new NoContainsNoAddCollection());
+ Assert.AreEqual(0, source.Count);
+ }
- ArrayList source = new ArrayList();
- source.Add(4);
- source.Add(5);
- source.Add(6);
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void RemoveAllTargetNullCollection()
+ {
+ CollectionUtils.RemoveAll(null, new ArrayList());
+ }
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void RemoveAllSourceNullCollection()
+ {
+ CollectionUtils.RemoveAll(new ArrayList(), null);
+ }
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void RemoveAllTargetCollectionDoesNotImplementContains()
+ {
+ CollectionUtils.RemoveAll(new NoContainsNoAddCollection(), new ArrayList());
+ }
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void RemoveAllTargetCollectionDoesNotImplementRemove()
+ {
+ CollectionUtils.RemoveAll(new NoContainsNoAddCollection(), new ArrayList());
+ }
+ [Test]
+ public void RemoveAllNoElements()
+ {
+ ArrayList target = new ArrayList();
+ target.Add(1);
+ target.Add(2);
+ target.Add(3);
- CollectionUtils.RemoveAll(target, source);
- Assert.IsTrue(3 == target.Count);
- }
- [Test]
- public void RemoveAllSomeElements()
- {
- ArrayList target = new ArrayList();
- target.Add(1);
- target.Add(2);
- target.Add(3);
- target.Add(4);
- target.Add(5);
+ ArrayList source = new ArrayList();
+ source.Add(4);
+ source.Add(5);
+ source.Add(6);
- ArrayList source = new ArrayList();
- source.Add(4);
- source.Add(5);
- source.Add(6);
+ CollectionUtils.RemoveAll(target, source);
+ Assert.IsTrue(3 == target.Count);
+ }
+ [Test]
+ public void RemoveAllSomeElements()
+ {
+ ArrayList target = new ArrayList();
+ target.Add(1);
+ target.Add(2);
+ target.Add(3);
+ target.Add(4);
+ target.Add(5);
- CollectionUtils.RemoveAll(target, source);
- Assert.IsTrue(3 == target.Count);
- }
- [Test]
- public void RemoveAllAllElements()
- {
- ArrayList target = new ArrayList();
- target.Add(1);
- target.Add(2);
- target.Add(3);
- target.Add(4);
- target.Add(5);
+ ArrayList source = new ArrayList();
+ source.Add(4);
+ source.Add(5);
+ source.Add(6);
- ArrayList source = new ArrayList();
- source.Add(1);
- source.Add(2);
- source.Add(3);
- source.Add(4);
- source.Add(5);
- source.Add(6);
+ CollectionUtils.RemoveAll(target, source);
+ Assert.IsTrue(3 == target.Count);
+ }
+ [Test]
+ public void RemoveAllAllElements()
+ {
+ ArrayList target = new ArrayList();
+ target.Add(1);
+ target.Add(2);
+ target.Add(3);
+ target.Add(4);
+ target.Add(5);
- CollectionUtils.RemoveAll(target, source);
- Assert.IsTrue(0 == target.Count);
- }
+ ArrayList source = new ArrayList();
+ source.Add(1);
+ source.Add(2);
+ source.Add(3);
+ source.Add(4);
+ source.Add(5);
+ source.Add(6);
+
+ CollectionUtils.RemoveAll(target, source);
+ Assert.IsTrue(0 == target.Count);
+ }
[Test]
public void IsCollectionEmptyOrNull()
@@ -331,14 +331,14 @@ namespace Spring.Util
ArrayList list = new ArrayList();
Assert.IsNull(CollectionUtils.FindValueOfType(list, typeof(String)));
list.Add("foo");
- object obj = CollectionUtils.FindValueOfType(list, typeof (String));
- Assert.IsNotNull(obj);
+ object obj = CollectionUtils.FindValueOfType(list, typeof(String));
+ Assert.IsNotNull(obj);
Assert.IsNotNull(obj as string);
string val = obj as string;
Assert.AreEqual("foo", val);
list.Add(new TestObject("Joe", 34));
- obj = CollectionUtils.FindValueOfType(list, typeof (TestObject));
+ obj = CollectionUtils.FindValueOfType(list, typeof(TestObject));
Assert.IsNotNull(obj);
TestObject to = obj as TestObject;
Assert.IsNotNull(to);
@@ -349,7 +349,8 @@ namespace Spring.Util
{
obj = CollectionUtils.FindValueOfType(list, typeof(TestObject));
Assert.Fail("Should have thrown exception");
- } catch (ArgumentException)
+ }
+ catch (ArgumentException)
{
//ok
}
@@ -361,7 +362,7 @@ namespace Spring.Util
{
ArrayList list = new ArrayList();
list.Add("mystring");
- string[] strList = (string[]) CollectionUtils.ToArray(list, typeof(string));
+ string[] strList = (string[])CollectionUtils.ToArray(list, typeof(string));
Assert.AreEqual(1, strList.Length);
try
@@ -369,7 +370,39 @@ namespace Spring.Util
CollectionUtils.ToArray(list, typeof(Type));
Assert.Fail("should fail");
}
- catch(InvalidCastException) {}
+ catch (InvalidCastException) { }
}
- }
+
+ [Test]
+ public void StableSorting()
+ {
+ DictionaryEntry[] entries = new DictionaryEntry[]
+ {
+ new DictionaryEntry(5, 4),
+ new DictionaryEntry(5, 5),
+ new DictionaryEntry(3, 2),
+ new DictionaryEntry(3, 3),
+ new DictionaryEntry(1, 0),
+ new DictionaryEntry(1, 1),
+ };
+
+ ICollection resultList = CollectionUtils.StableSort(entries, new CollectionUtils.CompareCallback(CompareEntries));
+ DictionaryEntry[] resultEntries = (DictionaryEntry[]) CollectionUtils.ToArray(resultList, typeof(DictionaryEntry));
+
+ Assert.AreEqual(0, resultEntries[0].Value);
+ Assert.AreEqual(1, resultEntries[1].Value);
+ Assert.AreEqual(2, resultEntries[2].Value);
+ Assert.AreEqual(3, resultEntries[3].Value);
+ Assert.AreEqual(4, resultEntries[4].Value);
+ Assert.AreEqual(5, resultEntries[5].Value);
+ }
+
+ private int CompareEntries(object x, object y)
+ {
+ DictionaryEntry dex = (DictionaryEntry)x;
+ DictionaryEntry dey = (DictionaryEntry)y;
+
+ return ((int)dex.Key).CompareTo(dey.Key);
+ }
+ }
}
diff --git a/test/Spring/Spring.Data.Tests/Transaction/Support/TransactionSynchronizationManagerTests.cs b/test/Spring/Spring.Data.Tests/Transaction/Support/TransactionSynchronizationManagerTests.cs
index da888276..cb2bc502 100644
--- a/test/Spring/Spring.Data.Tests/Transaction/Support/TransactionSynchronizationManagerTests.cs
+++ b/test/Spring/Spring.Data.Tests/Transaction/Support/TransactionSynchronizationManagerTests.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections;
using NUnit.Framework;
+using Spring.Core;
+using Spring.Util;
namespace Spring.Transaction.Support
{
@@ -30,6 +32,7 @@ namespace Spring.Transaction.Support
IList syncs = TransactionSynchronizationManager.Synchronizations;
Assert.IsNotNull(syncs); // to avoid mono mcs error 219
}
+
[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void InitSynchronizationsInvalid()
@@ -43,12 +46,14 @@ namespace Spring.Transaction.Support
{
TransactionSynchronizationManager.ClearSynchronization();
}
+
[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void RegisterSyncsInvalid()
{
TransactionSynchronizationManager.RegisterSynchronization(new MockTxnSync());
}
+
[Test]
public void SynchronizationsLifeCycle()
{
@@ -60,5 +65,57 @@ namespace Spring.Transaction.Support
Assert.AreEqual( 1, syncs.Count );
TransactionSynchronizationManager.ClearSynchronization();
}
+
+ [Test(Description = "http://jira.springframework.org/browse/SPRNET-1160")]
+ public void SynchronizationsExecuteInOrderOfRegistration()
+ {
+ TransactionSynchronizationManager.InitSynchronization();
+
+ try
+ {
+ // expect syncs to be run A, B, C, D, E since all have order '1'
+ TransactionSynchronizationManager.RegisterSynchronization(new Sync("A", 1));
+ TransactionSynchronizationManager.RegisterSynchronization(new Sync("B", 1));
+ TransactionSynchronizationManager.RegisterSynchronization(new Sync("C", 1));
+ TransactionSynchronizationManager.RegisterSynchronization(new Sync("D", 1));
+ TransactionSynchronizationManager.RegisterSynchronization(new Sync("E", 1));
+
+ // simulate what APTM does
+ Sync[] syncs = (Sync[]) CollectionUtils.ToArray(TransactionSynchronizationManager.Synchronizations, typeof(Sync));
+ Assert.AreEqual( "A", syncs[0].Name );
+ Assert.AreEqual( "B", syncs[1].Name );
+ Assert.AreEqual( "C", syncs[2].Name );
+ Assert.AreEqual( "D", syncs[3].Name );
+ Assert.AreEqual( "E", syncs[4].Name );
+ }
+ finally
+ {
+ TransactionSynchronizationManager.ClearSynchronization();
+ }
+ }
+
+ private class Sync : TransactionSynchronizationAdapter, IOrdered
+ {
+ private readonly string name;
+ private readonly int order;
+
+ public Sync(string name, int order)
+ {
+ this.name = name;
+ this.order = order;
+ }
+
+ public int Order { get { return order; } }
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public override string ToString()
+ {
+ return name;
+ }
+ }
}
}