001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.http.header;
014
015import java.util.function.*;
016
017import org.apache.juneau.*;
018import org.apache.juneau.http.annotation.*;
019import org.apache.juneau.internal.*;
020
021/**
022 * Represents a parsed <l>Accept-Language</l> HTTP request header.
023 *
024 * <p>
025 * List of acceptable human languages for response.
026 *
027 * <h5 class='figure'>Example</h5>
028 * <p class='bcode'>
029 *    Accept-Language: en-US
030 * </p>
031 *
032 * <h5 class='topic'>RFC2616 Specification</h5>
033 *
034 * The Accept-Language request-header field is similar to Accept, but restricts the set of natural languages that are
035 * preferred as a response to the request.
036 * Language tags are defined in section 3.10.
037 *
038 * <p class='bcode'>
039 *    Accept-Language = "Accept-Language" ":"
040 *                      1#( language-range [ ";" "q" "=" qvalue ] )
041 *    language-range  = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
042 * </p>
043 *
044 * <p>
045 * Each language-range MAY be given an associated quality value which represents an estimate of the user's preference
046 * for the languages specified by that range.
047 * The quality value defaults to "q=1".
048 * For example...
049 * <p class='bcode'>
050 *    Accept-Language: da, en-gb;q=0.8, en;q=0.7
051 * </p>
052 * <p>
053 * ...would mean: "I prefer Danish, but will accept British English and other types of English."
054 *
055 * <p>
056 * A language-range matches a language-tag if it exactly equals the tag, or if it exactly equals a prefix of the tag
057 * such that the first tag character following the prefix is "-".
058 *
059 * <p>
060 * The special range "*", if present in the Accept-Language field, matches every tag not matched by any other range
061 * present in the Accept-Language field.
062 *
063 * <p>
064 * Note: This use of a prefix matching rule does not imply that language tags are assigned to languages in such a way
065 * that it is always true that if a user understands a language with a certain
066 * tag, then this user will also understand all languages with tags for which this tag is a prefix.
067 * The prefix rule simply allows the use of prefix tags if this is the case.
068 *
069 * <p>
070 * The language quality factor assigned to a language-tag by the Accept-Language field is the quality value of the
071 * longest language- range in the field that matches the language-tag.
072 *
073 * <p>
074 * If no language- range in the field matches the tag, the language quality factor assigned is 0.
075 *
076 * <p>
077 * If no Accept-Language header is present in the request, the server SHOULD assume that all languages are equally
078 * acceptable.
079 *
080 * <p>
081 * If an Accept-Language header is present, then all languages which are assigned a quality factor greater than 0 are
082 * acceptable.
083 *
084 * <p>
085 * It might be contrary to the privacy expectations of the user to send an Accept-Language header with the complete
086 * linguistic preferences of the user in every request.
087 * For a discussion of this issue, see section 15.1.4.
088 *
089 * <p>
090 * As intelligibility is highly dependent on the individual user, it is recommended that client applications make the
091 * choice of linguistic preference available to the user.
092 * If the choice is not made available, then the Accept-Language header field MUST NOT be given in the request.
093 *
094 * <p>
095 * Note: When making the choice of linguistic preference available to the user, we remind implementors of the fact that
096 * users are not familiar with the details of language matching as described above, and should provide appropriate
097 * guidance.
098 * As an example, users might assume that on selecting "en-gb", they will be served any kind of English document if
099 * British English is not available.
100 * A user agent might suggest in such a case to add "en" to get the best matching behavior.
101 *
102 * <h5 class='section'>See Also:</h5><ul>
103 *    <li class='link'><a class="doclink" href="../../../../../index.html#juneau-rest-common">juneau-rest-common</a>
104 *    <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a>
105 * </ul>
106 *
107 * @serial exclude
108 */
109@Header("Accept-Language")
110public class AcceptLanguage extends BasicStringRangesHeader {
111
112   //-----------------------------------------------------------------------------------------------------------------
113   // Static
114   //-----------------------------------------------------------------------------------------------------------------
115
116   private static final long serialVersionUID = 1L;
117   private static final String NAME = "Accept-Language";
118
119   private static final Cache<String,AcceptLanguage> CACHE = Cache.of(String.class, AcceptLanguage.class).build();
120
121   /**
122    * Static creator.
123    *
124    * @param value
125    *    The header value.
126    *    <br>Must be parsable by {@link StringRanges#of(String)}.
127    *    <br>Can be <jk>null</jk>.
128    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
129    */
130   public static AcceptLanguage of(String value) {
131      return value == null ? null : CACHE.get(value, ()->new AcceptLanguage(value));
132   }
133
134   /**
135    * Static creator.
136    *
137    * @param value
138    *    The header value.
139    *    <br>Can be <jk>null</jk>.
140    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
141    */
142   public static AcceptLanguage of(StringRanges value) {
143      return value == null ? null : new AcceptLanguage(value);
144   }
145
146   /**
147    * Static creator with delayed value.
148    *
149    * <p>
150    * Header value is re-evaluated on each call to {@link #getValue()}.
151    *
152    * @param value
153    *    The supplier of the header value.
154    *    <br>Can be <jk>null</jk>.
155    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
156    */
157   public static AcceptLanguage of(Supplier<StringRanges> value) {
158      return value == null ? null : new AcceptLanguage(value);
159   }
160
161   //-----------------------------------------------------------------------------------------------------------------
162   // Instance
163   //-----------------------------------------------------------------------------------------------------------------
164
165   /**
166    * Constructor.
167    *
168    * @param value
169    *    The header value.
170    *    <br>Must be parsable by {@link StringRanges#of(String)}.
171    *    <br>Can be <jk>null</jk>.
172    */
173   public AcceptLanguage(String value) {
174      super(NAME, value);
175   }
176
177   /**
178    * Constructor.
179    *
180    * @param value
181    *    The header value.
182    *    <br>Can be <jk>null</jk>.
183    */
184   public AcceptLanguage(StringRanges value) {
185      super(NAME, value);
186   }
187
188   /**
189    * Constructor with delayed value.
190    *
191    * <p>
192    * Header value is re-evaluated on each call to {@link #getValue()}.
193    *
194    * @param value
195    *    The supplier of the header value.
196    *    <br>Can be <jk>null</jk>.
197    */
198   public AcceptLanguage(Supplier<StringRanges> value) {
199      super(NAME, value);
200   }
201}