Skip to content

Instantly share code, notes, and snippets.

@dav-rob
Created July 19, 2012 18:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dav-rob/3145802 to your computer and use it in GitHub Desktop.
Save dav-rob/3145802 to your computer and use it in GitHub Desktop.
3 Letters Plus Number String Sort
package com.cs.cts.crm.elasticsearch.util;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.elasticsearch.script.AbstractFloatSearchScript;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.NativeScriptFactory;
/**
* This class is run in isolation on the ElasticSearch Server, so can have no dependencies on other classes in CMT.
*
* @author drober20
*
*/
public class CustomColumnSorterFactory implements NativeScriptFactory{
private final static Log LOG = LogFactory.getLog(CustomColumnSorterFactory.class);
@Override
public ExecutableScript newScript(Map<String, Object> params) {
LOG.info("Last string float value = " + last);
return new ColumnSortScript(params);
}
private static String lastString = "\u007F";// 8 bit last string
/**
* This method is to allow us to sort on more then one letter in a string when we only have the
* option of returning a single Float (or Int or Double) value from 'sortValue' method for each
* document, rather than being able to compare one document with another.
*
* @param custAttrValue
* @return
*/
private static Float getFirstThreeLettersFloatValue(String custAttrValue) {
if (custAttrValue.length() == 0){
throw new IllegalStateException("Null or empty strings should be initialised to 'z'");
}
int threeCharValue = 0;
int sortCharLength = custAttrValue.length() < 3 ? custAttrValue.length() : 3;
for (int i = 0; i < sortCharLength;i++ ){
int singleCharValue = custAttrValue.charAt(i);
// force 8 bit letters
// may be able to stop this by returning doubles from 'sortValue' method.
if (singleCharValue > 127){
singleCharValue = 127;
}
if (i==0){
threeCharValue += singleCharValue << 16;
} else if (i == 1) {
threeCharValue += singleCharValue << 8;
} else {
threeCharValue += singleCharValue;
}
}
return new Float (threeCharValue);
}
protected static Float last = getFirstThreeLettersFloatValue(lastString);
private static Float getAsFloat(String custAttValue1) {
try {
Float theFloat = Float.valueOf(custAttValue1);
return theFloat;
}catch (NumberFormatException nfe){
return null;
}
}
public static Float getScore(List<Map> custColsMapList, String indexFieldName, boolean isASC){
String custAttrValue = getCustomAttrValue(custColsMapList, indexFieldName);
Float score = getFloatScore(custAttrValue, isASC);
return score;
}
public static String getCustomAttrValue(final List<Map> custColsMapList, String indexFieldName) {
String custAttValue = null;
for (Map custColsMap : custColsMapList) {
String ccId = (String)custColsMap.get("ccId");
if (ccId.equals(indexFieldName)){
//LOG.info("ccId = " + ccId );
Object value = custColsMap.get("value");
//LOG.info("value = " + value );
if (value != null){
return value.toString();
}
}
}
return custAttValue;
}
public static Float getFloatScore(String custAttrValue, boolean isASC) {
boolean isEmpty = custAttrValue == null || custAttrValue.trim().equals("");
if (isEmpty){
return isASC ? last : 0;
}
Float floatValue = getAsFloat(custAttrValue);
if (floatValue == null){
floatValue = getFirstThreeLettersFloatValue(custAttrValue.toUpperCase());
} else {
// reduce the numbers value to give the letters a bit more room in the float range.
// tried doing floatValue = floatValue - 1000000 to give the numbers more room
// below the letters, but it doesn't work.
floatValue = floatValue;
}
return floatValue;
}
private static Float getScoreForDirection(boolean isASC, Float score) {
if (isASC){
score = 0- score;
}
return score;
}
static class ColumnSortScript extends AbstractFloatSearchScript {
private Map<String, Object> params;
public ColumnSortScript(Map<String, Object> params) {
this.params = params;
}
@Override
public float runAsFloat() {
try {
String sortDirection = (String)params.get("sortDirection");
boolean isASC = sortDirection == null || (sortDirection != null && !sortDirection.toUpperCase().trim().equals("DESC"));
Object customColsMapList = source().get("customColumns");
//LOG.info(" Source = " + customColsMapList.getClass());
if (customColsMapList == null ){
float defaultReturn = defaultReturn(isASC);
//LOG.info("Default return = " + defaultReturn);
return defaultReturn;
//return getScoreForDirection(isASC, last);
}
List<Map> custColsMapList = (List<Map>) customColsMapList;
if (CSUtils.isEmpty(custColsMapList)){
float defaultReturn = defaultReturn(isASC);
//LOG.info("Default return = " + defaultReturn);
return defaultReturn;
}
String indexFieldName = (String)params.get("indexFieldName");
Float score = getScore(custColsMapList, indexFieldName, isASC);
score = getScoreForDirection(isASC, score);
//LOG.info("score = " + score);
return score;
} catch (Exception e) {
LOG.error("Unexpected error sorting custom columns.", e);
return 0;
}
}
private float defaultReturn(boolean isASC) {
if (isASC){
return 0 - last;
} else {
return 0;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment