EntryComparator.java

package org.microspace.table.query.sql;

import java.io.Serializable;
import java.util.Comparator;
import java.util.List;

import org.microspace.table.Entry;
import org.microspace.table.column.Accessor;
import org.microspace.table.column.GetSetPair;
import org.microspace.table.query.SqlFormat;
import org.microspace.util.PojoUtil;

/**
 * Generic Comparator of Entry objects.
 * 
 * @author Gaspar Sinai - {@literal gaspar.sinai@microspace.org}
 * @version 2017-07-29
 * @param <T> The type of the Table.
 */
public class EntryComparator<T> implements Comparator<Entry<T>>, Serializable {

	private static final long serialVersionUID = -1558132359899475455L;

	public enum Type {
		
		ASC(true),
		DESC(false),
		SKIP(false);
		
		
		final boolean ascending;
		
		private Type (boolean ascending) {
			this.ascending = ascending;
		}
		public boolean getAscending() {
			return ascending;
		}
	}
	
	final Class<T> tableClass;
	final GetSetPair<T> getSetPairs[];
	final String columnEscList[];
	
	final Type[] types;
	final Type sortByUpdateTime;
	
	
	@SuppressWarnings("unchecked")
	public EntryComparator (Class<T> tableClass, Type sortByUpdateTime,
			List<String> columnList, List<Type> types, List<String> columnListEsc) {
		this.sortByUpdateTime = sortByUpdateTime;
		this.tableClass = tableClass;
		this.types = types.toArray(new Type[types.size()]);
		this.columnEscList = columnListEsc.toArray(new String[columnListEsc.size()]);
		this.getSetPairs = (GetSetPair<T>[]) new GetSetPair<?>[columnList.size()];
		Accessor<T> accessor = PojoUtil.getUnannotateAccessor(tableClass);
		int i=0;
		for (String column : columnList) {
			GetSetPair<T> getSetPair = accessor.getGetSetPair(column);
			if (getSetPair == null) {
				throw new IllegalArgumentException ("Field Not Found: " + column);
			}
			getSetPairs[i++] = getSetPair;
		}
		String[] columnListArray = new String[columnList.size()];
		columnList.toArray(columnListArray);
	}

	@Override
	public int compare(Entry<T> o1, Entry<T> o2) {
		int ret;
		for (int i=0; i<getSetPairs.length; i++) {
			if (types[i] == Type.SKIP) continue;
			boolean ascending = types[i] == Type.ASC;
			ret = compareField(o1, o2, i, ascending);
			if (ret != 0) return ret;
		}
		if (sortByUpdateTime == Type.SKIP) {
			return 0;
		}
		ret = o1.getUpdateCount().compareTo (o2.getUpdateCount());
		return sortByUpdateTime == Type.ASC ? ret : -ret;
	}
	
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private int compareField (Entry<T> o1, Entry<T> o2, int index, boolean ascending) {
		
		Object field1 = getSetPairs[index].get(o1.getSpaceEntry());
		Object field2 = getSetPairs[index].get(o2.getSpaceEntry());
		if (field1 == null && field2 == null) return 0;
		if (field1 == null) return ascending ? -1 : 1;
		if (field2 == null) return ascending ? 1 : -1;
		int ret;
		if (field1 instanceof Comparable) {
			ret = ((Comparable)field1).compareTo(field2);
		} else {
			ret = field1.toString().compareTo(field2.toString());
		} 
		return ascending ? ret : -ret;
	}
	
	public String constructSqlString (SqlFormat format) {
		if (getSetPairs.length == 0) {
			return "";
		}
		StringBuffer ret = new StringBuffer();
		ret.append("ORDER BY ");
		String comma = "";
		for (int i= 0; i< getSetPairs.length; i++) {
			if (types[i] == Type.SKIP) {
				continue;
			}
			GetSetPair<T> gs = getSetPairs[i];
			ret.append(comma);
			comma =", ";
			String esc = columnEscList[i];
			if (format == SqlFormat.GIGASPACES) {
				esc = "`";
			}
			ret.append(esc);
			ret.append(gs.getName());
			ret.append(esc);
			if (types[i] == Type.DESC) {
				ret.append(" DESC");
			}
		}
		return ret.toString();
	}
}