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.juneau.assertions.*;
025import org.apache.juneau.commons.collections.*;
026import org.apache.juneau.commons.lang.*;
027import org.apache.juneau.http.annotation.*;
028
029/**
030 * Represents a parsed <l>Client-Version</l> HTTP request header.
031 *
032 * <p>
033 * Specifies a client-side version number.
034 *
035 * <h5 class='figure'>Example</h5>
036 * <p class='bcode'>
037 *    Client-Version: 2.0.1
038 * </p>
039 *
040 * <p>
041 * Not part of the RFC2616 specification, but provided to allow for HTTP responses to be tailored to specified
042 * known client versions.
043 *
044 * <h5 class='section'>See Also:</h5><ul>
045 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a>
046 * </ul>
047 *
048 * @serial exclude
049 */
050@Header("Client-Version")
051public class ClientVersion extends BasicStringHeader {
052   private static final long serialVersionUID = 1L;
053   private static final String NAME = "Client-Version";
054
055   private static final Cache<String,ClientVersion> CACHE = Cache.of(String.class, ClientVersion.class).build();
056
057   /**
058    * Static creator.
059    *
060    * @param value
061    *    The header value.
062    *    <br>Must be parsable by {@link Version#of(String)}
063    *    <br>Can be <jk>null</jk>.
064    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
065    */
066   public static ClientVersion of(String value) {
067      return value == null ? null : CACHE.get(value, () -> new ClientVersion(value));
068   }
069
070   /**
071    * Static creator with delayed value.
072    *
073    * <p>
074    * Header value is re-evaluated on each call to {@link #getValue()}.
075    *
076    * @param value
077    *    The supplier of the header value.
078    *    <br>Can be <jk>null</jk>.
079    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
080    */
081   public static ClientVersion of(Supplier<Version> value) {
082      return value == null ? null : new ClientVersion(value);
083   }
084
085   /**
086    * Static creator.
087    *
088    * @param value
089    *    The header value.
090    *    <br>Can be <jk>null</jk>.
091    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
092    */
093   public static ClientVersion of(Version value) {
094      return value == null ? null : new ClientVersion(value);
095   }
096
097   private final Version value;
098   private final Supplier<Version> supplier;
099
100   /**
101    * Constructor.
102    *
103    * @param value
104    *    The header value.
105    *    <br>Must be parsable by {@link Version#of(String)}
106    *    <br>Can be <jk>null</jk>.
107    */
108   public ClientVersion(String value) {
109      super(NAME, value);
110      this.value = Version.of(value);
111      this.supplier = null;
112   }
113
114   /**
115    * Constructor with delayed value.
116    *
117    * <p>
118    * Header value is re-evaluated on each call to {@link #getValue()}.
119    *
120    * @param value
121    *    The supplier of the header value.
122    *    <br>Can be <jk>null</jk>.
123    */
124   public ClientVersion(Supplier<Version> value) {
125      super(NAME, (String)null);
126      this.value = null;
127      supplier = value;
128   }
129
130   /**
131    * Constructor.
132    *
133    * @param value
134    *    The header value.
135    *    <br>Can be <jk>null</jk>.
136    */
137   public ClientVersion(Version value) {
138      super(NAME, s(value));
139      this.value = value;
140      this.supplier = null;
141   }
142
143   /**
144    * Provides the ability to perform fluent-style assertions on this header.
145    *
146    * <h5 class='section'>Examples:</h5>
147    * <p class='bjava'>
148    *    <jc>// Validates the response content is older than 1.</jc>
149    *    <jv>client</jv>
150    *       .get(<jsf>URL</jsf>)
151    *       .run()
152    *       .getHeader(ClientVersion.<jk>class</jk>).assertVersion().major().isGreaterThan(1);
153    * </p>
154    *
155    * @return A new fluent assertion object.
156    * @throws AssertionError If assertion failed.
157    */
158   public FluentVersionAssertion<ClientVersion> assertVersion() {
159      return new FluentVersionAssertion<>(asVersion().orElse(null), this);
160   }
161
162   /**
163    * Returns the header value as a {@link Version} object.
164    *
165    * @return The header value as a {@link Version} object, or {@link Optional#empty()} if the value is <jk>null</jk>.
166    */
167   public Optional<Version> asVersion() {
168      return opt(value);
169   }
170
171   @Override /* Overridden from Header */
172   public String getValue() {
173      if (nn(supplier))
174         return s(supplier.get());
175      return super.getValue();
176   }
177}