| <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>LocaleTokenizer.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Fulcrum Localization</a> > <a href="index.source.html" class="el_package">org.apache.fulcrum.localization</a> > <span class="el_source">LocaleTokenizer.java</span></div><h1>LocaleTokenizer.java</h1><pre class="source lang-java linenums">package org.apache.fulcrum.localization; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.Locale; |
| import java.util.NoSuchElementException; |
| import java.util.Objects; |
| import java.util.StringTokenizer; |
| |
| /** |
| * Parses the HTTP <code>Accept-Language</code> header as per section |
| * 14.4 of RFC 2068 (HTTP 1.1 header field definitions). |
| * |
| * @author <a href="mailto:dlr@collab.net">Daniel Rall</a> |
| * @version $Id$ |
| */ |
| public class LocaleTokenizer |
| implements Iterator<Object> |
| { |
| /** |
| * Separates elements of the <code>Accept-Language</code> HTTP |
| * header. |
| */ |
| private static final String LOCALE_SEPARATOR = ","; |
| |
| /** |
| * Separates locale from quality within elements. |
| */ |
| private static final char QUALITY_SEPARATOR = ';'; |
| |
| /** |
| * The default quality value for an <code>AcceptLanguage</code> |
| * object. |
| */ |
| <span class="fc" id="L56"> protected static final Float DEFAULT_QUALITY = 1.0f;</span> |
| |
| /** |
| * The parsed locales. |
| */ |
| <span class="fc" id="L61"> private ArrayList<AcceptLanguage> locales = new ArrayList<>(3);</span> |
| |
| /** |
| * Parses the <code>Accept-Language</code> header. |
| * |
| * @param header The <code>Accept-Language</code> header |
| * (i.e. <code>en, es;q=0.8, zh-TW;q=0.1</code>). |
| */ |
| public LocaleTokenizer(String header) |
| <span class="fc" id="L70"> {</span> |
| <span class="fc" id="L71"> StringTokenizer tok = new StringTokenizer(header, LOCALE_SEPARATOR);</span> |
| <span class="fc bfc" id="L72" title="All 2 branches covered."> while (tok.hasMoreTokens())</span> |
| { |
| <span class="fc" id="L74"> AcceptLanguage acceptLang = new AcceptLanguage();</span> |
| <span class="fc" id="L75"> String element = tok.nextToken().trim();</span> |
| int index; |
| |
| // Record and cut off any quality value that comes after a |
| // semi-colon. |
| <span class="fc bfc" id="L80" title="All 2 branches covered."> if ( (index = element.indexOf(QUALITY_SEPARATOR)) != -1 )</span> |
| { |
| <span class="fc" id="L82"> String q = element.substring(index);</span> |
| <span class="fc" id="L83"> element = element.substring(0, index);</span> |
| <span class="pc bpc" id="L84" title="1 of 2 branches missed."> if ( (index = q.indexOf('=')) != -1 )</span> |
| { |
| try |
| { |
| <span class="fc" id="L88"> acceptLang.quality =</span> |
| <span class="fc" id="L89"> Float.valueOf(q.substring(index + 1));</span> |
| } |
| <span class="nc" id="L91"> catch (NumberFormatException useDefault)</span> |
| { |
| // ignore |
| <span class="fc" id="L94"> }</span> |
| } |
| } |
| |
| <span class="fc" id="L98"> element = element.trim();</span> |
| |
| // Create a Locale from the language. A dash may separate the |
| // language from the country. |
| <span class="fc bfc" id="L102" title="All 2 branches covered."> if ( (index = element.indexOf('-')) == -1 )</span> |
| { |
| // No dash means no country. |
| <span class="fc" id="L105"> acceptLang.locale = new Locale(element, "");</span> |
| } |
| else |
| { |
| <span class="fc" id="L109"> acceptLang.locale = new Locale(element.substring(0, index),</span> |
| <span class="fc" id="L110"> element.substring(index + 1));</span> |
| } |
| |
| <span class="fc" id="L113"> locales.add(acceptLang);</span> |
| <span class="fc" id="L114"> }</span> |
| |
| // Sort by quality in descending order. |
| <span class="fc" id="L117"> locales.sort(Collections.reverseOrder());</span> |
| <span class="fc" id="L118"> }</span> |
| |
| /** |
| * @return Whether there are more locales. |
| */ |
| public boolean hasNext() |
| { |
| <span class="nc bnc" id="L125" title="All 2 branches missed."> return !locales.isEmpty();</span> |
| } |
| |
| /** |
| * Creates a <code>Locale</code> from the next element of the |
| * <code>Accept-Language</code> header. |
| * |
| * @return The next highest-rated <code>Locale</code>. |
| * @throws NoSuchElementException No more locales. |
| */ |
| public Object next() |
| { |
| <span class="pc bpc" id="L137" title="1 of 2 branches missed."> if (locales.isEmpty())</span> |
| { |
| <span class="nc" id="L139"> throw new NoSuchElementException();</span> |
| } |
| <span class="fc" id="L141"> return (locales.remove(0)).locale;</span> |
| } |
| |
| /** |
| * Not implemented. |
| */ |
| @Override |
| public final void remove() |
| { |
| <span class="nc" id="L150"> throw new UnsupportedOperationException(getClass().getName() +</span> |
| " does not support remove()"); |
| } |
| |
| /** |
| * Struct representing an element of the HTTP |
| * <code>Accept-Language</code> header. |
| */ |
| <span class="fc" id="L158"> protected static class AcceptLanguage implements Comparable<Object></span> |
| { |
| /** |
| * The language and country. |
| */ |
| Locale locale; |
| |
| /** |
| * The quality of our locale (as values approach |
| * <code>1.0</code>, they indicate increased user preference). |
| */ |
| <span class="fc" id="L169"> Float quality = DEFAULT_QUALITY;</span> |
| |
| @Override |
| public int compareTo(Object acceptLang) |
| { |
| <span class="pc bpc" id="L174" title="1 of 2 branches missed."> if ( acceptLang == null )</span> |
| <span class="nc" id="L175"> throw new NullPointerException("AcceptLanguage not found");</span> |
| |
| <span class="pc bpc" id="L177" title="1 of 2 branches missed."> if ( acceptLang instanceof AcceptLanguage )</span> |
| { |
| <span class="fc" id="L179"> Float q2 = ((AcceptLanguage) acceptLang).quality;</span> |
| <span class="fc" id="L180"> return quality.compareTo( q2 );</span> |
| } else { |
| <span class="nc" id="L182"> throw new NullPointerException("The object to compare is not the correct type");</span> |
| } |
| |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| <span class="nc bnc" id="L189" title="All 2 branches missed."> if (this == o) return true;</span> |
| <span class="nc bnc" id="L190" title="All 2 branches missed."> if (!(o instanceof AcceptLanguage)) return false;</span> |
| <span class="nc" id="L191"> AcceptLanguage that = (AcceptLanguage) o;</span> |
| <span class="nc" id="L192"> return quality.equals(that.quality);</span> |
| } |
| |
| @Override |
| public int hashCode() { |
| <span class="nc" id="L197"> return Objects.hash(locale, quality);</span> |
| } |
| } |
| } |
| </pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.8.7.202105040129</span></div></body></html> |