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