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