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.http.part;
014
015import static org.apache.juneau.common.internal.ArgUtils.*;
016import static org.apache.juneau.common.internal.StringUtils.*;
017import static org.apache.juneau.internal.ClassUtils.*;
018
019import java.util.*;
020import java.util.function.*;
021
022import org.apache.http.*;
023import org.apache.juneau.*;
024import org.apache.juneau.annotation.*;
025import org.apache.juneau.assertions.*;
026import org.apache.juneau.http.header.*;
027import org.apache.juneau.internal.*;
028import org.apache.juneau.reflect.*;
029
030/**
031 * Implementation of {@link NameValuePair} for serializing POJOs as URL-encoded form post entries.
032 *
033 * Provides the following features:
034 * <ul class='spaced-list'>
035 *    <li>
036 *       Values from {@link Supplier Suppliers}.
037 *    <li>
038 *       Caching.
039 *    <li>
040 *       Fluent setters.
041 *    <li>
042 *       Fluent assertions.
043 * </ul>
044 *
045 * <h5 class='section'>See Also:</h5><ul>
046 *    <li class='link'><a class="doclink" href="../../../../../index.html#juneau-rest-common">juneau-rest-common</a>
047 * </ul>
048 */
049@FluentSetters
050@BeanIgnore
051public class BasicPart implements NameValuePair, Headerable {
052   private final String name;
053   private final Object value;
054
055   /**
056    * Static creator.
057    *
058    * @param name The part name.
059    * @param value The part value.
060    * @return A new {@link BasicPart} object.
061    */
062   public static BasicPart of(String name, Object value) {
063      return new BasicPart(name, value);
064   }
065
066   /**
067    * Creates a {@link NameValuePair} from a name/value pair string (e.g. <js>"Foo: bar"</js>)
068    *
069    * @param pair The pair string.
070    * @return A new {@link NameValuePair} object.
071    */
072   public static BasicPart ofPair(String pair) {
073      if (pair == null)
074         return null;
075      int i = pair.indexOf(':');
076      if (i == -1)
077         i = pair.indexOf('=');
078      if (i == -1)
079         return of(pair, "");
080      return of(pair.substring(0,i).trim(), pair.substring(i+1).trim());
081   }
082
083   /**
084    * Utility method for converting an arbitrary object to a {@link NameValuePair}.
085    *
086    * @param o
087    *    The object to cast or convert to a {@link NameValuePair}.
088    * @return Either the same object cast as a {@link NameValuePair} or converted to a {@link NameValuePair}.
089    */
090   @SuppressWarnings("rawtypes")
091   public static NameValuePair cast(Object o) {
092      if (o instanceof NameValuePair)
093         return (NameValuePair)o;
094      if (o instanceof NameValuePairable)
095         return ((NameValuePairable)o).asNameValuePair();
096      if (o instanceof NameValuePair) {
097         NameValuePair p = (NameValuePair)o;
098         return BasicPart.of(p.getName(), p.getValue());
099      }
100      if (o instanceof Headerable) {
101         Header x = ((Headerable)o).asHeader();
102         return BasicPart.of(x.getName(), x.getValue());
103      }
104      if (o instanceof Map.Entry) {
105         Map.Entry e = (Map.Entry)o;
106         return BasicPart.of(stringify(e.getKey()), e.getValue());
107      }
108      throw new BasicRuntimeException("Object of type {0} could not be converted to a Part.", className(o));
109   }
110
111   /**
112    * Returns <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object.
113    *
114    * @param o The object to check.
115    * @return <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object.
116    */
117   public static boolean canCast(Object o) {
118      ClassInfo ci = ClassInfo.of(o);
119      return ci != null && ci.isChildOfAny(Headerable.class, NameValuePair.class, NameValuePairable.class, Map.Entry.class);
120   }
121
122   /**
123    * Constructor.
124    *
125    * @param name The part name.
126    * @param value The POJO to serialize to The part value.
127    */
128   public BasicPart(String name, Object value) {
129      this.name = name;
130      this.value = value;
131   }
132
133   /**
134    * Copy constructor.
135    *
136    * @param copyFrom The object to copy.
137    */
138   protected BasicPart(BasicPart copyFrom) {
139      assertArgNotNull("copyFrom", copyFrom);
140      this.name = copyFrom.name;
141      this.value = copyFrom.value;
142   }
143
144   /**
145    * Provides an object for performing assertions against the name of this pair.
146    *
147    * @return An object for performing assertions against the name of this pair.
148    */
149   public FluentStringAssertion<BasicPart> assertName() {
150      return new FluentStringAssertion<>(getName(), this);
151   }
152
153   /**
154    * Provides an object for performing assertions against the value of this pair.
155    *
156    * @return An object for performing assertions against the value of this pair.
157    */
158   public FluentStringAssertion<BasicPart> assertValue() {
159      return new FluentStringAssertion<>(getValue(), this);
160   }
161
162   @Override /* Headerable */
163   public BasicHeader asHeader() {
164      return BasicHeader.of(name, stringify(value));
165   }
166
167   @Override /* NameValuePair */
168   public String getName() {
169      return name;
170   }
171
172   @Override /* NameValuePair */
173   public String getValue() {
174      return stringify(unwrap(value));
175   }
176
177   /**
178    * Returns the raw value of the part.
179    *
180    * @return The raw value of the part.
181    */
182   public Object getRawValue() {
183      return unwrap(value);
184   }
185
186   @Override /* Object */
187   public String toString() {
188      return getName() + "=" + getValue();
189   }
190
191   private Object unwrap(Object o) {
192      while (o instanceof Supplier)
193         o = ((Supplier<?>)o).get();
194      return o;
195   }
196
197   // <FluentSetters>
198
199   // </FluentSetters>
200}