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