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.commons.collections.*; 023import org.apache.juneau.http.annotation.*; 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 private static final long serialVersionUID = 1L; 116 private static final String NAME = "Accept-Language"; 117 118 private static final Cache<String,AcceptLanguage> CACHE = Cache.of(String.class, AcceptLanguage.class).build(); 119 120 /** 121 * Static creator. 122 * 123 * @param value 124 * The header value. 125 * <br>Must be parsable by {@link StringRanges#of(String)}. 126 * <br>Can be <jk>null</jk>. 127 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 128 */ 129 public static AcceptLanguage of(String value) { 130 return value == null ? null : CACHE.get(value, () -> new AcceptLanguage(value)); 131 } 132 133 /** 134 * Static creator. 135 * 136 * @param value 137 * The header value. 138 * <br>Can be <jk>null</jk>. 139 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 140 */ 141 public static AcceptLanguage of(StringRanges value) { 142 return value == null ? null : new AcceptLanguage(value); 143 } 144 145 /** 146 * Static creator with delayed value. 147 * 148 * <p> 149 * Header value is re-evaluated on each call to {@link #getValue()}. 150 * 151 * @param value 152 * The supplier of the header value. 153 * <br>Can be <jk>null</jk>. 154 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 155 */ 156 public static AcceptLanguage of(Supplier<StringRanges> value) { 157 return value == null ? null : new AcceptLanguage(value); 158 } 159 160 /** 161 * Constructor. 162 * 163 * @param value 164 * The header value. 165 * <br>Must be parsable by {@link StringRanges#of(String)}. 166 * <br>Can be <jk>null</jk>. 167 */ 168 public AcceptLanguage(String value) { 169 super(NAME, value); 170 } 171 172 /** 173 * Constructor. 174 * 175 * @param value 176 * The header value. 177 * <br>Can be <jk>null</jk>. 178 */ 179 public AcceptLanguage(StringRanges value) { 180 super(NAME, value); 181 } 182 183 /** 184 * Constructor with delayed value. 185 * 186 * <p> 187 * Header value is re-evaluated on each call to {@link #getValue()}. 188 * 189 * @param value 190 * The supplier of the header value. 191 * <br>Can be <jk>null</jk>. 192 */ 193 public AcceptLanguage(Supplier<StringRanges> value) { 194 super(NAME, value); 195 } 196}