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