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.commons.utils.ThrowableUtils.*; 020import static org.apache.juneau.commons.utils.Utils.*; 021 022import java.util.function.*; 023 024import org.apache.juneau.httppart.*; 025import org.apache.juneau.oapi.*; 026import org.apache.juneau.serializer.*; 027 028/** 029 * TODO 030 * 031 * <h5 class='section'>See Also:</h5><ul> 032 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a> 033 * </ul> 034 * 035 * @serial exclude 036 */ 037public class SerializedHeader extends BasicHeader { 038 private static final long serialVersionUID = 1L; 039 040 /** 041 * Static creator. 042 * 043 * @param name The header name. 044 * @param value 045 * The POJO to serialize as the header value. 046 * <br>Can be <jk>null</jk>. 047 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 048 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 049 */ 050 public static SerializedHeader of(String name, Object value) { 051 return new SerializedHeader(name, value, null, null, false); 052 } 053 054 /** 055 * Static creator. 056 * 057 * @param name The HTTP header name name. 058 * @param value 059 * The POJO to serialize as the header value. 060 * @param serializer 061 * The serializer to use for serializing the value to a string value. 062 * @param schema 063 * The schema object that defines the format of the output. 064 * <br>If <jk>null</jk>, defaults to the schema defined on the serializer. 065 * <br>If that's also <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}. 066 * <br>Only used if serializer is schema-aware (e.g. {@link OpenApiSerializer}). 067 * <br>Can also be a {@link Supplier}. 068 * @param skipIfEmpty If value is a blank string, the value should return as <jk>null</jk>. 069 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 070 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 071 */ 072 public static SerializedHeader of(String name, Object value, HttpPartSerializerSession serializer, HttpPartSchema schema, boolean skipIfEmpty) { 073 return new SerializedHeader(name, value, serializer, schema, skipIfEmpty); 074 } 075 076 /** 077 * Static creator with delayed value. 078 * 079 * <p> 080 * Header value is re-evaluated on each call to {@link #getValue()}. 081 * 082 * @param name The header name. 083 * @param value 084 * The supplier of the POJO to serialize as the header value. 085 * <br>Can be <jk>null</jk>. 086 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 087 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 088 */ 089 public static SerializedHeader of(String name, Supplier<?> value) { 090 return new SerializedHeader(name, value, null, null, false); 091 } 092 093 /** 094 * Static creator with delayed value. 095 * 096 * <p> 097 * Header value is re-evaluated on each call to {@link #getValue()}. 098 * 099 * @param name The HTTP header name name. 100 * @param value 101 * The supplier of the POJO to serialize as the header value. 102 * @param serializer 103 * The serializer to use for serializing the value to a string value. 104 * @param schema 105 * The schema object that defines the format of the output. 106 * <br>If <jk>null</jk>, defaults to the schema defined on the serializer. 107 * <br>If that's also <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}. 108 * <br>Only used if serializer is schema-aware (e.g. {@link OpenApiSerializer}). 109 * <br>Can also be a {@link Supplier}. 110 * @param skipIfEmpty If value is a blank string, the value should return as <jk>null</jk>. 111 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 112 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 113 */ 114 public static SerializedHeader of(String name, Supplier<?> value, HttpPartSerializerSession serializer, HttpPartSchema schema, boolean skipIfEmpty) { 115 return new SerializedHeader(name, value, serializer, schema, skipIfEmpty); 116 } 117 118 private final Object value; 119 private final Supplier<Object> supplier; 120 private HttpPartSerializerSession serializer; 121 private HttpPartSchema schema = HttpPartSchema.DEFAULT; 122 private boolean skipIfEmpty; 123 124 /** 125 * Constructor. 126 * 127 * @param name The HTTP header name name. 128 * @param value The POJO to serialize to the parameter value. 129 * @param serializer 130 * The serializer to use for serializing the value to a string value. 131 * @param schema 132 * The schema object that defines the format of the output. 133 * <br>If <jk>null</jk>, defaults to the schema defined on the serializer. 134 * <br>If that's also <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}. 135 * <br>Only used if serializer is schema-aware (e.g. {@link OpenApiSerializer}). 136 * <br>Can also be a {@link Supplier}. 137 * @param skipIfEmpty If value is a blank string, the value should return as <jk>null</jk>. 138 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 139 */ 140 @SuppressWarnings("unchecked") 141 public SerializedHeader(String name, Object value, HttpPartSerializerSession serializer, HttpPartSchema schema, boolean skipIfEmpty) { 142 super(name, null); 143 this.value = value instanceof Supplier ? null : value; 144 this.supplier = value instanceof Supplier ? (Supplier<Object>)value : null; 145 this.serializer = serializer; 146 this.schema = schema; 147 this.skipIfEmpty = skipIfEmpty; 148 } 149 150 /** 151 * Constructor with delayed value. 152 * 153 * <p> 154 * Header value is re-evaluated on each call to {@link #getValue()}. 155 * 156 * @param name The HTTP header name name. 157 * @param value The supplier of the POJO to serialize to the parameter value. 158 * @param serializer 159 * The serializer to use for serializing the value to a string value. 160 * @param schema 161 * The schema object that defines the format of the output. 162 * <br>If <jk>null</jk>, defaults to the schema defined on the serializer. 163 * <br>If that's also <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}. 164 * <br>Only used if serializer is schema-aware (e.g. {@link OpenApiSerializer}). 165 * <br>Can also be a {@link Supplier}. 166 * @param skipIfEmpty If value is a blank string, the value should return as <jk>null</jk>. 167 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 168 */ 169 public SerializedHeader(String name, Supplier<Object> value, HttpPartSerializerSession serializer, HttpPartSchema schema, boolean skipIfEmpty) { 170 super(name, null); 171 this.value = null; 172 supplier = value; 173 this.serializer = serializer; 174 this.schema = schema; 175 this.skipIfEmpty = skipIfEmpty; 176 } 177 178 /** 179 * Copy constructor. 180 * 181 * @param copyFrom The object to copy. 182 */ 183 protected SerializedHeader(SerializedHeader copyFrom) { 184 super(copyFrom); 185 this.value = copyFrom.value; 186 this.supplier = copyFrom.supplier; 187 this.serializer = copyFrom.serializer == null ? serializer : copyFrom.serializer; 188 this.schema = copyFrom.schema == null ? schema : copyFrom.schema; 189 this.skipIfEmpty = copyFrom.skipIfEmpty; 190 } 191 192 /** 193 * Creates a copy of this object. 194 * 195 * @return A new copy of this object. 196 */ 197 public SerializedHeader copy() { 198 return new SerializedHeader(this); 199 } 200 201 /** 202 * Copies this bean and sets the serializer and schema on it. 203 * 204 * @param serializer The new serializer for the bean. Can be <jk>null</jk>. 205 * @param schema The new schema for the bean. Can be <jk>null</jk>. 206 * @return Either a new bean with the serializer set, or this bean if 207 * both values are <jk>null</jk> or the serializer and schema were already set. 208 */ 209 public SerializedHeader copyWith(HttpPartSerializerSession serializer, HttpPartSchema schema) { 210 if ((this.serializer == null && nn(serializer)) || (this.schema == null && nn(schema))) { 211 SerializedHeader h = copy(); 212 if (nn(serializer)) 213 h.serializer(serializer); 214 if (nn(schema)) 215 h.schema(schema); 216 return h; 217 } 218 return this; 219 } 220 221 @Override /* Overridden from NameValuePair */ 222 public String getValue() { 223 try { 224 Object v = value; 225 if (nn(supplier)) 226 v = supplier.get(); 227 HttpPartSchema schema = this.schema == null ? HttpPartSchema.DEFAULT : this.schema; 228 var def = schema.getDefault(); 229 if (v == null) { 230 if ((def == null && ! schema.isRequired()) || (def == null && schema.isAllowEmptyValue())) 231 return null; 232 } 233 if (e(s(v)) && skipIfEmpty && def == null) 234 return null; 235 return serializer == null ? s(v) : serializer.serialize(HttpPartType.HEADER, schema, v); 236 } catch (SchemaValidationException e) { 237 throw rex(e, "Validation error on request {0} parameter ''{1}''=''{2}''", HttpPartType.HEADER, getName(), value); 238 } catch (SerializeException e) { 239 throw rex(e, "Serialization error on request {0} parameter ''{1}''", HttpPartType.HEADER, getName()); 240 } 241 } 242 243 /** 244 * Sets the schema object that defines the format of the output. 245 * 246 * @param value The new value for this property. 247 * @return This object. 248 */ 249 public SerializedHeader schema(HttpPartSchema value) { 250 schema = value; 251 return this; 252 } 253 254 /** 255 * Sets the serializer to use for serializing the value to a string value. 256 * 257 * @param value The new value for this property. 258 * @return This object. 259 */ 260 public SerializedHeader serializer(HttpPartSerializer value) { 261 if (nn(value)) 262 return serializer(value.getPartSession()); 263 return this; 264 } 265 266 /** 267 * Sets the serializer to use for serializing the value to a string value. 268 * 269 * @param value The new value for this property. 270 * @return This object. 271 */ 272 public SerializedHeader serializer(HttpPartSerializerSession value) { 273 serializer = value; 274 return this; 275 } 276 277 /** 278 * Don't serialize this header if the value is <jk>null</jk> or an empty string. 279 * 280 * @return This object. 281 */ 282 public SerializedHeader skipIfEmpty() { 283 return skipIfEmpty(true); 284 } 285 286 /** 287 * Don't serialize this header if the value is <jk>null</jk> or an empty string. 288 * 289 * @param value The new value of this setting. 290 * @return This object. 291 */ 292 public SerializedHeader skipIfEmpty(boolean value) { 293 skipIfEmpty = value; 294 return this; 295 } 296}