blob: 292289c904c674a58be1d24b811a50ac0ffeef03 [file] [log] [blame]
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
// * with the License. You may obtain a copy of the License at *
// * *
// * http://www.apache.org/licenses/LICENSE-2.0 *
// * *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
// * specific language governing permissions and limitations under the License. *
// ***************************************************************************************************************************
package org.apache.juneau.http.part;
import static org.apache.juneau.assertions.Assertions.*;
import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.ExceptionUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import java.util.*;
import java.util.function.*;
import org.apache.http.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.assertions.*;
import org.apache.juneau.http.header.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.reflect.*;
/**
* Implementation of {@link NameValuePair} for serializing POJOs as URL-encoded form post entries.
*
* Provides the following features:
* <ul class='spaced-list'>
* <li>
* Values from {@link Supplier Suppliers}.
* <li>
* Caching.
* <li>
* Fluent setters.
* <li>
* Fluent assertions.
* </ul>
*/
@FluentSetters
@BeanIgnore
public class BasicPart implements NameValuePair, Headerable {
private final String name;
private final Object value;
/**
* Convenience creator.
*
* @param name The part name.
* @param value The part value.
* @return A new {@link BasicPart} object.
*/
public static BasicPart of(String name, Object value) {
return new BasicPart(name, value);
}
/**
* Creates a {@link NameValuePair} from a name/value pair string (e.g. <js>"Foo: bar"</js>)
*
* @param pair The pair string.
* @return A new {@link NameValuePair} object.
*/
public static BasicPart ofPair(String pair) {
if (pair == null)
return null;
int i = pair.indexOf(':');
if (i == -1)
i = pair.indexOf('=');
if (i == -1)
return of(pair, "");
return of(pair.substring(0,i).trim(), pair.substring(i+1).trim());
}
/**
* Convenience creator using supplier.
*
* <p>
* Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
*
* @param name The part name.
* @param value The part value supplier.
* @return A new {@link BasicPart} object.
*/
public static BasicPart of(String name, Supplier<?> value) {
return new BasicPart(name, value);
}
/**
* Utility method for converting an arbitrary object to a {@link NameValuePair}.
*
* @param o
* The object to cast or convert to a {@link NameValuePair}.
* @return Either the same object cast as a {@link NameValuePair} or converted to a {@link NameValuePair}.
*/
@SuppressWarnings("rawtypes")
public static NameValuePair cast(Object o) {
if (o instanceof NameValuePair)
return (NameValuePair)o;
if (o instanceof NameValuePairable)
return ((NameValuePairable)o).asNameValuePair();
if (o instanceof NameValuePair) {
NameValuePair p = (NameValuePair)o;
return BasicPart.of(p.getName(), p.getValue());
}
if (o instanceof Headerable) {
Header x = ((Headerable)o).asHeader();
return BasicPart.of(x.getName(), x.getValue());
}
if (o instanceof Map.Entry) {
Map.Entry e = (Map.Entry)o;
return BasicPart.of(stringify(e.getKey()), e.getValue());
}
throw runtimeException("Object of type {0} could not be converted to a Part.", className(o));
}
/**
* Returns <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object.
*
* @param o The object to check.
* @return <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object.
*/
public static boolean canCast(Object o) {
ClassInfo ci = ClassInfo.of(o);
return ci != null && ci.isChildOfAny(Headerable.class, NameValuePair.class, NameValuePairable.class, Map.Entry.class);
}
/**
* Constructor.
*
* @param name The part name.
* @param value The POJO to serialize to The part value.
*/
public BasicPart(String name, Object value) {
this.name = name;
this.value = value;
}
/**
* Copy constructor.
*
* @param copyFrom The object to copy.
*/
protected BasicPart(BasicPart copyFrom) {
assertArgNotNull("copyFrom", copyFrom);
this.name = copyFrom.name;
this.value = copyFrom.value;
}
/**
* Provides an object for performing assertions against the name of this pair.
*
* @return An object for performing assertions against the name of this pair.
*/
public FluentStringAssertion<BasicPart> assertName() {
return new FluentStringAssertion<>(getName(), this);
}
/**
* Provides an object for performing assertions against the value of this pair.
*
* @return An object for performing assertions against the value of this pair.
*/
public FluentStringAssertion<BasicPart> assertValue() {
return new FluentStringAssertion<>(getValue(), this);
}
@Override /* Headerable */
public BasicHeader asHeader() {
return BasicHeader.of(name, stringify(value));
}
@Override /* NameValuePair */
public String getName() {
return name;
}
@Override /* NameValuePair */
public String getValue() {
return stringify(unwrap(value));
}
/**
* Returns the raw value of the part.
*
* @return The raw value of the part.
*/
public Object getRawValue() {
return unwrap(value);
}
/**
* Returns <jk>true</jk> if the specified object is a {@link Supplier}.
*
* @param o The object to check.
* @return <jk>true</jk> if the specified object is a {@link Supplier}.
*/
protected boolean isSupplier(Object o) {
return o instanceof Supplier;
}
@Override /* Object */
public String toString() {
return getName() + "=" + getValue();
}
private Object unwrap(Object o) {
while (o instanceof Supplier)
o = ((Supplier<?>)o).get();
return o;
}
// <FluentSetters>
// </FluentSetters>
}