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.commons.utils.Shorts.*;
020
021import java.util.function.*;
022
023import org.apache.juneau.http.*;
024
025/**
026 * Root concrete implementation of {@link HttpPart}.
027 *
028 * <p>
029 * Holds a name/value pair representing a query parameter, form field, or path variable.  The value may be
030 * supplied eagerly (as a {@link String}) or lazily (via a {@link Supplier}).  A {@code null} value signals
031 * that the part should be omitted from the request.
032 *
033 * <p>
034 * Create instances via the static factory methods:
035 * <p class='bjava'>
036 *    <jc>// Eager</jc>
037 *    HttpPart <jv>p1</jv> = HttpPartBean.<jsm>of</jsm>(<js>"status"</js>, <js>"active"</js>);
038 *
039 *    <jc>// Lazy — evaluated at request-send time</jc>
040 *    HttpPart <jv>p2</jv> = HttpPartBean.<jsm>of</jsm>(<js>"page"</js>, () -> String.valueOf(currentPage()));
041 * </p>
042 *
043 * <h5 class='section'>See Also:</h5><ul>
044 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/NextGenRestClient">Next-Generation REST Client</a>
045 * </ul>
046 *
047 * @since 9.2.1
048 */
049public class HttpPartBean implements HttpPart {
050
051   private final String name;
052   private final Supplier<String> valueSupplier;
053
054   /**
055    * Constructor.
056    *
057    * @param name The part name. Must not be <jk>null</jk>.
058    * @param value The part value. May be <jk>null</jk>.
059    */
060   protected HttpPartBean(String name, String value) {
061      this.name = reqnn("name", name);
062      this.valueSupplier = () -> value;
063   }
064
065   /**
066    * Constructor with lazy value supplier.
067    *
068    * @param name The part name. Must not be <jk>null</jk>.
069    * @param valueSupplier Supplier that provides the value at request time. Must not be <jk>null</jk>.
070    */
071   protected HttpPartBean(String name, Supplier<String> valueSupplier) {
072      this.name = reqnn("name", name);
073      this.valueSupplier = reqnn("valueSupplier", valueSupplier);
074   }
075
076   /**
077    * Creates an {@link HttpPartBean} with an eager string value.
078    *
079    * @param name The part name. Must not be <jk>null</jk>.
080    * @param value The part value. May be <jk>null</jk>.
081    * @return A new instance. Never <jk>null</jk>.
082    */
083   public static HttpPartBean of(String name, String value) {
084      return new HttpPartBean(name, value);
085   }
086
087   /**
088    * Creates an {@link HttpPartBean} with a lazy value supplier.
089    *
090    * <p>
091    * The supplier is evaluated at request-send time; if it returns {@code null} the part is omitted.
092    *
093    * @param name The part name. Must not be <jk>null</jk>.
094    * @param valueSupplier Supplier for the part value. Must not be <jk>null</jk>.
095    * @return A new instance. Never <jk>null</jk>.
096    */
097   public static HttpPartBean of(String name, Supplier<String> valueSupplier) {
098      return new HttpPartBean(name, valueSupplier);
099   }
100
101   @Override /* HttpPart */
102   public String getName() {
103      return name;
104   }
105
106   @Override /* HttpPart */
107   public String getValue() {
108      return valueSupplier.get();
109   }
110
111   @Override /* Object */
112   public String toString() {
113      return name + "=" + getValue();
114   }
115
116   @Override /* Object */
117   public boolean equals(Object obj) {
118      return (obj instanceof HttpPartBean o2) && eq(this, o2, (x, y) -> eq(x.name, y.name) && eq(x.getValue(), y.getValue()));
119   }
120
121   @Override /* Object */
122   public int hashCode() {
123      return h(name, getValue());
124   }
125}