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 static org.apache.juneau.commons.utils.Shorts.*;
020
021import java.util.*;
022import java.util.function.*;
023
024import org.apache.juneau.http.*;
025
026/**
027 * Root concrete implementation of {@link HttpHeader}.
028 *
029 * <p>
030 * Holds a name/value pair where the value may be supplied eagerly (as a {@link String}) or lazily
031 * (via a {@link Supplier}).  A lazy supplier returning {@code null} signals that the header should
032 * be omitted from the request.
033 *
034 * <p>
035 * Create instances via the static factory methods:
036 * <p class='bjava'>
037 *    <jc>// Eager</jc>
038 *    HttpHeader <jv>h1</jv> = HttpHeaderBean.<jsm>of</jsm>(<js>"X-My-Header"</js>, <js>"my-value"</js>);
039 *
040 *    <jc>// Lazy — evaluated at request-send time</jc>
041 *    HttpHeader <jv>h2</jv> = HttpHeaderBean.<jsm>of</jsm>(<js>"Authorization"</js>, () -> tokenSupplier.get());
042 * </p>
043 *
044 * <h5 class='section'>See Also:</h5><ul>
045 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/NextGenRestClient">Next-Generation REST Client</a>
046 * </ul>
047 *
048 * @since 9.2.1
049 */
050public class HttpHeaderBean implements HttpHeader {
051
052   private final String name;
053   private final Supplier<String> valueSupplier;
054
055   /**
056    * Constructor.
057    *
058    * @param name The header name. Must not be <jk>null</jk>.
059    * @param value The header value. May be <jk>null</jk>.
060    */
061   protected HttpHeaderBean(String name, String value) {
062      this.name = reqnn("name", name);
063      this.valueSupplier = () -> value;
064   }
065
066   /**
067    * Constructor with lazy value supplier.
068    *
069    * @param name The header name. Must not be <jk>null</jk>.
070    * @param valueSupplier Supplier that provides the header value at request time. Must not be <jk>null</jk>.
071    */
072   protected HttpHeaderBean(String name, Supplier<String> valueSupplier) {
073      this.name = reqnn("name", name);
074      this.valueSupplier = reqnn("valueSupplier", valueSupplier);
075   }
076
077   /**
078    * Creates an {@link HttpHeaderBean} with an eager string value.
079    *
080    * @param name The header name. Must not be <jk>null</jk>.
081    * @param value The header value. May be <jk>null</jk> to indicate the header should be omitted.
082    * @return A new instance. Never <jk>null</jk>.
083    */
084   public static HttpHeaderBean of(String name, String value) {
085      return new HttpHeaderBean(name, value);
086   }
087
088   /**
089    * Creates an {@link HttpHeaderBean} with a lazy value supplier.
090    *
091    * <p>
092    * The supplier is evaluated at request-send time; if it returns {@code null} the header is omitted.
093    *
094    * @param name The header name. Must not be <jk>null</jk>.
095    * @param valueSupplier Supplier for the header value. Must not be <jk>null</jk>.
096    * @return A new instance. Never <jk>null</jk>.
097    */
098   public static HttpHeaderBean of(String name, Supplier<String> valueSupplier) {
099      return new HttpHeaderBean(name, valueSupplier);
100   }
101
102   @Override /* HttpHeader */
103   public String getName() {
104      return name;
105   }
106
107   @Override /* HttpHeader */
108   public String getValue() {
109      return valueSupplier.get();
110   }
111
112   /**
113    * Returns {@code true} if the header value is equal to the given value, ignoring case.
114    *
115    * @param other The value to compare against. May be <jk>null</jk>.
116    * @return {@code true} if the value is equal, ignoring case.
117    */
118   public boolean equalsIgnoreCase(String other) {
119      return eqic(getValue(), other);
120   }
121
122   @Override /* Object */
123   public String toString() {
124      return name + ": " + getValue();
125   }
126
127   @Override /* Object */
128   public boolean equals(Object obj) {
129      return (obj instanceof HttpHeaderBean o2) && eq(this, o2, (x, y) -> eqic(x.name, y.name) && eq(x.getValue(), y.getValue()));
130   }
131
132   @Override /* Object */
133   public int hashCode() {
134      return h(name.toLowerCase(Locale.ROOT), getValue());
135   }
136}