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