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 long value.
030 *
031 * <p>
032 * <h5 class='figure'>Example</h5>
033 * <p class='bcode'>
034 *    Content-Length: 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="int64")
046public class BasicLongHeader 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 by {@link Long#parseLong(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 BasicLongHeader of(String name, String value) {
066      return value == null ? null : new BasicLongHeader(name, value);
067   }
068
069   /**
070    * Static creator.
071    *
072    * @param name The header name.
073    * @param value
074    *    The header value.
075    *    <br>Must be parsable by {@link Long#parseLong(String)}.
076    *    <br>Can be <jk>null</jk>.
077    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
078    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
079    */
080   public static BasicLongHeader of(String name, Long value) {
081      return value == null ? null : new BasicLongHeader(name, value);
082   }
083
084   /**
085    * Static creator with delayed value.
086    *
087    * <p>
088    * Header value is re-evaluated on each call to {@link #getValue()}.
089    *
090    * @param name The header name.
091    * @param value
092    *    The supplier of the header value.
093    *    <br>Can be <jk>null</jk>.
094    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
095    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
096    */
097   public static BasicLongHeader of(String name, Supplier<Long> value) {
098      return value == null ? null : new BasicLongHeader(name, value);
099   }
100
101   //-----------------------------------------------------------------------------------------------------------------
102   // Instance
103   //-----------------------------------------------------------------------------------------------------------------
104
105   private final Long value;
106   private final Supplier<Long> supplier;
107
108   /**
109    * Constructor.
110    *
111    * @param name The header name.
112    * @param value
113    *    The header value.
114    *    <br>Must be parsable by {@link Long#parseLong(String)}.
115    *    <br>Can be <jk>null</jk>.
116    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
117    */
118   public BasicLongHeader(String name, String value) {
119      super(name, value);
120      this.value = parse(value);
121      this.supplier = null;
122   }
123
124   /**
125    * Constructor.
126    *
127    * @param name The header name.
128    * @param value
129    *    The header value.
130    *    <br>Can be <jk>null</jk>.
131    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
132    */
133   public BasicLongHeader(String name, Long value) {
134      super(name, value);
135      this.value = value;
136      this.supplier = null;
137   }
138
139   /**
140    * Constructor with delayed value.
141    *
142    * <p>
143    * Header value is re-evaluated on each call to {@link #getValue()}.
144    *
145    * @param name The header name.
146    * @param value
147    *    The supplier of the header value.
148    *    <br>Can be <jk>null</jk>.
149    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
150    */
151   public BasicLongHeader(String name, Supplier<Long> value) {
152      super(name, null);
153      this.value = null;
154      this.supplier = value;
155   }
156
157   @Override /* Header */
158   public String getValue() {
159      return Utils.s(value());
160   }
161
162   /**
163    * Returns the header value as a {@link Long} wrapped in an {@link Optional}.
164    *
165    * @return The header value as a {@link Long} wrapped in an {@link Optional}.  Never <jk>null</jk>.
166    */
167   public Optional<Long> asLong() {
168      return Utils.opt(value());
169   }
170
171   /**
172    * Returns the header value as a {@link Long}.
173    *
174    * @return The header value as a {@link Long}.  Can be <jk>null</jk>.
175    */
176   public Long toLong() {
177      return value();
178   }
179
180   /**
181    * Provides the ability to perform fluent-style assertions on this header.
182    *
183    * <h5 class='section'>Examples:</h5>
184    * <p class='bjava'>
185    *    <jc>// Validates the response body is not too large.</jc>
186    *    <jv>client</jv>
187    *       .get(<jsf>URL</jsf>)
188    *       .run()
189    *       .getHeader(<js>"Length"</js>).asLongHeader().assertLong().isLessThan(100000);
190    * </p>
191    *
192    * @return A new fluent assertion object.
193    * @throws AssertionError If assertion failed.
194    */
195   public FluentLongAssertion<BasicLongHeader> assertLong() {
196      return new FluentLongAssertion<>(value(), this);
197   }
198
199   /**
200    * Return the value if present, otherwise return <c>other</c>.
201    *
202    * <p>
203    * This is a shortened form for calling <c>asLong().orElse(<jv>other</jv>)</c>.
204    *
205    * @param other The value to be returned if there is no value present, can be <jk>null</jk>.
206    * @return The value, if present, otherwise <c>other</c>.
207    */
208   public Long orElse(Long other) {
209      Long x = value();
210      return x != null ? x : other;
211   }
212
213   private Long parse(String value) {
214      try {
215         return value == null ? null : Long.parseLong(value);
216      } catch (NumberFormatException e) {
217         throw new BasicRuntimeException("Value ''{0}'' could not be parsed as a long.", value);
218      }
219   }
220
221   private Long value() {
222      if (supplier != null)
223         return supplier.get();
224      return value;
225   }
226}