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.rest.httppart;
014
015import static org.apache.juneau.common.internal.StringUtils.*;
016
017import java.util.*;
018import java.util.function.*;
019
020import org.apache.http.*;
021import org.apache.juneau.annotation.*;
022import org.apache.juneau.assertions.*;
023import org.apache.juneau.http.part.*;
024
025/**
026 * Implementation of a named object.
027 *
028 * <h5 class='section'>See Also:</h5><ul>
029 *    <li class='link'><a class="doclink" href="../../../../../index.html#jrs.HttpParts">HTTP Parts</a>
030 * </ul>
031 */
032@BeanIgnore
033public class BasicNamedAttribute implements NamedAttribute {
034
035   //-----------------------------------------------------------------------------------------------------------------
036   // Static
037   //-----------------------------------------------------------------------------------------------------------------
038
039   /**
040    * Static creator.
041    *
042    * @param name The parameter name.
043    * @param value The parameter value.
044    * @return A new {@link BasicPart} object.
045    */
046   public static BasicNamedAttribute of(String name, Object value) {
047      return new BasicNamedAttribute(name, value);
048   }
049
050   /**
051    * Creates a {@link BasicNamedAttribute} from a name/value pair string (e.g. <js>"Foo: bar"</js>)
052    *
053    * @param pair The pair string.
054    * @return A new {@link NameValuePair} object.
055    */
056   public static BasicNamedAttribute ofPair(String pair) {
057      if (pair == null)
058         return null;
059      int i = pair.indexOf(':');
060      if (i == -1)
061         i = pair.indexOf('=');
062      if (i == -1)
063         return of(pair, "");
064      return of(pair.substring(0,i).trim(), pair.substring(i+1).trim());
065   }
066
067   /**
068    * Static creator with delayed value.
069    *
070    * <p>
071    * Value is re-evaluated on each call to {@link #getValue()}.
072    *
073    * @param name The parameter name.
074    * @param value The parameter value supplier.
075    * @return A new {@link BasicPart} object.
076    */
077   public static BasicNamedAttribute of(String name, Supplier<?> value) {
078      return new BasicNamedAttribute(name, value);
079   }
080
081   //-----------------------------------------------------------------------------------------------------------------
082   // Instance
083   //-----------------------------------------------------------------------------------------------------------------
084
085   private final String name;
086   private final Object value;
087
088   /**
089    * Constructor.
090    *
091    * @param name The parameter name.
092    * @param value The POJO to serialize to the parameter value.
093    */
094   public BasicNamedAttribute(String name, Object value) {
095      this.name = name;
096      this.value = value;
097   }
098
099   /**
100    * Copy constructor.
101    *
102    * @param copyOf The object to copy.
103    */
104   protected BasicNamedAttribute(BasicNamedAttribute copyOf) {
105      this.name = copyOf.name;
106      this.value = copyOf.value;
107   }
108
109   /**
110    * Provides an object for performing assertions against the name of this pair.
111    *
112    * @return An object for performing assertions against the name of this pair.
113    */
114   public FluentStringAssertion<BasicNamedAttribute> assertName() {
115      return new FluentStringAssertion<>(getName(), this);
116   }
117
118   /**
119    * Provides an object for performing assertions against the value of this pair.
120    *
121    * @return An object for performing assertions against the value of this pair.
122    */
123   public FluentObjectAssertion<Object,BasicNamedAttribute> assertValue() {
124      return new FluentObjectAssertion<>(getValue(), this);
125   }
126
127   @Override /* NameValuePair */
128   public String getName() {
129      return name;
130   }
131
132   @Override /* NameValuePair */
133   public Object getValue() {
134      return unwrap(value);
135   }
136
137   /**
138    * Returns <jk>true</jk> if the value exists.
139    *
140    * <p>
141    * This is a shortcut for calling <c>asString().isPresent()</c>.
142    *
143    * @return <jk>true</jk> if the value exists.
144    */
145   public boolean isPresent() {
146      return getValue() != null;
147   }
148
149   /**
150    * If a value is present, returns the value, otherwise throws {@link NoSuchElementException}.
151    *
152    * <p>
153    * This is a shortcut for calling <c>asString().get()</c>.
154    *
155    * @return The value if present.
156    */
157   public Object get() {
158      Object o = getValue();
159      if (o == null)
160         throw new NoSuchElementException();
161      return o;
162   }
163
164   /**
165    * If a value is present, returns the value, otherwise returns other.
166    *
167    * <p>
168    * This is a shortcut for calling <c>asString().orElse(<jv>other</jv>)</c>.
169    *
170    * @param other The other value.
171    * @return The value if present or the other value if not.
172    */
173   public Object orElse(Object other) {
174      Object o = getValue();
175      return o != null ? o : other;
176   }
177
178   @Override /* Object */
179   public String toString() {
180      return urlEncode(getName()) + "=" + getValue();
181   }
182
183   private Object unwrap(Object o) {
184      while (o instanceof Supplier)
185         o = ((Supplier<?>)o).get();
186      return o;
187   }
188}