package er.extensions.foundation; import java.text.Collator; import java.util.Locale; import com.webobjects.eocontrol.EOQualifier; import com.webobjects.eocontrol.EOSortOrdering; import com.webobjects.foundation.NSKeyValueCoding; import com.webobjects.foundation.NSSelector; import er.extensions.eof.qualifiers.ERXRegExQualifier; import er.extensions.localization.ERXLocalizer; /** * Comparison support that sorts strings in a locale-savvy manner and adds * support for regex in-memory matching when using qualifier strings. * * @author ak on Fri Apr 11 2003 */ public class ERXComparisonSupport { private static Class stringClass = String.class; private static final int MAGIC = -42; private static boolean fixAnyway; public static void initialize() { EOSortOrdering.ComparisonSupport.setSupportForClass(new StringSortSupport(), String.class); EOQualifier.ComparisonSupport.setSupportForClass(new StringQualifierSupport(), String.class); fixAnyway = ERXProperties.booleanForKeyWithDefault("er.extensions.ERXComparisonSupport.fixAnyway", true); } /** * Support class that adds regex matching, causing it to use the correct selector <code>String.matches(String)</code> * instead of <code>String.matches(Object)</code>. * We would not need this if there was a way to set the selector by name in EOQualifier... */ protected static class StringQualifierSupport extends EOQualifier.ComparisonSupport { @Override public boolean _compareWithArbitrarySelector(Object aLeft, Object aRight, NSSelector aSelector) { if(aSelector.name().equals(ERXRegExQualifier.MatchesSelectorName)) { aSelector = ERXRegExQualifier.MatchesSelector; } return super._compareWithArbitrarySelector(aLeft, aRight, aSelector); } } protected static class StringSortSupport extends EOSortOrdering.ComparisonSupport { private Collator collator() { Locale locale = ERXLocalizer.currentLocalizer().locale(); if(locale != null) { locale = Locale.getDefault(); } return Collator.getInstance(locale); } private static int _handleNulls(Object object1, Object object2) { if (object1 == null || object1 == NSKeyValueCoding.NullValue) { if (object2 == null || object2 == NSKeyValueCoding.NullValue) return 0; return -1; } if (object2 == null || object2 == NSKeyValueCoding.NullValue) return 1; return MAGIC; } @Override protected int _genericCompareTo(Object object1, Object object2) { // AK: unfortunately, the is no combination that allows us to keep // sorting by case, but disregard the Umlaut characters. So // we just use the default, unless we come up with a better idea... if(fixAnyway) { int i = _handleNulls(object1, object2); if (i != MAGIC) return i; Class clazz = object1.getClass(); if (clazz == stringClass) { return collator().compare(object1.toString(),object2.toString()); } } return super._genericCompareTo(object1, object2); } @Override protected int _genericCaseInsensitiveCompareTo(Object object1, Object object2) { int i = _handleNulls(object1, object2); if (i != MAGIC) return i; Class clazz = object1.getClass(); if (clazz == stringClass) { return collator().compare(object1.toString().toUpperCase(),object2.toString().toUpperCase()); } return super._genericCaseInsensitiveCompareTo(object1, object2); } } }