/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.core.gui.components.form.flexible.impl.elements.table;
import java.sql.Timestamp;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.olat.core.commons.persistence.SortKey;
/**
* Replicate the same mechanism as in the TableController but
* as delegate.
*
*
* Initial date: 11.02.2014<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class SortableFlexiTableModelDelegate<T> {
private boolean asc;
private int columnIndex;
private final SortKey orderBy;
private final Collator collator;
private final SortableFlexiTableDataModel<T> tableModel;
public SortableFlexiTableModelDelegate(SortKey orderBy, SortableFlexiTableDataModel<T> tableModel, Locale locale) {
this.tableModel = tableModel;
this.orderBy = orderBy;
if(orderBy != null && orderBy.getKey() != null) {
FlexiColumnModel colModel = getColumnModel(orderBy.getKey(), tableModel.getTableColumnModel());
columnIndex = colModel.getColumnIndex();
asc = orderBy.isAsc();
} else {
columnIndex = 0;
asc = orderBy == null ? true : orderBy.isAsc();
}
if (locale != null) {
collator = Collator.getInstance(locale);
} else {
collator = Collator.getInstance();
}
}
public int getColumnIndex() {
return columnIndex;
}
public boolean isAsc() {
return asc;
}
public Collator getCollator() {
return collator;
}
public SortKey getOrderBy() {
return orderBy;
}
public SortableFlexiTableDataModel<T> getTableModel() {
return tableModel;
}
public List<T> sort() {
int rowCount = tableModel.getRowCount();
List<T> rows = new ArrayList<>(rowCount);
for(int i=0; i<rowCount; i++) {
rows.add(tableModel.getObject(i));
}
sort(rows);
reverse(rows);
return rows;
}
protected void reverse(List<T> rows) {
if(!asc) {
Collections.reverse(rows);
}
}
protected void sort(List<T> rows) {
Collections.sort(rows, new DefaultComparator());
}
private static final FlexiColumnModel getColumnModel(String orderBy, FlexiTableColumnModel columnModel) {
FlexiColumnModel colModel = null;
for(int i=columnModel.getColumnCount(); i-->0; ) {
FlexiColumnModel cm = columnModel.getColumnModel(i);
if(cm.isSortable() && orderBy.equals(cm.getSortKey())) {
colModel = cm;
break;
}
}
return colModel;
}
protected final int compareString(final String a, final String b) {
if (a == null || b == null) {
return compareNullObjects(a, b);
}
return collator == null ? a.compareTo(b) : collator.compare(a, b);
}
protected final int compareBooleans(final Boolean a, final Boolean b) {
if (a == null || b == null) {
return compareNullObjects(a, b);
}
boolean ba = a.booleanValue();
boolean bb = b.booleanValue();
return compareBooleans(ba, bb);
}
protected final int compareBooleans(final boolean a, final boolean b) {
return a? (b? 0: -1):(b? 1: 0);
}
protected final int compareDateAndTimestamps(Date a, Date b) {
if (a == null || b == null) {
return compareNullObjects(a, b);
}
if (a instanceof Timestamp) { // a timestamp (a) cannot compare a date (b), but vice versa is ok.
if(b instanceof Timestamp) {
return ((Timestamp)a).compareTo((Timestamp)b);
} else {
Timestamp ta = (Timestamp)a;
Date aAsDate = new Date(ta.getTime());
return aAsDate.compareTo(b);
}
} else if (b instanceof Timestamp) {
Timestamp tb = (Timestamp)b;
Date bAsDate = new Date(tb.getTime());
return a.compareTo(bAsDate);
}
return a.compareTo(b);
}
protected final int compareLongs(Long a, Long b) {
if (a == null || b == null) {
return compareNullObjects(a, b);
}
return a.compareTo(b);
}
protected final int compareInts(int a, int b) {
return Integer.compare(a, b);
}
protected final int compareDoubles(double a, double b) {
return Double.compare(a, b);
}
protected final int compareNullObjects(final Object a, final Object b) {
boolean ba = (a == null);
boolean bb = (b == null);
return ba? (bb? 0: -1):(bb? 1: 0);
}
public class ReverseComparator implements Comparator<T> {
private final Comparator<T> delegate;
public ReverseComparator(Comparator<T> delegate) {
this.delegate = delegate;
}
@Override
public int compare(T o1, T o2) {
return -1 * delegate.compare(o1, o2);
}
}
public class DefaultComparator implements Comparator<T> {
@Override
public int compare(T t1, T t2) {
Object val1 = tableModel.getValueAt(t1, columnIndex);
Object val2 = tableModel.getValueAt(t2, columnIndex);
if (val1 == null || val2 == null) {
return compareNullObjects(val1, val2);
}
if (val1 instanceof String && val2 instanceof String) {
return collator.compare(val1, val2);
}
if(val1 instanceof Date && val2 instanceof Date) {
return compareDateAndTimestamps((Date)val1, (Date)val2);
}
if (val1 instanceof Comparable && val2 instanceof Comparable) {
@SuppressWarnings("rawtypes")
Comparable c1 = (Comparable)val1;
@SuppressWarnings("rawtypes")
Comparable c2 = (Comparable)val2;
@SuppressWarnings("unchecked")
int s = c1.compareTo(c2);
return s;
}
return val1.toString().compareTo(val2.toString());
}
}
}