001: package gnu.xquery.util;
002:
003: import java.io.*;
004:
005: public class NamedCollator
006: /* #ifdef JAVA2 */
007: extends java.text.Collator
008: /* #endif */
009: implements Externalizable {
010: /* #ifdef JAVA2 */
011: java.text.Collator collator;
012: /* #endif */
013:
014: String name;
015:
016: public static final String UNICODE_CODEPOINT_COLLATION = "http://www.w3.org/2005/xpath-functions/collation/codepoint";
017:
018: public static NamedCollator make(String name) {
019: NamedCollator coll = new NamedCollator();
020: coll.name = name;
021: coll.resolve();
022: return coll;
023: }
024:
025: public String getName() {
026: return name;
027: }
028:
029: public static NamedCollator find(String name) {
030: return make(name);
031: }
032:
033: public static final NamedCollator codepointCollation = new NamedCollator();
034: static {
035: codepointCollation.name = UNICODE_CODEPOINT_COLLATION;
036: }
037:
038: public void resolve() {
039: if (name != null && !name.equals(UNICODE_CODEPOINT_COLLATION)) {
040: // FIXME!
041: throw new RuntimeException("unknown collation: " + name);
042: }
043: }
044:
045: /** Compares two strings lexicographically by codepoint.
046: * Same as {@code String.compareTo} but handles surrogate characters.
047: * @return -1, 0, or 1 depending on their relative order.
048: */
049: public static int codepointCompare(String str1, String str2) {
050: int i1 = 0, i2 = 0;
051: int len1 = str1.length();
052: int len2 = str2.length();
053: for (;;) {
054: if (i1 == len1)
055: return i2 == len2 ? 0 : -1;
056: if (i2 == len2)
057: return 1;
058: int c1 = str1.charAt(i1++);
059: if (c1 >= 0xD800 && c1 < 0xDC00 && i1 < len1)
060: c1 = (c1 - 0xD800) * 0x400
061: + (str1.charAt(i1++) - 0xDC00) + 0x10000;
062: int c2 = str2.charAt(i2++);
063: if (c2 >= 0xD800 && c2 < 0xDC00 && i2 < len2)
064: c2 = (c2 - 0xD800) * 0x400
065: + (str2.charAt(i2++) - 0xDC00) + 0x10000;
066: if (c1 != c2)
067: return c1 < c2 ? -1 : 1;
068: }
069: }
070:
071: public int compare(String str1, String str2) {
072: /* #ifdef JAVA2 */
073: if (collator != null)
074: return collator.compare(str1, str2);
075: /* #endif */
076: return codepointCompare(str1, str2);
077: }
078:
079: /* #ifdef JAVA2 */
080: public java.text.CollationKey getCollationKey(String source) {
081: return collator.getCollationKey(source);
082: }
083:
084: /* #endif */
085:
086: public int hashCode() {
087: /* #ifdef JAVA2 */
088: if (collator != null)
089: return collator.hashCode();
090: /* #endif */
091: return 0;
092: }
093:
094: public void writeExternal(ObjectOutput out) throws IOException {
095: out.writeUTF(name);
096: }
097:
098: public void readExternal(ObjectInput in) throws IOException,
099: ClassNotFoundException {
100: name = in.readUTF();
101: resolve();
102: }
103: }
|