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;
018
019import static org.apache.juneau.commons.utils.ThrowableUtils.*;
020import static org.apache.juneau.commons.utils.Utils.*;
021
022import java.net.*;
023import java.time.*;
024import java.util.*;
025import java.util.function.*;
026
027import org.apache.http.*;
028import org.apache.juneau.*;
029import org.apache.juneau.http.header.*;
030import org.apache.juneau.http.part.*;
031import org.apache.juneau.httppart.*;
032import org.apache.juneau.commons.lang.*;
033import org.apache.juneau.commons.reflect.*;
034
035/**
036 * Standard predefined HTTP parts.
037 *
038 * <h5 class='section'>See Also:</h5><ul>
039 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a>
040 * </ul>
041 */
042public class HttpParts {
043
044   private static final Function<ClassMeta<?>,String> HEADER_NAME_FUNCTION = x -> {
045      var n = Value.<String>empty();
046      x.forEachAnnotation(org.apache.juneau.http.annotation.Header.class, y -> ne(y.value()), y -> n.set(y.value()));
047      x.forEachAnnotation(org.apache.juneau.http.annotation.Header.class, y -> ne(y.name()), y -> n.set(y.name()));
048      return n.orElse(null);
049   };
050
051   private static final Function<ClassMeta<?>,String> QUERY_NAME_FUNCTION = x -> {
052      var n = Value.<String>empty();
053      x.forEachAnnotation(org.apache.juneau.http.annotation.Query.class, y -> ne(y.value()), y -> n.set(y.value()));
054      x.forEachAnnotation(org.apache.juneau.http.annotation.Query.class, y -> ne(y.name()), y -> n.set(y.name()));
055      return n.orElse(null);
056   };
057
058   private static final Function<ClassMeta<?>,String> FORMDATA_NAME_FUNCTION = x -> {
059      var n = Value.<String>empty();
060      x.forEachAnnotation(org.apache.juneau.http.annotation.FormData.class, y -> ne(y.value()), y -> n.set(y.value()));
061      x.forEachAnnotation(org.apache.juneau.http.annotation.FormData.class, y -> ne(y.name()), y -> n.set(y.name()));
062      return n.orElse(null);
063   };
064
065   private static final Function<ClassMeta<?>,String> PATH_NAME_FUNCTION = x -> {
066      var n = Value.<String>empty();
067      x.forEachAnnotation(org.apache.juneau.http.annotation.Path.class, y -> ne(y.value()), y -> n.set(y.value()));
068      x.forEachAnnotation(org.apache.juneau.http.annotation.Path.class, y -> ne(y.name()), y -> n.set(y.name()));
069      return n.orElse(null);
070   };
071
072   private static final Function<ClassMeta<?>,ConstructorInfo> CONSTRUCTOR_FUNCTION = x -> {
073      return x.getPublicConstructor(y -> y.hasParameterTypes(String.class)).orElseGet(() -> x.getPublicConstructor(y -> y.hasParameterTypes(String.class, String.class)).orElse(null));
074   };
075
076   /**
077    * Creates a {@link BasicPart} from a name/value pair string (e.g. <js>"Foo: bar"</js>)
078    *
079    * @param pair The pair string.
080    * @return A new {@link BasicPart} object.
081    */
082   public static final BasicPart basicPart(String pair) {
083      return BasicPart.ofPair(pair);
084   }
085
086   /**
087    * Creates a new {@link BasicPart} part.
088    *
089    * @param name The part name.
090    * @param value The part value.
091    * @return A new {@link BasicPart} object.
092    */
093   public static final BasicPart basicPart(String name, Object value) {
094      return BasicPart.of(name, value);
095   }
096
097   /**
098    * Creates a new {@link BasicPart} part with a delayed value.
099    *
100    * <p>
101    * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
102    *
103    * @param name The part name.
104    * @param value The part value supplier.
105    * @return A new {@link BasicPart} object.
106    */
107   public static final BasicPart basicPart(String name, Supplier<?> value) {
108      return BasicPart.of(name, value);
109   }
110
111   /**
112    * Creates a new {@link BasicBooleanPart} part.
113    *
114    * @param name The part name.
115    * @param value
116    *    The part value.
117    *    <br>Can be any of the following:
118    *    <ul>
119    *       <li>{@link Boolean} - As-is.
120    *       <li>{@link String} - Parsed using {@link Boolean#parseBoolean(String)}.
121    *       <li>Anything else - Converted to <c>String</c> and then parsed.
122    *    </ul>
123    * @return A new {@link BasicBooleanPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
124    */
125   public static final BasicBooleanPart booleanPart(String name, Boolean value) {
126      return BasicBooleanPart.of(name, value);
127   }
128
129   /**
130    * Creates a new {@link BasicBooleanPart} part with a delayed value.
131    *
132    * <p>
133    * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
134    *
135    * @param name The part name.
136    * @param value
137    *    The part value supplier.
138    *    <br>Can be any of the following:
139    *    <ul>
140    *       <li>{@link Boolean} - As-is.
141    *       <li>{@link String} - Parsed using {@link Boolean#parseBoolean(String)}.
142    *       <li>Anything else - Converted to <c>String</c> and then parsed.
143    *    </ul>
144    * @return A new {@link BasicBooleanPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
145    */
146   public static final BasicBooleanPart booleanPart(String name, Supplier<Boolean> value) {
147      return BasicBooleanPart.of(name, value);
148   }
149
150   /**
151    * Returns <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object.
152    *
153    * @param o The object to check.
154    * @return <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object.
155    */
156   public static boolean canCast(Object o) {
157      if (o == null)
158         return false;
159      var ci = ClassInfo.of(o);
160      return nn(ci) && ci.isChildOfAny(Headerable.class, NameValuePair.class, NameValuePairable.class, Map.Entry.class);
161   }
162
163   /**
164    * Utility method for converting an arbitrary object to a {@link NameValuePair}.
165    *
166    * @param o
167    *    The object to cast or convert to a {@link NameValuePair}.
168    * @return Either the same object cast as a {@link NameValuePair} or converted to a {@link NameValuePair}.
169    */
170   public static NameValuePair cast(Object o) {
171      if (o instanceof NameValuePair o2)
172         return o2;
173      if (o instanceof Headerable o3) {
174         Header x = o3.asHeader();
175         return BasicPart.of(x.getName(), x.getValue());
176      }
177      if (o instanceof Map.Entry o4) {
178         return BasicPart.of(s(o4.getKey()), o4.getValue());
179      }
180      throw rex("Object of type {0} could not be converted to a Part.", cn(o));
181   }
182
183   /**
184    * Creates a new {@link BasicCsvArrayPart} part.
185    *
186    * @param name The part name.
187    * @param value
188    *    The part value.
189    *    <br>Can be any of the following:
190    *    <ul>
191    *       <li><c>String</c> - A comma-delimited string.
192    *       <li><c>String[]</c> - A pre-parsed value.
193    *       <li>Any other array type - Converted to <c>String[]</c>.
194    *       <li>Any {@link Collection} - Converted to <c>String[]</c>.
195    *       <li>Anything else - Converted to <c>String</c>.
196    *    </ul>
197    * @return A new {@link BasicCsvArrayPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
198    */
199   public static final BasicCsvArrayPart csvArrayPart(String name, String...value) {
200      return BasicCsvArrayPart.of(name, value);
201   }
202
203   /**
204    * Creates a new {@link BasicCsvArrayPart} part with a delayed value.
205    *
206    * <p>
207    * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
208    *
209    * @param name The part name.
210    * @param value
211    *    The part value supplier.
212    *    <br>Can be any of the following:
213    *    <ul>
214    *       <li><c>String</c> - A comma-delimited string.
215    *       <li><c>String[]</c> - A pre-parsed value.
216    *       <li>Any other array type - Converted to <c>String[]</c>.
217    *       <li>Any {@link Collection} - Converted to <c>String[]</c>.
218    *       <li>Anything else - Converted to <c>String</c>.
219    *    </ul>
220    * @return A new {@link BasicCsvArrayPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
221    */
222   public static final BasicCsvArrayPart csvArrayPart(String name, Supplier<String[]> value) {
223      return BasicCsvArrayPart.of(name, value);
224   }
225
226   /**
227    * Creates a new {@link BasicDatePart} part with a delayed value.
228    *
229    * <p>
230    * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
231    *
232    * @param name The part name.
233    * @param value
234    *    The part value supplier.
235    *    <br>Can be any of the following:
236    *    <ul>
237    *       <li><c>String</c> - An ISO-8601 formated string (e.g. <js>"1994-10-29T19:43:31Z"</js>).
238    *       <li>{@link ZonedDateTime}
239    *       <li>{@link Calendar}
240    *       <li>Anything else - Converted to <c>String</c>.
241    *    </ul>
242    * @return A new {@link BasicDatePart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
243    */
244   public static final BasicDatePart datePart(String name, Supplier<ZonedDateTime> value) {
245      return BasicDatePart.of(name, value);
246   }
247
248   /**
249    * Creates a new {@link BasicDatePart} part.
250    *
251    * @param name The part name.
252    * @param value
253    *    The part value.
254    *    <br>Can be any of the following:
255    *    <ul>
256    *       <li><c>String</c> - An ISO-8601 formated string (e.g. <js>"1994-10-29T19:43:31Z"</js>).
257    *       <li>{@link ZonedDateTime}
258    *       <li>{@link Calendar}
259    *       <li>Anything else - Converted to <c>String</c>.
260    *    </ul>
261    * @return A new {@link BasicDatePart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
262    */
263   public static final BasicDatePart datePart(String name, ZonedDateTime value) {
264      return BasicDatePart.of(name, value);
265   }
266
267   /**
268    * Returns the constructor for the specified type.
269    *
270    * <p>
271    * Looks for one of the following constructors:
272    * <ul class='javatree'>
273    *    <li class='jm><c><jk>public</jk> T(String <jv>value</jv>);</c>
274    *    <li class='jm><c><jk>public</jk> T(String <jv>name</jv>, String <jv>value</jv>);</c>
275    * </ul>
276    *
277    * @param type The header type to find the constructor on.
278    * @return The constructor.  Never <jk>null</jk>.
279    */
280   public static Optional<ConstructorInfo> getConstructor(ClassMeta<?> type) {
281      return type.getProperty("HttpPart.Constructor", CONSTRUCTOR_FUNCTION);
282   }
283
284   /**
285    * Returns the name of the specified part type.
286    *
287    * <p>
288    * Gets the name from one of the following annotations:
289    * <ul class='javatreec'>
290    *    <li class='ja'>{@link org.apache.juneau.http.annotation.Header}
291    *    <li class='ja'>{@link org.apache.juneau.http.annotation.Query}
292    *    <li class='ja'>{@link org.apache.juneau.http.annotation.FormData}
293    *    <li class='ja'>{@link org.apache.juneau.http.annotation.Path}
294    * </ul>
295    *
296    * @param partType The part type.
297    * @param type The type to check.
298    * @return The part name.  Never <jk>null</jk>.
299    */
300   public static Optional<String> getName(HttpPartType partType, ClassMeta<?> type) {
301      return switch (partType) {
302         case FORMDATA -> type.getProperty("HttpPart.formData.name", FORMDATA_NAME_FUNCTION);
303         case HEADER -> type.getProperty("HttpPart.header.name", HEADER_NAME_FUNCTION);
304         case PATH -> type.getProperty("HttpPart.path.name", PATH_NAME_FUNCTION);
305         case QUERY -> type.getProperty("HttpPart.query.name", QUERY_NAME_FUNCTION);
306         default -> opte();
307      };
308   }
309
310   /**
311    * Creates a new {@link BasicIntegerPart} part.
312    *
313    * @param name The part name.
314    * @param value
315    *    The part value.
316    *    <br>Can be any of the following:
317    *    <ul>
318    *       <li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
319    *       <li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
320    *       <li>Anything else - Converted to <c>String</c>.
321    *    </ul>
322    * @return A new {@link BasicIntegerPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
323    */
324   public static final BasicIntegerPart integerPart(String name, Integer value) {
325      return BasicIntegerPart.of(name, value);
326   }
327
328   /**
329    * Creates a new {@link BasicIntegerPart} part with a delayed value.
330    *
331    * <p>
332    * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
333    *
334    * @param name The part name.
335    * @param value
336    *    The part value supplier.
337    *    <br>Can be any of the following:
338    *    <ul>
339    *       <li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
340    *       <li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
341    *       <li>Anything else - Converted to <c>String</c>.
342    *    </ul>
343    * @return A new {@link BasicIntegerPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
344    */
345   public static final BasicIntegerPart integerPart(String name, Supplier<Integer> value) {
346      return BasicIntegerPart.of(name, value);
347   }
348
349   /**
350    * Returns <jk>true</jk> if the specified type is a part type.
351    *
352    * <p>
353    * A part type extends from either {@link org.apache.http.Header} or {@link org.apache.http.NameValuePair}
354    * or is annotated with {@link org.apache.juneau.http.annotation.Header}, {@link org.apache.juneau.http.annotation.Query},
355    * {@link org.apache.juneau.http.annotation.FormData}, or {@link org.apache.juneau.http.annotation.Path}.
356    *
357    * @param partType The part type.
358    * @param type The type to check.
359    * @return <jk>true</jk> if the specified type is a part type.
360    */
361   public static boolean isHttpPart(HttpPartType partType, ClassMeta<?> type) {
362      return switch (partType) {
363         case PATH, QUERY, FORMDATA -> type.getProperty("HttpPart.isNameValuePair", x -> x.isChildOf(NameValuePair.class)).orElse(false);
364         case HEADER -> type.getProperty("HttpPart.isHeader", x -> x.isChildOf(org.apache.http.Header.class)).orElse(false);
365         default -> false;
366      };
367   }
368
369   /**
370    * Creates a new {@link BasicLongPart} part.
371    *
372    * @param name The part name.
373    * @param value
374    *    The part value.
375    *    <br>Can be any of the following:
376    *    <ul>
377    *       <li>{@link Number} - Converted to a long using {@link Number#longValue()}.
378    *       <li>{@link String} - Parsed using {@link Long#parseLong(String)}.
379    *       <li>Anything else - Converted to <c>String</c>.
380    *    </ul>
381    * @return A new {@link BasicLongPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
382    */
383   public static final BasicLongPart longPart(String name, Long value) {
384      return BasicLongPart.of(name, value);
385   }
386
387   /**
388    * Creates a new {@link BasicLongPart} part with a delayed value.
389    *
390    * <p>
391    * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
392    *
393    * @param name The part name.
394    * @param value
395    *    The part value supplier.
396    *    <br>Can be any of the following:
397    *    <ul>
398    *       <li>{@link Number} - Converted to a long using {@link Number#longValue()}.
399    *       <li>{@link String} - Parsed using {@link Long#parseLong(String)}.
400    *       <li>Anything else - Converted to <c>String</c>.
401    *    </ul>
402    * @return A new {@link BasicLongPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
403    */
404   public static final BasicLongPart longPart(String name, Supplier<Long> value) {
405      return BasicLongPart.of(name, value);
406   }
407
408   /**
409    * Instantiates a new {@link org.apache.juneau.http.part.PartList}.
410    *
411    * @return A new part list.
412    */
413   public static final PartList partList() {
414      return PartList.create();
415   }
416
417   /**
418    * Creates a new {@link PartList} initialized with the specified parts.
419    *
420    * @param parts The parts to add to the list.  Can be <jk>null</jk>.  <jk>null</jk> entries are ignored.
421    * @return A new unmodifiable instance, never <jk>null</jk>.
422    */
423   public static final PartList partList(List<NameValuePair> parts) {
424      return PartList.of(parts);
425   }
426
427   /**
428    * Creates a new {@link PartList} initialized with the specified parts.
429    *
430    * @param parts The parts to add to the list.  <jk>null</jk> entries are ignored.
431    * @return A new unmodifiable instance, never <jk>null</jk>.
432    */
433   public static final PartList partList(NameValuePair...parts) {
434      return PartList.of(parts);
435   }
436
437   /**
438    * Creates a new {@link PartList} initialized with the specified name/value pairs.
439    *
440    * @param pairs
441    *    Initial list of pairs.
442    *    <br>Must be an even number of parameters representing key/value pairs.
443    * @throws RuntimeException If odd number of parameters were specified.
444    * @return A new instance.
445    */
446   public static PartList partList(String...pairs) {
447      return PartList.ofPairs(pairs);
448   }
449
450   /**
451    * Creates a new {@link SerializedPart} part.
452    *
453    * @param name The part name.
454    * @param value
455    *    The part value.
456    *    <br>Can be any POJO.
457    * @return A new {@link SerializedPart} object, never <jk>null</jk>.
458    */
459   public static final SerializedPart serializedPart(String name, Object value) {
460      return SerializedPart.of(name, value);
461   }
462
463   /**
464    * Creates a new {@link SerializedPart} part with a delayed value.
465    *
466    * @param name The part name.
467    * @param value
468    *    The part value supplier.
469    *    <br>Can be a supplier of any POJO.
470    * @return A new {@link SerializedPart} object, never <jk>null</jk>.
471    */
472   public static final SerializedPart serializedPart(String name, Supplier<?> value) {
473      return SerializedPart.of(name, value);
474   }
475
476   /**
477    * Creates a new {@link BasicStringPart} part.
478    *
479    * @param name The part name.
480    * @param value
481    *    The part value.
482    *    <br>Can be any of the following:
483    *    <ul>
484    *       <li>{@link String}
485    *       <li>Anything else - Converted to <c>String</c> then parsed.
486    *    </ul>
487    * @return A new {@link BasicStringPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
488    */
489   public static final BasicStringPart stringPart(String name, String value) {
490      return BasicStringPart.of(name, value);
491   }
492
493   /**
494    * Creates a new {@link BasicStringPart} part with a delayed value.
495    *
496    * <p>
497    * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
498    *
499    * @param name The part name.
500    * @param value
501    *    The part value supplier.
502    *    <br>Can be any of the following:
503    *    <ul>
504    *       <li>{@link String}
505    *       <li>Anything else - Converted to <c>String</c> then parsed.
506    *    </ul>
507    * @return A new {@link BasicStringPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
508    */
509   public static final BasicStringPart stringPart(String name, Supplier<String> value) {
510      return BasicStringPart.of(name, value);
511   }
512
513   /**
514    * Creates a new {@link BasicUriPart} part with a delayed value.
515    *
516    * <p>
517    * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
518    *
519    * @param name The header name.
520    * @param value
521    *    The header value supplier.
522    *    <br>Can be any of the following:
523    *    <ul>
524    *       <li>{@link String}
525    *       <li>Anything else - Converted to <c>String</c> then parsed.
526    *    </ul>
527    * @return A new {@link BasicUriPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
528    */
529   public static final BasicUriPart uriPart(String name, Supplier<URI> value) {
530      return BasicUriPart.of(name, value);
531   }
532
533   /**
534    * Creates a new {@link BasicUriPart} part.
535    *
536    * @param name The header name.
537    * @param value
538    *    The header value.
539    *    <br>Can be any of the following:
540    *    <ul>
541    *       <li>{@link String}
542    *       <li>Anything else - Converted to <c>String</c> then parsed.
543    *    </ul>
544    * @return A new {@link BasicUriPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
545    */
546   public static final BasicUriPart uriPart(String name, URI value) {
547      return BasicUriPart.of(name, value);
548   }
549}