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