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