Browse Source

2008-05-14 Atsushi Enomoto <[email protected]>

	* EnumerableRowCollectionExtensions.cs,
	  OrderedEnumerableRowCollection.cs : implemented ThenBy().
	  It required some generic refactoring.

	* EnumerableRowCollectionTest.cs : added tests for thenby (again
	  commented out yet).


svn path=/trunk/mcs/; revision=103157
Atsushi Eno 17 years ago
parent
commit
c9c8a9b1f5

+ 6 - 0
mcs/class/System.Data.DataSetExtensions/System.Data/ChangeLog

@@ -1,3 +1,9 @@
+2008-05-14  Atsushi Enomoto  <[email protected]>
+
+	* EnumerableRowCollectionExtensions.cs,
+	  OrderedEnumerableRowCollection.cs : implemented ThenBy().
+	  It required some generic refactoring.
+
 2008-05-13  Jb Evain  <[email protected]>
 
 	* EnumerableRowCollection.cs: delete methods

+ 2 - 6
mcs/class/System.Data.DataSetExtensions/System.Data/EnumerableRowCollectionExtensions.cs

@@ -66,28 +66,24 @@ namespace System.Data
 			return new EnumerableRowCollection<S> (Enumerable.Select<TRow, S> (source, selector));
 		}
 
-		[MonoTODO]
 		public static OrderedEnumerableRowCollection<TRow> ThenBy<TRow, TKey> (this OrderedEnumerableRowCollection<TRow> source, Func<TRow, TKey> keySelector)
 		{
 			return ThenBy<TRow, TKey> (source, keySelector, Comparer<TKey>.Default);
 		}
 
-		[MonoTODO]
 		public static OrderedEnumerableRowCollection<TRow> ThenBy<TRow, TKey> (this OrderedEnumerableRowCollection<TRow> source, Func<TRow, TKey> keySelector, IComparer<TKey> comparer)
 		{
-			throw new NotImplementedException ();
+			return OrderedEnumerableRowCollection<TRow>.AddSort<TRow, TKey> (source, keySelector, comparer, false);
 		}
 
-		[MonoTODO]
 		public static OrderedEnumerableRowCollection<TRow> ThenByDescending<TRow, TKey> (this OrderedEnumerableRowCollection<TRow> source, Func<TRow, TKey> keySelector)
 		{
 			return ThenByDescending<TRow, TKey> (source, keySelector, Comparer<TKey>.Default);
 		}
 
-		[MonoTODO]
 		public static OrderedEnumerableRowCollection<TRow> ThenByDescending<TRow, TKey> (this OrderedEnumerableRowCollection<TRow> source, Func<TRow, TKey> keySelector, IComparer<TKey> comparer)
 		{
-			throw new NotImplementedException ();
+			return OrderedEnumerableRowCollection<TRow>.AddSort<TRow, TKey> (source, keySelector, comparer, true);
 		}
 
 		public static EnumerableRowCollection<TRow> Where<TRow> (this EnumerableRowCollection<TRow> source, Func<TRow, bool> predicate)

+ 57 - 20
mcs/class/System.Data.DataSetExtensions/System.Data/OrderedEnumerableRowCollection.cs

@@ -39,32 +39,75 @@ namespace System.Data
 	{
 		internal static OrderedEnumerableRowCollection<TRow> Create<TRow, TKey> (IEnumerable<TRow> source, Func<TRow, TKey> keySelector, IComparer<TKey> comparer, bool descending)
 		{
-			return new OrderedEnumerableRowCollection<TRow> (new Sorter<TRow, TKey> (source, keySelector, comparer, descending));
+			var sorter = new SortComparer<TRow> ();
+			sorter.AddSort<TKey> (keySelector, comparer, descending);
+			return new OrderedEnumerableRowCollection<TRow> (new SortedEnumerable <TRow> (source, sorter));
 		}
 
-		OrderedEnumerableRowCollection (IEnumerable<TRow> source)
+		internal static OrderedEnumerableRowCollection<TRow> AddSort<TRow, TKey> (OrderedEnumerableRowCollection<TRow> source, Func<TRow, TKey> keySelector, IComparer<TKey> comparer, bool descending)
+		{
+			source.source.Sorter.AddSort<TKey> (keySelector, comparer, descending);
+			return source;
+		}
+
+		OrderedEnumerableRowCollection (SortedEnumerable<TRow> source)
 			: base (source)
 		{
+			this.source = source;
 		}
+
+		SortedEnumerable<TRow> source;
 	}
 
