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