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.common.internal.StringUtils.*;
016import static org.apache.juneau.internal.CollectionUtils.*;
017
018import java.util.*;
019import java.util.function.*;
020
021import org.apache.juneau.annotation.*;
022import org.apache.juneau.assertions.*;
023import org.apache.juneau.http.annotation.*;
024
025/**
026 * Category of headers that consist of a single boolean value.
027 *
028 * <p>
029 * <h5 class='figure'>Example</h5>
030 * <p class='bcode'>
031 *    Foo: true
032 * </p>
033 *
034 * <h5 class='section'>See Also:</h5><ul>
035 *    <li class='link'><a class="doclink" href="../../../../../index.html#juneau-rest-common">juneau-rest-common</a>
036 *    <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a>
037 * </ul>
038 *
039 * @serial exclude
040 */
041@Header
042@Schema(type="boolean")
043public class BasicBooleanHeader extends BasicHeader {
044
045   //-----------------------------------------------------------------------------------------------------------------
046   // Static
047   //-----------------------------------------------------------------------------------------------------------------
048
049   private static final long serialVersionUID = 1L;
050
051   /**
052    * Static creator.
053    *
054    * @param name The header name.
055    * @param value
056    *    The header value.
057    *    <br>Must be parsable by {@link Boolean#parseBoolean(String)}.
058    *    <br>Can be <jk>null</jk>.
059    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
060    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
061    */
062   public static BasicBooleanHeader of(String name, String value) {
063      return value == null ? null : new BasicBooleanHeader(name, value);
064   }
065
066   /**
067    * Static creator.
068    *
069    * @param name The header name.
070    * @param value
071    *    The header value.
072    *    <br>Can be <jk>null</jk>.
073    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
074    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
075    */
076   public static BasicBooleanHeader of(String name, Boolean value) {
077      return value == null ? null : new BasicBooleanHeader(name, value);
078   }
079
080   /**
081    * Static creator with delayed value.
082    *
083    * <p>
084    * Header value is re-evaluated on each call to {@link #getValue()}.
085    *
086    * @param name The header name.
087    * @param value
088    *    The supplier of the header value.
089    *    <br>Can be <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 BasicBooleanHeader of(String name, Supplier<Boolean> value) {
094      return value == null ? null : new BasicBooleanHeader(name, value);
095   }
096
097   //-----------------------------------------------------------------------------------------------------------------
098   // Instance
099   //-----------------------------------------------------------------------------------------------------------------
100
101   private final Boolean value;
102   private final Supplier<Boolean> supplier;
103
104   /**
105    * Constructor.
106    *
107    * @param name The header name.
108    * @param value
109    *    The header value.
110    *    <br>Must be parsable by {@link Boolean#parseBoolean(String)}.
111    *    <br>Can be <jk>null</jk>.
112    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
113    */
114   public BasicBooleanHeader(String name, String value) {
115      super(name, value);
116      this.value = isEmpty(value) ? null : Boolean.valueOf(value);
117      this.supplier = null;
118   }
119
120   /**
121    * Constructor.
122    *
123    * @param name The header name.
124    * @param value
125    *    The header value.
126    *    <br>Can be <jk>null</jk>.
127    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
128    */
129   public BasicBooleanHeader(String name, Boolean value) {
130      super(name, value);
131      this.value = value;
132      this.supplier = null;
133   }
134
135   /**
136    * Constructor with delayed value.
137    *
138    * <p>
139    * Header value is re-evaluated on each call to {@link #getValue()}.
140    *
141    * @param name The header name.
142    * @param value
143    *    The supplier of the header value.
144    *    <br>Can be <jk>null</jk>.
145    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
146    */
147   public BasicBooleanHeader(String name, Supplier<Boolean> value) {
148      super(name, null);
149      this.value = null;
150      this.supplier = value;
151   }
152
153   @Override /* Header */
154   public String getValue() {
155      return stringify(value());
156   }
157
158   /**
159    * Returns the header value as a {@link Boolean} wrapped in an {@link Optional}.
160    *
161    * @return The header value as a {@link Boolean} wrapped in an {@link Optional}.  Never <jk>null</jk>.
162    */
163   public Optional<Boolean> asBoolean() {
164      return optional(value());
165   }
166
167   /**
168    * Returns the header value as a {@link Boolean}.
169    *
170    * @return The header value as a {@link Boolean}.  Can be <jk>null</jk>.
171    */
172   public Boolean toBoolean() {
173      return value();
174   }
175
176   /**
177    * Returns <jk>true</jk> if the header value is <jk>true</jk>.
178    *
179    * @return <jk>true</jk> if the header value is <jk>true</jk>.
180    */
181   public boolean isTrue() {
182      Boolean x = value();
183      return x == null ? value : x;
184   }
185
186   /**
187    * Provides the ability to perform fluent-style assertions on this header.
188    *
189    * <h5 class='section'>Examples:</h5>
190    * <p class='bjava'>
191    *    <jc>// Validates the response header Foo is true.</jc>
192    *    <jv>client</jv>
193    *       .get(<jsf>URL</jsf>)
194    *       .run()
195    *       .getHeader(<js>"Foo"</js>).asBooleanHeader().assertBoolean().isTrue();
196    * </p>
197    *
198    * @return A new fluent assertion object.
199    * @throws AssertionError If assertion failed.
200    */
201   public FluentBooleanAssertion<BasicBooleanHeader> assertBoolean() {
202      return new FluentBooleanAssertion<>(value(), this);
203   }
204
205   /**
206    * Return the value if present, otherwise return <c>other</c>.
207    *
208    * <p>
209    * This is a shortened form for calling <c>asBoolean().orElse(<jv>other</jv>)</c>.
210    *
211    * @param other The value to be returned if there is no value present, can be <jk>null</jk>.
212    * @return The value, if present, otherwise <c>other</c>.
213    */
214   public Boolean orElse(Boolean other) {
215      Boolean x = value();
216      return x != null ? x : other;
217   }
218
219   private Boolean value() {
220      if (supplier != null)
221         return supplier.get();
222      return value;
223   }
224}