for (int keyNameI = 0; keyNameI < keyNamesLn; keyNameI++) {
try {
key = ((TemplateHashModel) key).get(keyNames[keyNameI]);
} catch (ClassCastException e) {
if (!(key instanceof TemplateHashModel)) {
throw new TemplateModelException(
startErrorMessage(keyNamesLn, i)
+ (keyNameI == 0
? "Sequence items must be hashes when using ?sort_by. "
: "The " + StringUtil.jQuote(keyNames[keyNameI - 1])
+ " subvariable is not a hash, so ?sort_by "
+ "can't proceed with getting the "
+ StringUtil.jQuote(keyNames[keyNameI])
+ " subvariable."));
} else {
throw e;
}
}
if (key == null) {
throw new TemplateModelException(
startErrorMessage(keyNamesLn, i)
+ "The " + StringUtil.jQuote(keyNames[keyNameI])
+ " subvariable was not found.");
}
} // for each key
if (keyType == KEY_TYPE_NOT_YET_DETECTED) {
if (key instanceof TemplateScalarModel) {
keyType = KEY_TYPE_STRING;
keyComparator = new LexicalKVPComparator(
Environment.getCurrentEnvironment().getCollator());
} else if (key instanceof TemplateNumberModel) {
keyType = KEY_TYPE_NUMBER;
keyComparator = new NumericalKVPComparator(
Environment.getCurrentEnvironment()
.getArithmeticEngine());
} else if (key instanceof TemplateDateModel) {
keyType = KEY_TYPE_DATE;
keyComparator = new DateKVPComparator();
} else if (key instanceof TemplateBooleanModel) {
keyType = KEY_TYPE_BOOLEAN;
keyComparator = new BooleanKVPComparator();
} else {
throw new TemplateModelException(
startErrorMessage(keyNamesLn, i)
+ "Values used for sorting must be numbers, strings, "
+ "date/times or booleans.");
}
}
switch(keyType) {
case KEY_TYPE_STRING:
try {
res.add(new KVP(
((TemplateScalarModel) key).getAsString(),
item));
} catch (ClassCastException e) {
if (!(key instanceof TemplateScalarModel)) {
throw newInconsistentSortKeyTypeException(
keyNamesLn, "string", "strings", i);
} else {
throw e;
}
}
break;
case KEY_TYPE_NUMBER:
try {
res.add(new KVP(
((TemplateNumberModel) key).getAsNumber(),
item));
} catch (ClassCastException e) {
if (!(key instanceof TemplateNumberModel)) {
throw newInconsistentSortKeyTypeException(
keyNamesLn, "number", "numbers", i);
}
}
break;
case KEY_TYPE_DATE:
try {
res.add(new KVP(
((TemplateDateModel) key).getAsDate(),
item));
} catch (ClassCastException e) {
if (!(key instanceof TemplateDateModel)) {
throw newInconsistentSortKeyTypeException(
keyNamesLn, "date/time", "date/times", i);
}
}
break;
case KEY_TYPE_BOOLEAN:
try {
res.add(new KVP(
((TemplateBooleanModel) key).getAsBoolean() ?
Boolean.TRUE : Boolean.FALSE,
item));
} catch (ClassCastException e) {
if (!(key instanceof TemplateBooleanModel)) {
throw newInconsistentSortKeyTypeException(
keyNamesLn, "boolean", "booleans", i);
}
}
break;
default:
throw new RuntimeException("FreeMarker bug: Unexpected key type");
}
}
// Sort tje List[KVP]:
try {
Collections.sort(res, keyComparator);
} catch (Exception exc) {
throw new TemplateModelException(
startErrorMessage(keyNamesLn)
+ "Unexpected error while sorting:" + exc, exc);
}
// Convert the List[KVP] to List[V]: