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}