1
18 package org.torweg.pulse.service.request;
19
20 import java.util.Collections;
21 import java.util.Locale;
22 import java.util.SortedSet;
23 import java.util.TreeSet;
24
25 import javax.servlet.http.HttpServletRequest;
26
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30
37 public final class AcceptLanguages {
38
39
42 private static final Logger LOGGER = LoggerFactory
43 .getLogger(AcceptLanguages.class);
44
45
48 private SortedSet<AcceptLanguages.Value> values;
49
50
53 public AcceptLanguages() {
54 super();
55 this.values = new TreeSet<AcceptLanguages.Value>();
56 }
57
58
64 AcceptLanguages(final HttpServletRequest req) {
65 super();
66 parseHeader(req.getHeader("Accept-Language"));
67 }
68
69
75 private void parseHeader(final String header) {
76 SortedSet<AcceptLanguages.Value> parsedLanguagesByQuality = new TreeSet<AcceptLanguages.Value>();
77 if (header == null) {
78 this.values = Collections
79 .unmodifiableSortedSet(parsedLanguagesByQuality);
80 return;
81 }
82 int position = 0;
83 String[] languages = header.split(",");
84 for (String language : languages) {
85 String[] langQuality = language.split(";q=");
86 if (langQuality.length == 1) {
87 parsedLanguagesByQuality.add(new Value(langQuality[0],
88 position++));
89 } else {
90 double q = Double.valueOf(langQuality[1].trim());
91 if ((q > 0) && (q <= 1)) {
92 parsedLanguagesByQuality.add(new Value(langQuality[0], q,
93 position++));
94 }
95 }
96 }
97 this.values = Collections
98 .unmodifiableSortedSet(parsedLanguagesByQuality);
99
100 if (LOGGER.isDebugEnabled()) {
102 StringBuilder builder = new StringBuilder();
103 for (AcceptLanguages.Value value : this.values) {
104 builder.append(value.toString());
105 builder.append(';');
106 }
107 LOGGER.debug(builder.toString());
108 }
109 }
110
111
114 public SortedSet<AcceptLanguages.Value> getValues() {
115 return this.values;
116 }
117
118
121 public static final class Value implements
122 Comparable<AcceptLanguages.Value> {
123
124
127 private Locale locale;
128
129
132 private final double quality;
133
134
137 private final int position;
138
139
147 protected Value(final String lang, final int p) {
148 super();
149 parseLocale(lang);
150 this.quality = 1;
151 this.position = p;
152 }
153
154
164 protected Value(final String lang, final double q, final int p) {
165 super();
166 parseLocale(lang);
167 if ((q <= 0) || (q > 1)) {
168 throw new IllegalArgumentException("Quality must be between 0 "
169 + "(excluded) and 1 (included).");
170 }
171 this.quality = q;
172 this.position = p;
173 }
174
175
179 private void parseLocale(final String lang) {
180 String[] parts = lang.trim().split("-");
181 if (parts.length == 1) {
182 this.locale = new Locale(parts[0]);
183 } else {
184 this.locale = new Locale(parts[0], parts[1]);
185 }
186 }
187
188
191 public Locale getLocale() {
192 return this.locale;
193 }
194
195
198 public double getQuality() {
199 return this.quality;
200 }
201
202
210 public int compareTo(final AcceptLanguages.Value o) {
211 if (this.quality == o.quality) {
212 if (this.position < o.position) {
213 return -1;
214 }
215 return 1;
216 } else if (this.quality > o.quality) {
217 return -1;
218 }
219 return 1;
220 }
221
222
225 @Override
226 public int hashCode() {
228 final int prime = 31; int result = 1;
230 result = prime * result
231 + ((this.locale == null) ? 0 : this.locale.hashCode());
232 long temp;
233 temp = Double.doubleToLongBits(this.quality);
234 result = prime * result + (int) (temp ^ (temp >>> 32));
235 return result;
236 }
238
243 @Override
244 public boolean equals(final Object obj) {
245 if (this == obj) {
246 return true;
247 }
248 if (obj == null) {
249 return false;
250 }
251 if (getClass() != obj.getClass()) {
252 return false;
253 }
254 AcceptLanguages.Value other = (AcceptLanguages.Value) obj;
255 if (this.locale == null) {
256 if (other.locale != null) {
257 return false;
258 }
259 } else if (!this.locale.equals(other.locale)) {
260 return false;
261 }
262 if (Double.doubleToLongBits(this.quality) != Double
263 .doubleToLongBits(other.quality)) {
264 return false;
265 }
266 if (this.position != other.position) {
267 return false;
268 }
269 return true;
270 }
271
272
275 @Override
276 public String toString() {
277 StringBuilder builder = new StringBuilder("Value[");
278 builder.append(locale.toString()).append(",q:").append(quality)
279 .append(",p:").append(position).append(']');
280 return builder.toString();
281 }
282
283 }
284
285 }
286