Created
July 19, 2012 18:21
-
-
Save dav-rob/3145802 to your computer and use it in GitHub Desktop.
3 Letters Plus Number String Sort
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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