001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.http.header;
014
015import static org.apache.juneau.internal.StringUtils.*;
016
017import java.util.function.*;
018
019import org.apache.juneau.*;
020import org.apache.juneau.assertions.*;
021import org.apache.juneau.http.*;
022import org.apache.juneau.http.annotation.*;
023
024/**
025 * Category of headers that consist of a single long value.
026 *
027 * <p>
028 * <h5 class='figure'>Example</h5>
029 * <p class='bcode w800'>
030 *    Content-Length: 300
031 * </p>
032 *
033 * <ul class='seealso'>
034 *    <li class='extlink'>{@doc ExtRFC2616}
035 * </ul>
036 */
037@Header(type="integer",format="int64")
038public class BasicLongHeader extends BasicHeader {
039
040   private static final long serialVersionUID = 1L;
041
042   /**
043    * Convenience creator.
044    *
045    * @param name The header name.
046    * @param value
047    *    The header value.
048    *    <br>Can be any of the following:
049    *    <ul>
050    *       <li>{@link Number} - Converted to a long using {@link Number#longValue()}.
051    *       <li>{@link String} - Parsed using {@link Long#parseLong(String)}.
052    *       <li>Anything else - Converted to <c>String</c>.
053    *    </ul>
054    * @return A new {@link BasicLongHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
055    */
056   public static BasicLongHeader of(String name, Object value) {
057      if (isEmpty(name) || value == null)
058         return null;
059      return new BasicLongHeader(name, value);
060   }
061
062   /**
063    * Convenience creator using supplier.
064    *
065    * <p>
066    * Header value is re-evaluated on each call to {@link #getValue()}.
067    *
068    * @param name The header name.
069    * @param value
070    *    The header value supplier.
071    *    <br>Can be any of the following:
072    *    <ul>
073    *       <li>{@link Number} - Converted to a long using {@link Number#longValue()}.
074    *       <li>{@link String} - Parsed using {@link Long#parseLong(String)}.
075    *       <li>Anything else - Converted to <c>String</c>.
076    *    </ul>
077    * @return A new {@link BasicLongHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
078    */
079   public static BasicLongHeader of(String name, Supplier<?> value) {
080      if (isEmpty(name) || value == null)
081         return null;
082      return new BasicLongHeader(name, value);
083   }
084
085   private Long parsed;
086
087   /**
088    * Constructor.
089    *
090    * @param name The header name.
091    * @param value
092    *    The header value.
093    *    <br>Can be any of the following:
094    *    <ul>
095    *       <li>{@link Number} - Converted to a long using {@link Number#longValue()}.
096    *       <li>{@link String} - Parsed using {@link Long#parseLong(String)}.
097    *       <li>Anything else - Converted to <c>String</c>.
098    *       <li>A {@link Supplier} of anything on this list.
099    *    </ul>
100    */
101   public BasicLongHeader(String name, Object value) {
102      super(name, value);
103      if (! isSupplier(value))
104         parsed = getParsedValue();
105   }
106
107   @Override /* Header */
108   public String getValue() {
109      return stringify(asLong());
110   }
111
112   /**
113    * Returns the header value as a long.
114    *
115    * @return The header value as a long.
116    */
117   public Long asLong() {
118      return getParsedValue();
119   }
120
121   /**
122    * Provides the ability to perform fluent-style assertions on this header.
123    *
124    * <h5 class='section'>Examples:</h5>
125    * <p class='bcode w800'>
126    *    <jc>// Validates the response body is not too large.</jc>
127    *    client
128    *       .get(<jsf>URL</jsf>)
129    *       .run()
130    *       .getLongHeader(<js>"Length"</js>).assertThat().isLessThan(100000);
131    * </p>
132    *
133    * @return A new fluent assertion object.
134    * @throws AssertionError If assertion failed.
135    */
136   public FluentLongAssertion<BasicLongHeader> assertLong() {
137      return new FluentLongAssertion<>(asLong(), this);
138   }
139
140   private Long getParsedValue() {
141      if (parsed != null)
142         return parsed;
143      Object o = getRawValue();
144      if (o == null)
145         return null;
146      if (o instanceof Number)
147         return ((Number)o).longValue();
148      String s = o.toString();
149      try {
150         return Long.parseLong(s);
151      } catch (NumberFormatException e) {
152         throw new BasicIllegalArgumentException("Value could not be parsed as a long: {0}", o);
153      }
154   }
155}