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 static org.apache.juneau.common.internal.StringUtils.*; 016import static org.apache.juneau.internal.ArrayUtils.*; 017import static org.apache.juneau.internal.CollectionUtils.*; 018 019import java.util.*; 020import java.util.function.*; 021 022import org.apache.juneau.assertions.*; 023 024/** 025 * Category of headers that consist of a comma-delimited list of string values. 026 * 027 * <p> 028 * <h5 class='figure'>Example</h5> 029 * <p class='bcode'> 030 * Allow: GET, PUT 031 * </p> 032 * 033 * <h5 class='section'>See Also:</h5><ul> 034 * <li class='link'><a class="doclink" href="../../../../../index.html#juneau-rest-common">juneau-rest-common</a> 035 * <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a> 036 * </ul> 037 * 038 * @serial exclude 039 */ 040public class BasicCsvHeader extends BasicHeader { 041 042 //----------------------------------------------------------------------------------------------------------------- 043 // Static 044 //----------------------------------------------------------------------------------------------------------------- 045 046 private static final long serialVersionUID = 1L; 047 048 /** 049 * Static creator. 050 * 051 * @param name The header name. 052 * @param value 053 * The header value. 054 * <br>Must be a comma-delimited list. 055 * <br>Can be <jk>null</jk>. 056 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 057 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 058 */ 059 public static BasicCsvHeader of(String name, String value) { 060 return value == null ? null : new BasicCsvHeader(name, value); 061 } 062 063 /** 064 * Static creator. 065 * 066 * @param name The header name. 067 * @param value 068 * The header value. 069 * <br>Can be <jk>null</jk>. 070 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 071 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 072 */ 073 public static BasicCsvHeader of(String name, String...value) { 074 return value == null ? null : new BasicCsvHeader(name, value); 075 } 076 077 /** 078 * Static creator with delayed value. 079 * 080 * <p> 081 * Header value is re-evaluated on each call to {@link #getValue()}. 082 * 083 * @param name The header name. 084 * @param value 085 * The supplier of the header value. 086 * <br>Can be <jk>null</jk>. 087 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 088 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 089 */ 090 public static BasicCsvHeader of(String name, Supplier<String[]> value) { 091 return value == null ? null : new BasicCsvHeader(name, value); 092 } 093 094 //----------------------------------------------------------------------------------------------------------------- 095 // Instance 096 //----------------------------------------------------------------------------------------------------------------- 097 098 private final String[] value; 099 private final Supplier<String[]> supplier; 100 101 /** 102 * Constructor. 103 * 104 * @param name The header name. 105 * @param value 106 * The header value. 107 * <br>Must be a comma-delimited list. 108 * <br>Can be <jk>null</jk>. 109 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 110 */ 111 public BasicCsvHeader(String name, String value) { 112 super(name, value); 113 this.value = split(value); 114 this.supplier = null; 115 } 116 117 /** 118 * Constructor. 119 * 120 * @param name The header name. 121 * @param value 122 * The header value. 123 * <br>Can be <jk>null</jk>. 124 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 125 */ 126 public BasicCsvHeader(String name, String...value) { 127 super(name, join(value, ", ")); 128 this.value = copyOf(value); 129 this.supplier = null; 130 } 131 132 /** 133 * Constructor with delayed value. 134 * 135 * <p> 136 * Header value is re-evaluated on each call to {@link #getValue()}. 137 * 138 * @param name The header name. 139 * @param value 140 * The supplier of the header value. 141 * <br>Can be <jk>null</jk>. 142 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 143 */ 144 public BasicCsvHeader(String name, Supplier<String[]> value) { 145 super(name, null); 146 this.value = null; 147 this.supplier = value; 148 } 149 150 @Override /* Header */ 151 public String getValue() { 152 return join(value(), ", "); 153 } 154 155 /** 156 * Returns the header value as an array wrapped in an {@link Optional}. 157 * 158 * <p> 159 * The array is a copy of the value of this header. 160 * 161 * @return The header value as an array wrapped in an {@link Optional}. Never <jk>null</jk>. 162 */ 163 public Optional<String[]> asArray() { 164 return optional(copyOf(value())); 165 } 166 167 /** 168 * Returns the header value as an array. 169 * 170 * <p> 171 * The array is a copy of the value of this header. 172 * 173 * @return The header value as an array. Can be <jk>null</jk>. 174 */ 175 public String[] toArray() { 176 return copyOf(value()); 177 } 178 179 /** 180 * Returns the header value as a list wrapped in an {@link Optional}. 181 * 182 * <p> 183 * The list is unmodifiable. 184 * 185 * @return The header value as a list wrapped in an {@link Optional}. Never <jk>null</jk>. 186 */ 187 public Optional<List<String>> asList() { 188 return optional(ulist(value())); 189 } 190 191 /** 192 * Returns the header value as a list. 193 * 194 * <p> 195 * The list is unmodifiable. 196 * 197 * @return The header value as a list. Can be <jk>null</jk>. 198 */ 199 public List<String> toList() { 200 return ulist(value()); 201 } 202 203 /** 204 * Returns <jk>true</jk> if this header contains the specified value. 205 * 206 * @param val The value to check for. 207 * @return <jk>true</jk> if this header contains the specified value. 208 */ 209 public boolean contains(String val) { 210 if (value != null) 211 for (String v : value) 212 if (eq(v, val)) 213 return true; 214 if (supplier != null) { 215 String[] value2 = supplier.get(); 216 if (value2 != null) 217 for (String v : supplier.get()) 218 if (eq(v, val)) 219 return true; 220 221 } 222 return false; 223 } 224 225 /** 226 * Returns <jk>true</jk> if this header contains the specified value using {@link String#equalsIgnoreCase(String)}. 227 * 228 * @param val The value to check for. 229 * @return <jk>true</jk> if this header contains the specified value. 230 */ 231 public boolean containsIgnoreCase(String val) { 232 if (value != null) 233 for (String v : value) 234 if (eqic(v, val)) 235 return true; 236 if (supplier != null) { 237 String[] value2 = supplier.get(); 238 if (value2 != null) 239 for (String v : supplier.get()) 240 if (eqic(v, val)) 241 return true; 242 } 243 return false; 244 } 245 246 /** 247 * Provides the ability to perform fluent-style assertions on this header. 248 * 249 * @return A new fluent assertion object. 250 * @throws AssertionError If assertion failed. 251 */ 252 public FluentListAssertion<String,BasicCsvHeader> assertList() { 253 return new FluentListAssertion<>(ulist(value()), this); 254 } 255 256 257 /** 258 * Return the value if present, otherwise return <c>other</c>. 259 * 260 * <p> 261 * This is a shortened form for calling <c>asArray().orElse(<jv>other</jv>)</c>. 262 * 263 * @param other The value to be returned if there is no value present, can be <jk>null</jk>. 264 * @return The value, if present, otherwise <c>other</c>. 265 */ 266 public String[] orElse(String[] other) { 267 String[] x = value(); 268 return x != null ? x : other; 269 } 270 271 private String[] value() { 272 if (supplier != null) 273 return supplier.get(); 274 return value; 275 } 276}