-	class Sorter<TRow, TKey> : IEnumerable<TRow>
+	class SortComparer<TRow> : IComparer<TRow>
 	{
-		IEnumerable<TRow> source;
-		Func<TRow, TKey> key_selector;
-		IComparer<TKey> comparer;
-		bool descending;
+		public SortComparer ()
+		{
+		}
+
+		new List<Comparison<TRow>> comparers = new List<Comparison<TRow>> ();
+
+		public void AddSort (Comparison<TRow> comparer)
+		{
+			comparers.Add (comparer);
+		}
 
-		public Sorter (IEnumerable<TRow> source, Func<TRow, TKey> keySelector, IComparer<TKey> comparer, bool descending)
+		public void AddSort<TKey> (Func<TRow, TKey> keySelector, IComparer<TKey> comparer, bool descending)
 		{
 			if (keySelector == null)
 				throw new ArgumentNullException ("keySelector");
 			if (comparer == null)
 				comparer = Comparer<TKey>.Default;
+			comparers.Add (delegate (TRow r1, TRow r2) {
+				int ret = comparer.Compare (keySelector (r1), keySelector (r2));
+				return descending ? -ret : ret;
+				});
+		}
+
+		public int Compare (TRow r1, TRow r2)
+		{
+			foreach (var c in comparers) {
+				int ret = c (r1, r2);
+				if (ret != 0)
+					return ret;
+			}
+			return 0;
+		}
+	}
+
+	class SortedEnumerable<TRow> : IEnumerable<TRow>
+	{
+		IEnumerable<TRow> source;
+		SortComparer<TRow> sorter;
+
+		public SortedEnumerable (IEnumerable<TRow> source, SortComparer<TRow> sorter)
+		{
 			this.source = source;
-			this.key_selector = keySelector;
-			this.comparer = comparer;
-			this.descending = descending;
+			this.sorter = sorter;
+		}
+
+		public SortComparer<TRow> Sorter {
+			get { return sorter; }
 		}
 
 		public IEnumerator<TRow> GetEnumerator ()
@@ -72,15 +115,9 @@ namespace System.Data
 			var list = new List<TRow> ();
 			foreach (TRow row in source)
 				list.Add (row);
-			list.Sort (delegate (TRow r1, TRow r2) {
-				return comparer.Compare (key_selector (r1), key_selector (r2));
-				});
-			if (descending)
-				for (int i = list.Count - 1; i >= 0; i--)
-					yield return list [i];
-			else
-				for (int i = 0, c = list.Count; i < c; i++)
-					yield return list [i];
+			list.Sort (sorter);
+			for (int i = 0, c = list.Count; i < c; i++)
+				yield return list [i];
 		}
 
 		IEnumerator IEnumerable.GetEnumerator ()

+ 5 - 0
mcs/class/System.Data.DataSetExtensions/Test/System.Data/ChangeLog

@@ -1,3 +1,8 @@
+2008-05-14  Atsushi Enomoto  <[email protected]>
+
+	* EnumerableRowCollectionTest.cs : added tests for thenby (again
+	  commented out yet).
+
 2008-05-13  Atsushi Enomoto  <[email protected]>
 
 	* EnumerableRowCollectionTest.cs : added tests for orderby (though

+ 58 - 0
mcs/class/System.Data.DataSetExtensions/Test/System.Data/EnumerableRowCollectionTest.cs

@@ -143,6 +143,64 @@ namespace MonoTests.System.Data
 				prevID = ql.StudentID;
 			}
 		}
