001: package net.sf.saxon.sort;
002:
003: import net.sf.saxon.Configuration;
004: import net.sf.saxon.trans.XPathException;
005:
006: import java.net.URI;
007: import java.net.URISyntaxException;
008: import java.text.Collator;
009: import java.util.Comparator;
010: import java.util.Locale;
011: import java.util.StringTokenizer;
012:
013: /**
014: * StandardCollationURIResolver allows a Collation to be created given
015: * a URI starting with "http://saxon.sf.net/collation?" followed by a set of query parameters.
016: */
017:
018: public class StandardCollationURIResolver implements
019: CollationURIResolver {
020:
021: private static final StandardCollationURIResolver theInstance = new StandardCollationURIResolver();
022:
023: /**
024: * The class is a singleton
025: */
026: private StandardCollationURIResolver() {
027: }
028:
029: /**
030: * Return the singleton instance of this class
031: */
032:
033: public static final StandardCollationURIResolver getInstance() {
034: return theInstance;
035: }
036:
037: /**
038: * Make a collator with given properties
039: * @param langAtt the language
040: * @param strengthAtt the collation strength: primary, secondary, tertiary, or identical
041: * @param decompositionAtt whether strings are normalized into Unicode decomposed normal form:
042: * none, standard, or full
043: * @return the collator
044: */
045:
046: private static Collator makeUsingProperties(String langAtt,
047: String strengthAtt, String decompositionAtt) {
048:
049: Collator collator;
050: // Start with the lang attribute
051:
052: if (langAtt != null) {
053: collator = Collator.getInstance(getLocale(langAtt));
054: } else {
055: collator = Collator.getInstance(); // use default locale
056: }
057:
058: if (strengthAtt != null && collator instanceof Collator) {
059: if (strengthAtt.equals("primary")) {
060: collator.setStrength(Collator.PRIMARY);
061: } else if (strengthAtt.equals("secondary")) {
062: collator.setStrength(Collator.SECONDARY);
063: } else if (strengthAtt.equals("tertiary")) {
064: collator.setStrength(Collator.TERTIARY);
065: } else if (strengthAtt.equals("identical")) {
066: collator.setStrength(Collator.IDENTICAL);
067: } else {
068: //throw new XPathException.Dynamic("Collation strength must be primary, secondary, tertiary, or identical");
069: }
070: }
071:
072: if (decompositionAtt != null && collator instanceof Collator) {
073: if (decompositionAtt.equals("none")) {
074: collator.setDecomposition(Collator.NO_DECOMPOSITION);
075: } else if (decompositionAtt.equals("standard")) {
076: collator
077: .setDecomposition(Collator.CANONICAL_DECOMPOSITION);
078: } else if (decompositionAtt.equals("full")) {
079: collator.setDecomposition(Collator.FULL_DECOMPOSITION);
080: } else {
081: //throw new XPathException.Dynamic("Collation decomposition must be none, standard, or full");
082: }
083: }
084: return collator;
085: }
086:
087: /**
088: * Get a locale given a language code in XML format
089: */
090:
091: private static Locale getLocale(String lang) {
092: int hyphen = lang.indexOf("-");
093: String language, country;
094: if (hyphen < 1) {
095: language = lang;
096: country = "";
097: } else {
098: language = lang.substring(1, hyphen);
099: country = lang.substring(hyphen + 1);
100: }
101: return new Locale(language, country);
102: }
103:
104: /**
105: * Create a collator from a parameterized URI
106: * @return null if the collation URI is not suitable
107: */
108:
109: public Comparator resolve(String uri, String base,
110: Configuration config) {
111: if (uri.equals("http://saxon.sf.net/collation")) {
112: return makeUsingProperties(null, null, null);
113: } else if (uri.startsWith("http://saxon.sf.net/collation?")) {
114: URI uuri;
115: try {
116: uuri = new URI(uri);
117: } catch (URISyntaxException err) {
118: return null;
119: }
120: String query = uuri.getQuery();
121: String lang = null;
122: String strength = null;
123: String decomposition = null;
124: String classname = null;
125: StringTokenizer queryTokenizer = new StringTokenizer(query,
126: ";&");
127: while (queryTokenizer.hasMoreElements()) {
128: String param = queryTokenizer.nextToken();
129: int eq = param.indexOf('=');
130: if (eq > 0 && eq < param.length() - 1) {
131: String kw = param.substring(0, eq);
132: String val = param.substring(eq + 1);
133: if (kw.equals("lang")) {
134: lang = val;
135: } else if (kw.equals("strength")) {
136: strength = val;
137: } else if (kw.equals("decomposition")) {
138: decomposition = val;
139: } else if (kw.equals("class")) {
140: classname = val;
141: }
142: }
143: }
144: if (classname != null) {
145: try {
146: return config.makeCollator(classname);
147: } catch (XPathException err) {
148: return null;
149: }
150: }
151: return makeUsingProperties(lang, strength, decomposition);
152: } else {
153: return null;
154: }
155: }
156:
157: }
158:
159: //
160: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
161: // you may not use this file except in compliance with the License. You may obtain a copy of the
162: // License at http://www.mozilla.org/MPL/
163: //
164: // Software distributed under the License is distributed on an "AS IS" basis,
165: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
166: // See the License for the specific language governing rights and limitations under the License.
167: //
168: // The Original Code is: all this file.
169: //
170: // The Initial Developer of the Original Code is Michael Kay
171: //
172: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
173: //
174: // Contributor(s): none.
175: //
|