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.*; 020import java.util.function.*; 021 022import org.apache.juneau.*; 023import org.apache.juneau.common.utils.*; 024 025/** 026 * Category of headers that consist of simple comma-delimited lists of strings with q-values. 027 * 028 * <p> 029 * <h5 class='figure'>Example</h5> 030 * <p class='bcode'> 031 * Accept-Encoding: compress;q=0.5, gzip;q=1.0 032 * </p> 033 * 034 * <h5 class='section'>See Also:</h5><ul> 035 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a> 036 * <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a> 037 * </ul> 038 * 039 * @serial exclude 040 */ 041public class BasicStringRangesHeader extends BasicHeader { 042 043 //----------------------------------------------------------------------------------------------------------------- 044 // Static 045 //----------------------------------------------------------------------------------------------------------------- 046 047 private static final long serialVersionUID = 1L; 048 049 /** 050 * Static creator. 051 * 052 * @param name The header name. 053 * @param value 054 * The header value. 055 * <br>Must be parsable by {@link StringRanges#of(String)}. 056 * <br>Can be <jk>null</jk>. 057 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 058 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 059 */ 060 public static BasicStringRangesHeader of(String name, String value) { 061 return value == null ? null : new BasicStringRangesHeader(name, value); 062 } 063 064 /** 065 * Static creator. 066 * 067 * @param name The header name. 068 * @param value 069 * The header value. 070 * <br>Can be <jk>null</jk>. 071 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 072 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 073 */ 074 public static BasicStringRangesHeader of(String name, StringRanges value) { 075 return value == null ? null : new BasicStringRangesHeader(name, value); 076 } 077 078 /** 079 * Static creator with delayed value. 080 * 081 * <p> 082 * Header value is re-evaluated on each call to {@link #getValue()}. 083 * 084 * @param name The header name. 085 * @param value 086 * The supplier of the header value. 087 * <br>Can be <jk>null</jk>. 088 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 089 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 090 */ 091 public static BasicStringRangesHeader of(String name, Supplier<StringRanges> value) { 092 return value == null ? null : new BasicStringRangesHeader(name, value); 093 } 094 095 //----------------------------------------------------------------------------------------------------------------- 096 // Instance 097 //----------------------------------------------------------------------------------------------------------------- 098 099 private final String stringValue; 100 private final StringRanges value; 101 private final Supplier<StringRanges> supplier; 102 103 /** 104 * Constructor. 105 * 106 * @param name The header name. 107 * @param value 108 * The header value. 109 * <br>Must be parsable by {@link StringRanges#of(String)}. 110 * <br>Can be <jk>null</jk>. 111 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 112 */ 113 public BasicStringRangesHeader(String name, String value) { 114 super(name, value); 115 this.stringValue = value; 116 this.value = StringRanges.of(value); 117 this.supplier = null; 118 } 119 120 /** 121 * Constructor. 122 * 123 * @param name The header name. 124 * @param value 125 * The header value. 126 * <br>Can be <jk>null</jk>. 127 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 128 */ 129 public BasicStringRangesHeader(String name, StringRanges value) { 130 super(name, Utils.s(value)); 131 this.stringValue = null; 132 this.value = value; 133 this.supplier = null; 134 } 135 136 /** 137 * Constructor with delayed value. 138 * 139 * <p> 140 * Header value is re-evaluated on each call to {@link #getValue()}. 141 * 142 * @param name The header name. 143 * @param value 144 * The supplier of the header value. 145 * <br>Can be <jk>null</jk>. 146 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 147 */ 148 public BasicStringRangesHeader(String name, Supplier<StringRanges> value) { 149 super(name, null); 150 this.stringValue = null; 151 this.value = null; 152 this.supplier = value; 153 } 154 155 @Override /* Header */ 156 public String getValue() { 157 return stringValue != null ? stringValue : Utils.s(value()); 158 } 159 160 /** 161 * Returns the header value as a {@link StringRanges} wrapped in an {@link Optional}. 162 * 163 * @return The header value as a {@link StringRanges} wrapped in an {@link Optional}. Never <jk>null</jk>. 164 */ 165 public Optional<StringRanges> asStringRanges() { 166 return Utils.opt(value()); 167 } 168 169 /** 170 * Returns the header value as a {@link StringRanges}. 171 * 172 * @return The header value as a {@link StringRanges}. Can be <jk>null</jk>. 173 */ 174 public StringRanges toStringRanges() { 175 return value(); 176 } 177 178 /** 179 * Given a list of media types, returns the best match for this string range header. 180 * 181 * <p> 182 * Note that fuzzy matching is allowed on the media types where the string range header may 183 * contain additional subtype parts. 184 * <br>For example, given identical q-values and an string range value of <js>"text/json+activity"</js>, 185 * the media type <js>"text/json"</js> will match if <js>"text/json+activity"</js> or <js>"text/activity+json"</js> 186 * isn't found. 187 * <br>The purpose for this is to allow serializers to match when artifacts such as <c>id</c> properties are 188 * present in the header. 189 * 190 * <p> 191 * See <a class="doclink" href="https://www.w3.org/TR/activitypub/#retrieving-objects">ActivityPub / Retrieving Objects</a> 192 * 193 * @param names The names to match against. 194 * @return The index into the array of the best match, or <c>-1</c> if no suitable matches could be found. 195 */ 196 public int match(List<String> names) { 197 StringRanges x = value(); 198 return x == null ? -1 : x.match(names); 199 } 200 201 /** 202 * Returns the {@link MediaRange} at the specified index. 203 * 204 * @param index The index position of the media range. 205 * @return The {@link MediaRange} at the specified index or <jk>null</jk> if the index is out of range. 206 */ 207 public StringRange getRange(int index) { 208 StringRanges x = value(); 209 return x == null ? null : x.getRange(index); 210 } 211 212 /** 213 * Return the value if present, otherwise return <c>other</c>. 214 * 215 * <p> 216 * This is a shortened form for calling <c>asArray().orElse(<jv>other</jv>)</c>. 217 * 218 * @param other The value to be returned if there is no value present, can be <jk>null</jk>. 219 * @return The value, if present, otherwise <c>other</c>. 220 */ 221 public StringRanges orElse(StringRanges other) { 222 StringRanges x = value(); 223 return x != null ? x : other; 224 } 225 226 private StringRanges value() { 227 if (supplier != null) 228 return supplier.get(); 229 return value; 230 } 231}