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