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.part;
018
019import static org.apache.juneau.common.utils.Utils.*;
020import static org.apache.juneau.internal.ArrayUtils.*;
021
022import java.util.*;
023import java.util.function.*;
024
025import org.apache.http.*;
026import org.apache.juneau.assertions.*;
027import org.apache.juneau.common.utils.*;
028
029/**
030 * A {@link NameValuePair} that consists of a comma-delimited list of string values.
031 *
032 * <h5 class='section'>See Also:</h5><ul>
033 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a>
034 * </ul>
035 */
036public class BasicCsvArrayPart extends BasicPart {
037
038   //-----------------------------------------------------------------------------------------------------------------
039   // Static
040   //-----------------------------------------------------------------------------------------------------------------
041
042   private static final String[] EMPTY = {};
043
044   /**
045    * Static creator.
046    *
047    * @param name The part name.
048    * @param value The part value.
049    * @return A new {@link BasicCsvArrayPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
050    */
051   public static BasicCsvArrayPart of(String name, String...value) {
052      if (Utils.isEmpty(name) || value == null)
053         return null;
054      return new BasicCsvArrayPart(name, value);
055   }
056
057   /**
058    * Static creator with delayed value.
059    *
060    * <p>
061    * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
062    *
063    * @param name The part name.
064    * @param value The part value supplier.
065    * @return A new {@link BasicCsvArrayPart} object, or <jk>null</jk> if the name or supplier is <jk>null</jk>.
066    */
067   public static BasicCsvArrayPart of(String name, Supplier<String[]> value) {
068      if (Utils.isEmpty(name) || value == null)
069         return null;
070      return new BasicCsvArrayPart(name, value);
071   }
072
073   //-----------------------------------------------------------------------------------------------------------------
074   // Instance
075   //-----------------------------------------------------------------------------------------------------------------
076
077   private final String[] value;
078   private final Supplier<String[]> supplier;
079   private String stringValue;
080
081   /**
082    * Constructor.
083    *
084    * @param name The part name.  Must not be <jk>null</jk>.
085    * @param value The part value.  Can be <jk>null</jk>.
086    */
087   public BasicCsvArrayPart(String name, String...value) {
088      super(name, value);
089      this.value = value;
090      this.supplier = null;
091      this.stringValue = null;
092   }
093
094   /**
095    * Constructor.
096    *
097    * @param name The part name.  Must not be <jk>null</jk>.
098    * @param value The part value supplier.  Can be <jk>null</jk> or supply <jk>null</jk>.
099    */
100   public BasicCsvArrayPart(String name, Supplier<String[]> value) {
101      super(name, value);
102      this.value = null;
103      this.supplier = value;
104      this.stringValue = null;
105   }
106
107   /**
108    * Constructor.
109    *
110    * <p>
111    * <jk>null</jk> values are treated as <jk>null</jk>.
112    * Otherwise parses as a comma-delimited list with whitespace trimmed.
113    *
114    * @param name The part name.  Must not be <jk>null</jk>.
115    * @param value The part value.  Can be <jk>null</jk>.
116    */
117   public BasicCsvArrayPart(String name, String value) {
118      super(name, value);
119      this.value = splita(value);
120      this.supplier = null;
121      this.stringValue = value;
122   }
123
124   @Override /* Header */
125   public String getValue() {
126      if (supplier != null)
127         return Utils.join(supplier.get(), ',');
128      if (stringValue != null)
129         stringValue = Utils.join(value, ',');
130      return stringValue;
131   }
132
133   /**
134    * Returns <jk>true</jk> if this part contains the specified value.
135    *
136    * @param val The value to check for.
137    * @return <jk>true</jk> if this part contains the specified value.
138    */
139   public boolean contains(String val) {
140      if (val != null)
141         for (String v : value())
142            if (Utils.eq(v, val))
143               return true;
144      return false;
145   }
146
147   /**
148    * Returns <jk>true</jk> if this part contains the specified value using {@link String#equalsIgnoreCase(String)}.
149    *
150    * @param val The value to check for.
151    * @return <jk>true</jk> if this part contains the specified value.
152    */
153   public boolean containsIgnoreCase(String val) {
154      if (val != null)
155         for (String v : value())
156            if (Utils.eqic(v, val))
157               return true;
158      return false;
159   }
160
161   /**
162    * Provides the ability to perform fluent-style assertions on this part.
163    *
164    * @return A new fluent assertion object.
165    * @throws AssertionError If assertion failed.
166    */
167   public FluentListAssertion<String,BasicCsvArrayPart> assertList() {
168      return new FluentListAssertion<>(u(alist(value())), this);
169   }
170
171   /**
172    * Returns The part value as a {@link List}.
173    *
174    * <p>
175    * The list is unmodifiable.
176    *
177    * @return The part value as a {@link List}, or <jk>null</jk> if the value <jk>null</jk>.
178    */
179   public List<String> toList() {
180      return u(alist(value()));
181   }
182
183   /**
184    * Returns The part value as a {@link List} wrapped in an {@link Optional}.
185    *
186    * <p>
187    * The list is unmodifiable.
188    *
189    * @return The part value as a {@link List} wrapped in an {@link Optional}.  Never <jk>null</jk>.
190    */
191   public Optional<List<String>> asList() {
192      return Utils.opt(toList());
193   }
194
195   /**
196    * Returns The part value as an array.
197    *
198    * <p>
199    * The array is a copy of the value of this part.
200    *
201    * @return The part value as an array, or <jk>null</jk> if the value <jk>null</jk>.
202    */
203   public String[] toArray() {
204      return copyOf(value());
205   }
206
207   /**
208    * Returns The part value as an array wrapped in an {@link Optional}.
209    *
210    * <p>
211    * Array is a copy of the value of this part.
212    *
213    * @return The part value as an array wrapped in an {@link Optional}.  Never <jk>null</jk>.
214    */
215   public Optional<String[]> asArray() {
216      return Utils.opt(copyOf(value()));
217   }
218
219   /**
220    * Return the value if present, otherwise return <c>other</c>.
221    *
222    * <p>
223    * This is a shortened form for calling <c>asArray().orElse(<jv>other</jv>)</c>.
224    *
225    * @param other The value to be returned if there is no value present, can be <jk>null</jk>.
226    * @return The value, if present, otherwise <c>other</c>.
227    */
228   public String[] orElse(String[] other) {
229      String[] x = value();
230      return x != null ? x : other;
231   }
232
233   private String[] value() {
234      if (supplier != null) {
235         String[] v = supplier.get();
236         return v != null ? v : EMPTY;
237      }
238      return value;
239   }
240}