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-Match</l> HTTP request header.
022 *
023 * <p>
024 * Only perform the action if the client supplied entity matches the same entity on the server.
025 * This is mainly for methods like PUT to only update a resource if it has not been modified since the user last
026 * updated it.
027 *
028 * <h5 class='figure'>Example</h5>
029 * <p class='bcode w800'>
030 *    If-Match: "737060cd8c284d8af7ad3082f209582d"
031 * </p>
032 *
033 * <h5 class='topic'>RFC2616 Specification</h5>
034 *
035 * The If-Match request-header field is used with a method to make it conditional.
036 * A client that has one or more entities previously obtained from the resource can verify that one of those entities
037 * is current by including a list of their associated entity tags in the If-Match header field.
038 * Entity tags are defined in section 3.11.
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, on updating requests, to prevent inadvertent modification of the wrong version of a resource.
042 * As a special case, the value "*" matches any current entity of the resource.
043 *
044 * <p class='bcode w800'>
045 *    If-Match = "If-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-Match header) on that resource, or if "*" is given and any current entity exists
051 * for that resource, then the server MAY perform the requested method as if the If-Match header field did not exist.
052 *
053 * <p>
054 * A server MUST use the strong comparison function (see section 13.3.3) to compare the entity tags in If-Match.
055 *
056 * <p>
057 * If none of the entity tags match, or if "*" is given and no current entity exists, the server MUST NOT perform the
058 * requested method, and MUST return a 412 (Precondition Failed) response.
059 * This behavior is most useful when the client wants to prevent an updating method, such as PUT, from modifying a
060 * resource that has changed since the client last retrieved it.
061 *
062 * <p>
063 * If the request would, without the If-Match header field, result in anything other than a 2xx or 412 status, then the
064 * If-Match header MUST be ignored.
065 *
066 * <p>
067 * The meaning of "If-Match: *" is that the method SHOULD be performed if the representation selected by the origin
068 * server (or by a cache, possibly using the Vary mechanism, see section 14.44) exists, and MUST NOT be performed if the
069 * representation does not exist.
070 *
071 * <p>
072 * A request intended to update a resource (e.g., a PUT) MAY include an If-Match header field to signal that the request
073 * method MUST NOT be applied if the entity corresponding to the If-Match value (a single entity tag) is no longer a
074 * representation of that resource.
075 * This allows the user to indicate that they do not wish the request to be successful if the resource has been changed
076 * without their knowledge.
077 *
078 * <p>
079 * Examples:
080 * <p class='bcode w800'>
081 *    If-Match: "xyzzy"
082 *    If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
083 *    If-Match: *
084 * </p>
085 *
086 * <p>
087 * The result of a request having both an If-Match header field and either an If-None-Match or an If-Modified-Since
088 * header fields is undefined by this specification.
089 *
090 * <ul class='seealso'>
091 *    <li class='extlink'>{@doc ExtRFC2616}
092 * </ul>
093 */
094@Header("If-Match")
095public class IfMatch extends BasicEntityTagArrayHeader {
096
097   private static final long serialVersionUID = 1L;
098
099   /**
100    * Convenience creator.
101    *
102    * @param value
103    *    The header value.
104    *    <br>Can be any of the following:
105    *    <ul>
106    *       <li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
107    *       <li>A collection or array of {@link EntityTag} objects.
108    *       <li>A collection or array of anything else - Converted to Strings.
109    *       <li>Anything else - Converted to <c>String</c>.
110    *    </ul>
111    * @return A new {@link IfMatch} object.
112    */
113   public static IfMatch of(Object value) {
114      if (value == null)
115         return null;
116      return new IfMatch(value);
117   }
118
119   /**
120    * Convenience creator using supplier.
121    *
122    * <p>
123    * Header value is re-evaluated on each call to {@link #getValue()}.
124    *
125    * @param value
126    *    The header value supplier.
127    *    <br>Can be any of the following:
128    *    <ul>
129    *       <li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
130    *       <li>A collection or array of {@link EntityTag} objects.
131    *       <li>A collection or array of anything else - Converted to Strings.
132    *       <li>Anything else - Converted to <c>String</c>.
133    *    </ul>
134    * @return A new {@link IfMatch} object.
135    */
136   public static IfMatch of(Supplier<?> value) {
137      if (value == null)
138         return null;
139      return new IfMatch(value);
140   }
141
142   /**
143    * Constructor.
144    *
145    * @param value
146    *    The header value.
147    *    <br>Can be any of the following:
148    *    <ul>
149    *       <li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
150    *       <li>A collection or array of {@link EntityTag} objects.
151    *       <li>A collection or array of anything else - Converted to Strings.
152    *       <li>Anything else - Converted to <c>String</c>.
153    *       <li>A {@link Supplier} of anything on this list.
154    *    </ul>
155    */
156   public IfMatch(Object value) {
157      super("If-Match", value);
158   }
159
160   /**
161    * Constructor
162    *
163    * @param value
164    *    The header value.
165    */
166   public IfMatch(String value) {
167      this((Object)value);
168   }
169}