+
+		[Test]
+		public void ThenBy ()
+		{
+			var ds = new DataSet ();
+			ds.ReadXml ("Test/System.Data/testdataset1.xml");
+			var table = ds.Tables [0];
+			var q = from line in table.AsEnumerable ()
+				where line.Field<int> ("Score") >= 80
+				orderby line.Field<bool> ("Gender"), line.Field<int> ("ID")
+				select new {
+					StudentID = line.Field<int> ("ID"),
+					StudentName = line.Field<string> ("Name"),
+					StudentScore = line.Field<int> ("Score") };
+			int prevID = -1;
+			foreach (var ql in q) {
+				switch (prevID) {
+				case -1:
+					Assert.AreEqual (4, ql.StudentID, "#1");
+					break;
+				case 4:
+					Assert.AreEqual (1, ql.StudentID, "#2");
+					break;
+				default:
+					Assert.Fail ("should match only one raw");
+				}
+				prevID = ql.StudentID;
+			}
+		}
+
+		[Test]
+		public void ThenByDescending ()
+		{
+			var ds = new DataSet ();
+			ds.ReadXml ("Test/System.Data/testdataset1.xml");
+			var table = ds.Tables [0];
+			var q = from line in table.AsEnumerable ()
+				where line.Field<int> ("Score") >= 80
+				orderby line.Field<bool> ("Gender"), line.Field<int> ("ID") descending
+				select new {
+					StudentID = line.Field<int> ("ID"),
+					StudentName = line.Field<string> ("Name"),
+					StudentScore = line.Field<int> ("Score") };
+			int prevID = -1;
+			foreach (var ql in q) {
+				switch (prevID) {
+				case -1:
+					Assert.AreEqual (1, ql.StudentID, "#1");
+					break;
+				case 4:
+					Assert.AreEqual (4, ql.StudentID, "#2");
+					break;
+				default:
+					Assert.Fail ("should match only one raw");
+				}
+				prevID = ql.StudentID;
+			}
+		}
 		*/
 	}
 }

+ 5 - 0
mcs/class/System.Data.DataSetExtensions/Test/System.Data/testdataset1.xml

@@ -10,6 +10,7 @@
                 <xs:element name="RegisteredDate" type="xs:dateTime" minOccurs="0" />
                 <xs:element name="Name" type="xs:string" minOccurs="0" />
                 <xs:element name="Score" type="xs:int" minOccurs="0" />
+                <xs:element name="Gender" type="xs:boolean" minOccurs="0" />
               </xs:sequence>
             </xs:complexType>
           </xs:element>
@@ -22,24 +23,28 @@
     <RegisteredDate>2008-05-13T00:00:00.000</RegisteredDate>
     <Name>Dorkpuff</Name>
     <Score>100</Score>
+    <Gender>0</Gender>
   </ScoreList>
   <ScoreList>
     <ID>2</ID>
     <RegisteredDate>2008-05-14T00:00:00.000</RegisteredDate>
     <Name>Headfoot</Name>
     <Score>30</Score>
+    <Gender>0</Gender>
   </ScoreList>
   <ScoreList>
     <ID>3</ID>
     <RegisteredDate>2008-05-15T00:00:00.000</RegisteredDate>
     <Name>Muckdoof</Name>
     <Score>60</Score>
+    <Gender>1</Gender>
   </ScoreList>
   <ScoreList>
     <ID>4</ID>
     <RegisteredDate>2008-05-16T00:00:00.000</RegisteredDate>
     <Name>Numbcheese</Name>
     <Score>80</Score>
+    <Gender>0</Gender>
   </ScoreList>
 </TestDataSet>