%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.turbine.services.localization.LocaleTokenizer$1 |
|
|
1 | package org.apache.turbine.services.localization; |
|
2 | ||
3 | /* |
|
4 | * Copyright 2001-2005 The Apache Software Foundation. |
|
5 | * |
|
6 | * Licensed under the Apache License, Version 2.0 (the "License") |
|
7 | * you may not use this file except in compliance with the License. |
|
8 | * You may obtain a copy of the License at |
|
9 | * |
|
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
11 | * |
|
12 | * Unless required by applicable law or agreed to in writing, software |
|
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
15 | * See the License for the specific language governing permissions and |
|
16 | * limitations under the License. |
|
17 | */ |
|
18 | ||
19 | import java.util.ArrayList; |
|
20 | import java.util.Collections; |
|
21 | import java.util.Iterator; |
|
22 | import java.util.Locale; |
|
23 | import java.util.NoSuchElementException; |
|
24 | import java.util.StringTokenizer; |
|
25 | ||
26 | /** |
|
27 | * Parses the HTTP <code>Accept-Language</code> header as per section |
|
28 | * 14.4 of RFC 2068 (HTTP 1.1 header field definitions). |
|
29 | * |
|
30 | * @author <a href="mailto:dlr@collab.net">Daniel Rall</a> |
|
31 | * @version $Id: LocaleTokenizer.java 264148 2005-08-29 14:21:04Z henning $ |
|
32 | */ |
|
33 | public class LocaleTokenizer |
|
34 | implements Iterator |
|
35 | { |
|
36 | /** |
|
37 | * Separates elements of the <code>Accept-Language</code> HTTP |
|
38 | * header. |
|
39 | */ |
|
40 | private static final String LOCALE_SEPARATOR = ","; |
|
41 | ||
42 | /** |
|
43 | * Separates locale from quality within elements. |
|
44 | */ |
|
45 | private static final char QUALITY_SEPARATOR = ';'; |
|
46 | ||
47 | /** |
|
48 | * The default quality value for an <code>AcceptLanguage</code> |
|
49 | * object. |
|
50 | */ |
|
51 | private static final Float DEFAULT_QUALITY = new Float(1.0f); |
|
52 | ||
53 | /** |
|
54 | * The parsed locales. |
|
55 | */ |
|
56 | private ArrayList locales = new ArrayList(3); |
|
57 | ||
58 | /** |
|
59 | * Parses the <code>Accept-Language</code> header. |
|
60 | * |
|
61 | * @param header The <code>Accept-Language</code> header |
|
62 | * (i.e. <code>en, es;q=0.8, zh-TW;q=0.1</code>). |
|
63 | */ |
|
64 | public LocaleTokenizer(String header) |
|
65 | { |
|
66 | StringTokenizer tok = new StringTokenizer(header, LOCALE_SEPARATOR); |
|
67 | while (tok.hasMoreTokens()) |
|
68 | { |
|
69 | AcceptLanguage acceptLang = new AcceptLanguage(); |
|
70 | String element = tok.nextToken().trim(); |
|
71 | int index; |
|
72 | ||
73 | // Record and cut off any quality value that comes after a |
|
74 | // semi-colon. |
|
75 | if ((index = element.indexOf(QUALITY_SEPARATOR)) != -1) |
|
76 | { |
|
77 | String q = element.substring(index); |
|
78 | element = element.substring(0, index); |
|
79 | if ((index = q.indexOf('=')) != -1) |
|
80 | { |
|
81 | try |
|
82 | { |
|
83 | acceptLang.quality = |
|
84 | Float.valueOf(q.substring(index + 1)); |
|
85 | } |
|
86 | catch (NumberFormatException useDefault) |
|
87 | { |
|
88 | } |
|
89 | } |
|
90 | } |
|
91 | ||
92 | element = element.trim(); |
|
93 | ||
94 | // Create a Locale from the language. A dash may separate the |
|
95 | // language from the country. |
|
96 | if ((index = element.indexOf('-')) == -1) |
|
97 | { |
|
98 | // No dash means no country. |
|
99 | acceptLang.locale = new Locale(element, ""); |
|
100 | } |
|
101 | else |
|
102 | { |
|
103 | acceptLang.locale = new Locale(element.substring(0, index), |
|
104 | element.substring(index + 1)); |
|
105 | } |
|
106 | ||
107 | locales.add(acceptLang); |
|
108 | } |
|
109 | ||
110 | // Sort by quality in descending order. |
|
111 | Collections.sort(locales, Collections.reverseOrder()); |
|
112 | } |
|
113 | ||
114 | /** |
|
115 | * @return Whether there are more locales. |
|
116 | */ |
|
117 | public boolean hasNext() |
|
118 | { |
|
119 | return !locales.isEmpty(); |
|
120 | } |
|
121 | ||
122 | /** |
|
123 | * Creates a <code>Locale</code> from the next element of the |
|
124 | * <code>Accept-Language</code> header. |
|
125 | * |
|
126 | * @return The next highest-rated <code>Locale</code>. |
|
127 | * @throws NoSuchElementException No more locales. |
|
128 | */ |
|
129 | public Object next() |
|
130 | { |
|
131 | if (locales.isEmpty()) |
|
132 | { |
|
133 | throw new NoSuchElementException(); |
|
134 | } |
|
135 | return ((AcceptLanguage) locales.remove(0)).locale; |
|
136 | } |
|
137 | ||
138 | /** |
|
139 | * Not implemented. |
|
140 | */ |
|
141 | public final void remove() |
|
142 | { |
|
143 | throw new UnsupportedOperationException(getClass().getName() + |
|
144 | " does not support remove()"); |
|
145 | } |
|
146 | ||
147 | /** |
|
148 | * Struct representing an element of the HTTP |
|
149 | * <code>Accept-Language</code> header. |
|
150 | */ |
|
151 | private class AcceptLanguage implements Comparable |
|
152 | { |
|
153 | /** |
|
154 | * The language and country. |
|
155 | */ |
|
156 | Locale locale; |
|
157 | ||
158 | /** |
|
159 | * The quality of our locale (as values approach |
|
160 | * <code>1.0</code>, they indicate increased user preference). |
|
161 | */ |
|
162 | Float quality = DEFAULT_QUALITY; |
|
163 | ||
164 | public final int compareTo(Object acceptLang) |
|
165 | { |
|
166 | return quality.compareTo(((AcceptLanguage) acceptLang).quality); |
|
167 | } |
|
168 | } |
|
169 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |