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.annotation.*; 024import org.apache.juneau.assertions.*; 025import org.apache.juneau.common.utils.*; 026import org.apache.juneau.http.annotation.*; 027 028/** 029 * Category of headers that consist of a single integer value. 030 * 031 * <p> 032 * <h5 class='figure'>Example</h5> 033 * <p class='bcode'> 034 * Age: 300 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 */ 044@Header 045@Schema(type="integer",format="int32") 046public class BasicIntegerHeader extends BasicHeader { 047 048 //----------------------------------------------------------------------------------------------------------------- 049 // Static 050 //----------------------------------------------------------------------------------------------------------------- 051 052 private static final long serialVersionUID = 1L; 053 054 /** 055 * Static creator. 056 * 057 * @param name The header name. 058 * @param value 059 * The header value. 060 * <br>Must be parsable using {@link Integer#parseInt(String)}. 061 * <br>Can be <jk>null</jk>. 062 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 063 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 064 */ 065 public static BasicIntegerHeader of(String name, String value) { 066 return value == null ? null : new BasicIntegerHeader(name, value); 067 } 068 069 /** 070 * Static creator. 071 * 072 * @param name The header name. 073 * @param value 074 * The header value. 075 * <br>Can be <jk>null</jk>. 076 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 077 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 078 */ 079 public static BasicIntegerHeader of(String name, Integer value) { 080 return value == null ? null : new BasicIntegerHeader(name, value); 081 } 082 083 /** 084 * Static creator with delayed value. 085 * 086 * <p> 087 * Header value is re-evaluated on each call to {@link #getValue()}. 088 * 089 * @param name The header name. 090 * @param value 091 * The supplier of the header value. 092 * <br>Can be <jk>null</jk>. 093 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>. 094 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 095 */ 096 public static BasicIntegerHeader of(String name, Supplier<Integer> value) { 097 return value == null ? null : new BasicIntegerHeader(name, value); 098 } 099 100 //----------------------------------------------------------------------------------------------------------------- 101 // Instance 102 //----------------------------------------------------------------------------------------------------------------- 103 104 private final Integer value; 105 private final Supplier<Integer> supplier; 106 107 /** 108 * Constructor. 109 * 110 * @param name The header name. 111 * @param value 112 * The header value. 113 * <br>Must be parsable using {@link Integer#parseInt(String)}. 114 * <br>Can be <jk>null</jk>. 115 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 116 */ 117 public BasicIntegerHeader(String name, String value) { 118 super(name, value); 119 this.value = parse(value); 120 this.supplier = null; 121 } 122 123 /** 124 * Constructor. 125 * 126 * @param name The header name. 127 * @param value 128 * The header value. 129 * <br>Can be <jk>null</jk>. 130 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 131 */ 132 public BasicIntegerHeader(String name, Integer value) { 133 super(name, value); 134 this.value = value; 135 this.supplier = null; 136 } 137 138 /** 139 * Constructor with delayed value. 140 * 141 * <p> 142 * Header value is re-evaluated on each call to {@link #getValue()}. 143 * 144 * @param name The header name. 145 * @param value 146 * The supplier of the header value. 147 * <br>Can be <jk>null</jk>. 148 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 149 */ 150 public BasicIntegerHeader(String name, Supplier<Integer> value) { 151 super(name, null); 152 this.value = null; 153 this.supplier = value; 154 } 155 156 @Override /* Header */ 157 public String getValue() { 158 return Utils.s(value()); 159 } 160 161 /** 162 * Returns the header value as an {@link Integer} wrapped in an {@link Optional}. 163 * 164 * @return The header value as an {@link Integer} wrapped in an {@link Optional}. Never <jk>null</jk>. 165 */ 166 public Optional<Integer> asInteger() { 167 return Utils.opt(value()); 168 } 169 170 /** 171 * Returns the header value as an {@link Integer}. 172 * 173 * @return The header value as an {@link Integer}. Can be <jk>null</jk>. 174 */ 175 public Integer toInteger() { 176 return value(); 177 } 178 179 /** 180 * Provides the ability to perform fluent-style assertions on this header. 181 * 182 * <h5 class='section'>Examples:</h5> 183 * <p class='bjava'> 184 * <jc>// Validates the response content is older than 1.</jc> 185 * <jv>client</jv> 186 * .get(<jsf>URL</jsf>) 187 * .run() 188 * .getHeader(<js>"Age"</js>).asIntegerHeader().assertInteger().isGreaterThan(1); 189 * </p> 190 * 191 * @return A new fluent assertion object. 192 * @throws AssertionError If assertion failed. 193 */ 194 public FluentIntegerAssertion<BasicIntegerHeader> assertInteger() { 195 return new FluentIntegerAssertion<>(value(), this); 196 } 197 198 /** 199 * Return the value if present, otherwise return <c>other</c>. 200 * 201 * <p> 202 * This is a shortened form for calling <c>asInteger().orElse(<jv>other</jv>)</c>. 203 * 204 * @param other The value to be returned if there is no value present, can be <jk>null</jk>. 205 * @return The value, if present, otherwise <c>other</c>. 206 */ 207 public Integer orElse(Integer other) { 208 Integer x = value(); 209 return x != null ? x : other; 210 } 211 212 private Integer parse(String value) { 213 try { 214 return value == null ? null : Integer.parseInt(value); 215 } catch (NumberFormatException e) { 216 throw new BasicRuntimeException("Value ''{0}'' could not be parsed as an integer.", value); 217 } 218 } 219 220 private Integer value() { 221 if (supplier != null) 222 return supplier.get(); 223 return value; 224 } 225}