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.internal.StringUtils.*;
016
017import java.lang.reflect.*;
018import java.util.*;
019import java.util.function.*;
020
021import org.apache.juneau.collections.*;
022import org.apache.juneau.http.*;
023import org.apache.juneau.internal.*;
024
025/**
026 * Category of headers that consist of a comma-delimited list of entity validator values.
027 *
028 * <p>
029 * <h5 class='figure'>Example</h5>
030 * <p class='bcode w800'>
031 *    If-Match: "xyzzy"
032 *    If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
033 *    If-Match: *
034 * </p>
035 *
036 * <ul class='seealso'>
037 *    <li class='extlink'>{@doc ExtRFC2616}
038 * </ul>
039 */
040public class BasicEntityTagArrayHeader extends BasicHeader {
041
042   private static final long serialVersionUID = 1L;
043
044   /**
045    * Convenience creator.
046    *
047    * @param name The header name.
048    * @param value
049    *    The header value.
050    *    <br>Can be any of the following:
051    *    <ul>
052    *       <li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
053    *       <li>A collection or array of {@link EntityTag} objects.
054    *       <li>A collection or array of anything else - Converted to Strings.
055    *       <li>Anything else - Converted to <c>String</c>.
056    *    </ul>
057    * @return A new {@link BasicEntityTagArrayHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
058    */
059   public static BasicEntityTagArrayHeader of(String name, Object value) {
060      if (isEmpty(name) || value == null)
061         return null;
062      return new BasicEntityTagArrayHeader(name, value);
063   }
064
065   /**
066    * Convenience creator using supplier.
067    *
068    * <p>
069    * Header value is re-evaluated on each call to {@link #getValue()}.
070    *
071    * @param name The header name.
072    * @param value
073    *    The header value supplier.
074    *    <br>Can be any of the following:
075    *    <ul>
076    *       <li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
077    *       <li>A collection or array of {@link EntityTag} objects.
078    *       <li>A collection or array of anything else - Converted to Strings.
079    *       <li>Anything else - Converted to <c>String</c>.
080    *    </ul>
081    * @return A new {@link BasicEntityTagArrayHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
082    */
083   public static BasicEntityTagArrayHeader of(String name, Supplier<?> value) {
084      if (isEmpty(name) || value == null)
085         return null;
086      return new BasicEntityTagArrayHeader(name, value);
087   }
088
089   private List<EntityTag> parsed;
090
091   /**
092    * Constructor.
093    *
094    * @param name The header name.
095    * @param value
096    *    The header value.
097    *    <br>Can be any of the following:
098    *    <ul>
099    *       <li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
100    *       <li>A collection or array of {@link EntityTag} objects.
101    *       <li>A collection or array of anything else - Converted to Strings.
102    *       <li>Anything else - Converted to <c>String</c>.
103    *       <li>A {@link Supplier} of anything on this list.
104    *    </ul>
105    */
106   public BasicEntityTagArrayHeader(String name, Object value) {
107      super(name, value);
108      if (! isSupplier(value))
109         parsed = getParsedValue();
110   }
111
112   @Override /* Header */
113   public String getValue() {
114      Object o = getRawValue();
115      if (o instanceof String)
116         return (String)o;
117      return StringUtils.join(asEntityTags(), ',');
118   }
119
120   /**
121    * Returns this header value as an array of {@link EntityTag} objects.
122    *
123    * @return this header value as an array of {@link EntityTag} objects.
124    */
125   public List<EntityTag> asEntityTags() {
126      return getParsedValue();
127   }
128
129   private List<EntityTag> getParsedValue() {
130      if (parsed != null)
131         return parsed;
132      Object o = getRawValue();
133      if (o == null)
134         return null;
135      if (o instanceof EntityTag[])
136         return AList.of((EntityTag[])o).unmodifiable();
137
138      AList<EntityTag> l = AList.of();
139      if (o instanceof Collection) {
140         for (Object o2 : (Collection<?>)o)
141            l.add(EntityTag.of(o2));
142      } else if (o.getClass().isArray()) {
143         for (int i = 0; i < Array.getLength(o); i++)
144            l.add(EntityTag.of(Array.get(o, i)));
145      } else {
146         for (String s : split(o.toString()))
147            l.add(EntityTag.of(s));
148      }
149      return l.unmodifiable();
150   }
151}