1 /*
2 * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/function/ext/LocaleFunctionSupport.java,v 1.6 2004/09/19 00:07:30 bewins Exp $
3 * $Revision: 1.6 $
4 * $Date: 2004/09/19 00:07:30 $
5 *
6 * ====================================================================
7 *
8 * Copyright (C) 2000-2002 bob mcwhirter & James Strachan.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions, and the disclaimer that follows
20 * these conditions in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * 3. The name "Jaxen" must not be used to endorse or promote products
24 * derived from this software without prior written permission. For
25 * written permission, please contact license@jaxen.org.
26 *
27 * 4. Products derived from this software may not be called "Jaxen", nor
28 * may "Jaxen" appear in their name, without prior written permission
29 * from the Jaxen Project Management (pm@jaxen.org).
30 *
31 * In addition, we request (but do not require) that you include in the
32 * end-user documentation provided with the redistribution and/or in the
33 * software itself an acknowledgement equivalent to the following:
34 * "This product includes software developed by the
35 * Jaxen Project (http://www.jaxen.org/)."
36 * Alternatively, the acknowledgment may be graphical using the logos
37 * available at http://www.jaxen.org/
38 *
39 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42 * DISCLAIMED. IN NO EVENT SHALL THE Jaxen AUTHORS OR THE PROJECT
43 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * ====================================================================
53 * This software consists of voluntary contributions made by many
54 * individuals on behalf of the Jaxen Project and was originally
55 * created by bob mcwhirter <bob@werken.com> and
56 * James Strachan <jstrachan@apache.org>. For more information on the
57 * Jaxen Project, please see <http://www.jaxen.org/>.
58 *
59 * $Id: LocaleFunctionSupport.java,v 1.6 2004/09/19 00:07:30 bewins Exp $
60 */
61
62 package org.jaxen.function.ext;
63
64 import java.util.List;
65 import java.util.Locale;
66 import java.util.StringTokenizer;
67
68 import org.jaxen.Function;
69 import org.jaxen.Navigator;
70 import org.jaxen.function.StringFunction;
71
72 /***
73 * <p>An abastract base class for Locale-specific extension
74 * functions. This class provides convenience methods that
75 * can be inherited, specifically to find a Locale from
76 * an XPath function argument value.
77 * </p>
78 *
79 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
80 */
81 public abstract class LocaleFunctionSupport implements Function
82 {
83
84 /***
85 * Attempts to convert the given function argument value
86 * into a Locale either via casting,
87 * extracting it from a List
88 * or looking up the named Locale using reflection.
89 *
90 * @param value is either a Locale, a List containing a Locale
91 * or a String containing the name of a Locale
92 * as defined by the Locale static members.
93 *
94 * @return the Locale for the value or null if one could
95 * not be deduced
96 */
97 protected Locale getLocale(Object value, Navigator navigator)
98 {
99 if (value instanceof Locale)
100 {
101 return (Locale) value;
102 }
103 else if(value instanceof List)
104 {
105 List list = (List) value;
106 if ( ! list.isEmpty() )
107 {
108 return getLocale( list.get(0), navigator );
109 }
110 }
111 else {
112 String text = StringFunction.evaluate( value, navigator );
113 if (text != null && text.length() > 0)
114 {
115 return findLocale( text );
116 }
117 }
118 return null;
119 }
120
121 /***
122 * Tries to find a Locale instance by name using xml:lang style encodings
123 * like 'en', 'en-US', 'en-US-Brooklyn'.
124 *
125 * @param localeText is the xml:lang encoding of a Locale
126 * @return the Locale for the given text or null if one could not
127 * be found
128 */
129 protected Locale findLocale(String localeText) {
130 StringTokenizer tokens = new StringTokenizer( localeText, "-" );
131 if (tokens.hasMoreTokens())
132 {
133 String language = tokens.nextToken();
134 if (! tokens.hasMoreTokens())
135 {
136 return findLocaleForLanguage(language);
137 }
138 else
139 {
140 String country = tokens.nextToken();
141 if (! tokens.hasMoreTokens())
142 {
143 return new Locale(language, country);
144 }
145 else
146 {
147 String variant = tokens.nextToken();
148 return new Locale(language, country, variant);
149 }
150 }
151 }
152 return null;
153 }
154
155 /***
156 * Finds the locale with the given language name with no country
157 * or variant, such as Locale.ENGLISH or Locale.FRENCH
158 *
159 * @param language is the language code to look for
160 * @return the Locale for the given language or null if one could not
161 * be found
162 */
163 protected Locale findLocaleForLanguage(String language) {
164 Locale[] locales = Locale.getAvailableLocales();
165 for ( int i = 0, size = locales.length; i < size; i++ )
166 {
167 Locale locale = locales[i];
168 if ( language.equals( locale.getLanguage() ) )
169 {
170 String country = locale.getCountry();
171 if ( country == null || country.length() == 0 )
172 {
173 String variant = locale.getVariant();
174 if ( variant == null || variant.length() == 0 )
175 {
176 return locale;
177 }
178 }
179 }
180 }
181 return null;
182 }
183 }