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.classic.header;
018import static org.apache.juneau.commons.utils.Shorts.*;
019
020import java.net.*;
021import java.util.*;
022import java.util.function.*;
023
024/**
025 * Category of headers that consist of a single URL value.
026 *
027 * <p>
028 * <h5 class='figure'>Example</h5>
029 * <p class='bcode'>
030 *    Location: http://www.w3.org/pub/WWW/People.html
031 * </p>
032 *
033 * <h5 class='section'>See Also:</h5><ul>
034 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommon">juneau-rest-common</a>
035 *    <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a>
036 * </ul>
037 *
038 * @serial exclude
039 */
040@SuppressWarnings({
041   "java:S2160" // equals() inherited from BasicHeader compares name+value; typed URI field is accessed via getValue()
042})
043public class BasicUriHeader 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>Must be parsable by {@link URI#create(String)}.
053    *    <br>Can be <jk>null</jk>.
054    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
055    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
056    */
057   public static BasicUriHeader of(String name, String value) {
058      return value == null ? null : new BasicUriHeader(name, value);
059   }
060
061   /**
062    * Static creator with delayed value.
063    *
064    * <p>
065    * Header value is re-evaluated on each call to {@link #getValue()}.
066    *
067    * @param name The header name.
068    * @param value
069    *    The supplier of the header value.
070    *    <br>Can be <jk>null</jk>.
071    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
072    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
073    */
074   public static BasicUriHeader of(String name, Supplier<URI> value) {
075      return value == null ? null : new BasicUriHeader(name, value);
076   }
077
078   /**
079    * Static creator.
080    *
081    * @param name The header name.
082    * @param value
083    *    The header value.
084    *    <br>Can be <jk>null</jk>.
085    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
086    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
087    */
088   public static BasicUriHeader of(String name, URI value) {
089      return value == null ? null : new BasicUriHeader(name, value);
090   }
091
092   private final URI value;
093   private final transient Supplier<URI> supplier;
094
095   /**
096    * Constructor.
097    *
098    * @param name The header name.
099    * @param value
100    *    The header value.
101    *    <br>Must be parsable by {@link URI#create(String)}.
102    *    <br>Can be <jk>null</jk> to create a header with no value.
103    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
104    */
105   public BasicUriHeader(String name, String value) {
106      super(name, value);
107      this.value = ie(value) ? null : URI.create(value);
108      this.supplier = null;
109   }
110
111   /**
112    * Constructor with delayed value.
113    *
114    * <p>
115    * Header value is re-evaluated on each call to {@link #getValue()}.
116    *
117    * @param name The header name.
118    * @param value
119    *    The supplier of the header value.
120    *    <br>Can be <jk>null</jk> to create a header with no value.
121    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
122    */
123   public BasicUriHeader(String name, Supplier<URI> value) {
124      super(name, null);
125      this.value = null;
126      supplier = value;
127   }
128
129   /**
130    * Constructor.
131    *
132    * @param name The header name.
133    * @param value
134    *    The header value.
135    *    <br>Can be <jk>null</jk> to create a header with no value.
136    * @throws IllegalArgumentException If name is <jk>null</jk> or empty.
137    */
138   public BasicUriHeader(String name, URI value) {
139      super(name, s(value));
140      this.value = value;
141      this.supplier = null;
142   }
143
144   /**
145    * Returns the header value as a {@link URI} wrapped in an {@link Optional}.
146    *
147    * @return The header value as a {@link URI} wrapped in an {@link Optional}.  Never <jk>null</jk>.
148    */
149   public Optional<URI> asUri() {
150      return o(value());
151   }
152
153   @Override /* Overridden from Header */
154   public String getValue() { return s(value()); }
155
156   /**
157    * Return the value if present, otherwise return <c>other</c>.
158    *
159    * <p>
160    * This is a shortened form for calling <c>asUri().orElse(<jv>other</jv>)</c>.
161    *
162    * @param other The value to be returned if there is no value present, can be <jk>null</jk>.
163    * @return The value, if present, otherwise <c>other</c>.
164    */
165   public URI orElse(URI other) {
166      URI x = value();
167      return nn(x) ? x : other;
168   }
169
170   /**
171    * Returns the header value as a {@link URI} wrapped in an {@link Optional}.
172    *
173    * @return The header value as a {@link URI} wrapped in an {@link Optional}.  Never <jk>null</jk>.
174    */
175   public URI toUri() {
176      return value();
177   }
178
179   private URI value() {
180      if (nn(supplier))
181         return supplier.get();
182      return value;
183   }
184}