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 java.util.function.*;
020
021import org.apache.juneau.http.annotation.*;
022
023/**
024 * Represents a parsed <l>If-None-Match</l> HTTP request header.
025 *
026 * <p>
027 * Allows a 304 Not Modified to be returned if content is unchanged.
028 *
029 * <h5 class='figure'>Example</h5>
030 * <p class='bcode'>
031 *    If-None-Match: "737060cd8c284d8af7ad3082f209582d"
032 * </p>
033 *
034 * <h5 class='topic'>RFC2616 Specification</h5>
035 *
036 * The If-None-Match request-header field is used with a method to make it conditional.
037 * A client that has one or more entities previously obtained from the resource can verify that none of those entities
038 * is current by including a list of their associated entity tags in the If-None-Match header field.
039 * The purpose of this feature is to allow efficient updates of cached information with a minimum amount of transaction
040 * overhead.
041 * It is also used to prevent a method (e.g. PUT) from inadvertently modifying an existing resource when the client
042 * believes that the resource does not exist.
043 *
044 * <p>
045 * As a special case, the value "*" matches any current entity of the resource.
046 *
047 * <p class='bcode'>
048 *    If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )
049 * </p>
050 *
051 * <p>
052 * If any of the entity tags match the entity tag of the entity that would have been returned in the response to a
053 * similar GET request (without the If-None-Match header) on that resource, or if "*" is given
054 * and any current entity exists for that resource, then the server MUST NOT perform the requested method, unless
055 * required to do so because the resource's modification date fails to match that supplied in an If-Modified-Since
056 * header field in the request.
057 * Instead, if the request method was GET or HEAD, the server SHOULD respond with a 304 (Not Modified) response,
058 * including the cache- related header fields (particularly ETag) of one of the entities that matched.
059 * For all other request methods, the server MUST respond with a status of 412 (Precondition Failed).
060 *
061 * <p>
062 * See section 13.3.3 for rules on how to determine if two entities tags match.
063 * The weak comparison function can only be used with GET or HEAD requests.
064 *
065 * <p>
066 * If none of the entity tags match, then the server MAY perform the requested method as if the If-None-Match header
067 * field did not exist, but MUST also ignore any If-Modified-Since header field(s) in the request.
068 * That is, if no entity tags match, then the server MUST NOT return a 304 (Not Modified) response.
069 *
070 * <p>
071 * If the request would, without the If-None-Match header field, result in anything other than a 2xx or 304 status,
072 * then the If-None-Match header MUST be ignored.
073 * (See section 13.3.4 for a discussion of server behavior when both If-Modified-Since and If-None-Match appear in the
074 * same request.)
075 *
076 * <p>
077 * The meaning of "If-None-Match: *" is that the method MUST NOT be performed if the representation selected by the
078 * origin server (or by a cache, possibly using the Vary mechanism, see section 14.44) exists, and SHOULD be performed
079 * if the representation does not exist.
080 * This feature is intended to be useful in preventing races between PUT operations.
081 *
082 * <p>
083 * Examples:
084 * <p class='bcode'>
085 *    If-None-Match: "xyzzy"
086 *    If-None-Match: W/"xyzzy"
087 *    If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
088 *    If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
089 *    If-None-Match: *
090 * </p>
091 *
092 * <p>
093 * The result of a request having both an If-None-Match header field and either an If-Match or an If-Unmodified-Since
094 * header fields is undefined by this specification.
095 *
096 * <h5 class='section'>See Also:</h5><ul>
097 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a>
098 *    <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a>
099 * </ul>
100 *
101 * @serial exclude
102 */
103@Header("If-None-Match")
104public class IfNoneMatch extends BasicEntityTagsHeader {
105
106   //-----------------------------------------------------------------------------------------------------------------
107   // Static
108   //-----------------------------------------------------------------------------------------------------------------
109
110   private static final long serialVersionUID = 1L;
111   private static final String NAME = "If-None-Match";
112
113   /**
114    * Static creator.
115    *
116    * @param value
117    *    The header value.
118    *    <br>Must be a comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
119    *    <br>Can be <jk>null</jk>.
120    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
121    */
122   public static IfNoneMatch of(String value) {
123      return value == null ? null : new IfNoneMatch(value);
124   }
125
126   /**
127    * Static creator.
128    *
129    * @param value
130    *    The header value.
131    *    <br>Can be <jk>null</jk>.
132    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
133    */
134   public static IfNoneMatch of(EntityTags value) {
135      return value == null ? null : new IfNoneMatch(value);
136   }
137
138   /**
139    * Static creator with delayed value.
140    *
141    * <p>
142    * Header value is re-evaluated on each call to {@link #getValue()}.
143    *
144    * @param value
145    *    The supplier of the header value.
146    *    <br>Can be <jk>null</jk>.
147    * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
148    */
149   public static IfNoneMatch of(Supplier<EntityTags> value) {
150      return value == null ? null : new IfNoneMatch(value);
151   }
152
153   //-----------------------------------------------------------------------------------------------------------------
154   // Instance
155   //-----------------------------------------------------------------------------------------------------------------
156
157   /**
158    * Constructor.
159    *
160    * @param value
161    *    The header value.
162    *    <br>Must be a comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
163    *    <br>Can be <jk>null</jk>.
164    */
165   public IfNoneMatch(String value) {
166      super(NAME, value);
167   }
168
169   /**
170    * Constructor.
171    *
172    * @param value
173    *    The header value.
174    *    <br>Can be <jk>null</jk>.
175    */
176   public IfNoneMatch(EntityTags value) {
177      super(NAME, value);
178   }
179
180   /**
181    * Constructor with delayed value.
182    *
183    * <p>
184    * Header value is re-evaluated on each call to {@link #getValue()}.
185    *
186    * @param value
187    *    The supplier of the header value.
188    *    <br>Can be <jk>null</jk>.
189    */
190   public IfNoneMatch(Supplier<EntityTags> value) {
191      super(NAME, value);
192   }
193}