1+ package org .finos .vuu .core .sort
2+
3+ import com .typesafe .scalalogging .StrictLogging
4+ import org .finos .vuu .core .sort .SortDirection .Ascending
5+ import org .finos .vuu .core .table .{Column , DataType , RowData }
6+
7+ trait RowDataComparator extends java.util.Comparator [RowData ]
8+
9+ object RowDataComparator extends StrictLogging {
10+
11+ def apply (columns : List [Column ], sortDirections : List [SortDirection ]): RowDataComparator = {
12+ val comparators = columns
13+ .lazyZip(sortDirections)
14+ .map((col, dir) => buildColumnComparator(col, dir == Ascending ))
15+ .toArray
16+ RowDataComparatorImpl (comparators)
17+ }
18+
19+ private def buildColumnComparator (column : Column , isAscending : Boolean ): (RowData , RowData ) => Int = {
20+ column.dataType match {
21+ case DataType .StringDataType =>
22+ (o1 : RowData , o2 : RowData ) => compareString(o1.get(column), o2.get(column), isAscending)
23+ case DataType .LongDataType | DataType .IntegerDataType | DataType .DoubleDataType |
24+ DataType .BooleanDataType | DataType .CharDataType | DataType .EpochTimestampType |
25+ DataType .ScaledDecimal2Type | DataType .ScaledDecimal4Type |
26+ DataType .ScaledDecimal6Type | DataType .ScaledDecimal8Type =>
27+ (o1 : RowData , o2 : RowData ) => compareComparable(o1.get(column), o2.get(column), isAscending)
28+ case _ =>
29+ logger.warn(s " Unable to sort datatype ${column.dataType}" )
30+ (_, _) => 0
31+ }
32+ }
33+
34+ private def compareComparable (v1 : Any , v2 : Any , isAscending : Boolean ): Int = {
35+ val c1 = v1.asInstanceOf [Comparable [AnyRef ]]
36+ val c2 = v2.asInstanceOf [AnyRef ]
37+
38+ if (c1 eq c2) 0
39+ else if (c1 == null ) if (isAscending) 1 else - 1
40+ else if (c2 == null ) if (isAscending) - 1 else 1
41+ else {
42+ val res = c1.compareTo(c2)
43+ if (isAscending) res else - res
44+ }
45+ }
46+
47+ private def compareString (v1 : Any , v2 : Any , isAscending : Boolean ): Int = {
48+ val c1 = v1.asInstanceOf [String ]
49+ val c2 = v2.asInstanceOf [String ]
50+
51+ if (c1 eq c2) 0
52+ else if (c1 == null ) if (isAscending) 1 else - 1
53+ else if (c2 == null ) if (isAscending) - 1 else 1
54+ else {
55+ val res = c1.compareToIgnoreCase(c2)
56+ if (isAscending) res else - res
57+ }
58+ }
59+
60+ }
61+
62+ case class RowDataComparatorImpl (comparators : Array [(RowData , RowData ) => Int ]) extends RowDataComparator {
63+
64+ override def compare (o1 : RowData , o2 : RowData ): Int = {
65+ var i = 0
66+ var result = 0
67+ while (i < comparators.length && result == 0 ) {
68+ result = comparators(i)(o1, o2)
69+ i += 1
70+ }
71+ result
72+ }
73+
74+ }
0 commit comments