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