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.Utils.*;
020
021import java.util.*;
022import java.util.function.*;
023
024import org.apache.http.*;
025import org.apache.juneau.assertions.*;
026
027/**
028 * Category of headers that consist of a single string value.
029 *
030 * <p>
031 * <h5 class='figure'>Example</h5>
032 * <p class='bcode'>
033 *    Host: www.myhost.com:8080
034 * </p>
035 *
036 * <h5 class='section'>See Also:</h5><ul>
037 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a>
038 *    <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a>
039 * </ul>
040 *
041 * @serial exclude
042 */
043public class BasicStringHeader extends BasicHeader {
044   private static final long serialVersionUID = 1L;
045
046   /**
047    * Static creator.
048    *
049    * @param name The header name.
050    * @param value
051    *    The header value.
052    *    <br>Can be <jk>null</jk>.
053    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
054    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
055    */
056   public static BasicStringHeader of(String name, String value) {
057      return value == null ? null : new BasicStringHeader(name, value);
058   }
059
060   /**
061    * Static creator with delayed value.
062    *
063    * <p>
064    * Header value is re-evaluated on each call to {@link #getValue()}.
065    *
066    * @param name The header name.
067    * @param value
068    *    The supplier of the header value.
069    *    <br>Can be <jk>null</jk>.
070    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
071    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
072    */
073   public static BasicStringHeader of(String name, Supplier<String> value) {
074      return value == null ? null : new BasicStringHeader(name, value);
075   }
076
077   /**
078    * Creates a {@link Header} from a name/value pair string (e.g. <js>"Foo: bar"</js>)
079    *
080    * @param pair The pair string.
081    * @return A new header bean.
082    */
083   public static BasicStringHeader ofPair(String pair) {
084      if (pair == null)
085         return null;
086      var i = pair.indexOf(':');
087      if (i == -1)
088         i = pair.indexOf('=');
089      if (i == -1)
090         return of(pair, "");
091      return of(pair.substring(0, i).trim(), pair.substring(i + 1).trim());
092   }
093
094   private final String value;
095   private final Supplier<String> supplier;
096
097   /**
098    * Constructor.
099    *
100    * @param name The header name.
101    * @param value
102    *    The header value.
103    *    <br>Can be <jk>null</jk>.
104    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
105    */
106   public BasicStringHeader(String name, String value) {
107      super(name, value);
108      this.value = value;
109      this.supplier = null;
110   }
111
112   /**
113    * Constructor with delayed value.
114    *
115    * <p>
116    * Header value is re-evaluated on each call to {@link #getValue()}.
117    *
118    * @param name The header name.
119    * @param value
120    *    The supplier of the header value.
121    *    <br>Can be <jk>null</jk>.
122    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
123    */
124   public BasicStringHeader(String name, Supplier<String> value) {
125      super(name, null);
126      this.value = null;
127      supplier = value;
128   }
129
130   /**
131    * Provides the ability to perform fluent-style assertions on this header.
132    *
133    * <h5 class='section'>Examples:</h5>
134    * <p class='bjava'>
135    *    <jc>// Validates the content type header is provided.</jc>
136    *    <jv>client</jv>
137    *       .get(<jsf>URL</jsf>)
138    *       .run()
139    *       .getHeader(<js>"Content-Type"</js>).assertString().exists();
140    * </p>
141    *
142    * @return A new fluent assertion object.
143    * @throws AssertionError If assertion failed.
144    */
145   public FluentStringAssertion<BasicStringHeader> assertString() {
146      return new FluentStringAssertion<>(value(), this);
147   }
148
149   @Override /* Overridden from BasicHeader */
150   public Optional<String> asString() {
151      return opt(value());
152   }
153
154   @Override /* Overridden from Header */
155   public String getValue() { return s(value()); }
156
157   /**
158    * Return the value if present, otherwise return <c>other</c>.
159    *
160    * <p>
161    * This is a shortened form for calling <c>asString().orElse(<jv>other</jv>)</c>.
162    *
163    * @param other The value to be returned if there is no value present, can be <jk>null</jk>.
164    * @return The value, if present, otherwise <c>other</c>.
165    */
166   @Override
167   public String orElse(String other) {
168      String x = value();
169      return nn(x) ? x : other;
170   }
171
172   private String value() {
173      if (nn(supplier))
174         return supplier.get();
175      return value;
176   }
177}