![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.juneau.rest.httppart.RequestHttpPart Maven / Gradle / Ivy
// ***************************************************************************************************************************
// * 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.rest.httppart;
import static org.apache.juneau.httppart.HttpPartType.*;
import static org.apache.juneau.internal.CollectionUtils.*;
import java.lang.reflect.*;
import java.time.*;
import java.util.*;
import java.util.regex.*;
import org.apache.http.*;
import org.apache.juneau.*;
import org.apache.juneau.assertions.*;
import org.apache.juneau.http.*;
import org.apache.juneau.http.part.*;
import org.apache.juneau.http.response.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.oapi.*;
import org.apache.juneau.parser.ParseException;
import org.apache.juneau.reflect.*;
import org.apache.juneau.rest.*;
/**
* Represents a single HTTP part on an HTTP request.
*
* Parent of the following classes:
*
* - {@link RequestHeader}
*
- {@link RequestQueryParam}
*
- {@link RequestFormParam}
*
- {@link RequestPathParam}
*
*
* See Also:
* - HTTP Parts
*
*/
@FluentSetters
public class RequestHttpPart {
private final HttpPartType partType;
private final String name;
private final RestRequest request;
private HttpPartParserSession parser;
private HttpPartSchema schema;
String value;
/**
* Constructor.
*
* @param partType The HTTP part type.
* @param request The request object.
* @param name The part name.
* @param value The part value.
*/
public RequestHttpPart(HttpPartType partType, RestRequest request, String name, String value) {
this.partType = partType;
this.request = request;
this.name = name;
this.value = value;
parser(null);
}
//------------------------------------------------------------------------------------------------------------------
// Setters
//------------------------------------------------------------------------------------------------------------------
/**
* Specifies the part schema for this part.
*
*
* Used by schema-based part parsers such as {@link OpenApiParser}.
*
* @param value
* The part schema.
* @return This object.
*/
@FluentSetter
public RequestHttpPart schema(HttpPartSchema value) {
this.schema = value;
return this;
}
/**
* Specifies the part parser to use for this part.
*
*
* If not specified, uses the part parser defined on the client by calling {@link org.apache.juneau.rest.RestContext.Builder#partParser()}.
*
* @param value
* The new part parser to use for this part.
*
If null , {@link SimplePartParser#DEFAULT} will be used.
* @return This object.
*/
@FluentSetter
public RequestHttpPart parser(HttpPartParserSession value) {
this.parser = value == null ? SimplePartParser.DEFAULT_SESSION : value;
return this;
}
/**
* Sets a default value for this part.
*
* @param def The default value.
* @return This object.
*/
public RequestHttpPart def(String def) {
if (value == null)
value = def;
return this;
}
//------------------------------------------------------------------------------------------------------------------
// Retrievers
//------------------------------------------------------------------------------------------------------------------
/**
* Returns the value of this part.
*
* @return The value of this part.
*/
public String getValue() {
return value;
}
/**
* Returns true if this part exists on the request.
*
*
* This is a shortened form for calling asString().isPresent() .
*
* @return true if this part exists on the request.
*/
public boolean isPresent() {
return asString().isPresent();
}
/**
* If a value is present, returns the value, otherwise throws {@link NoSuchElementException}.
*
*
* This is a shortened form for calling asString().get() .
*
* @return The value if present.
*/
public String get() {
return asString().get();
}
/**
* Return the value if present, otherwise return other.
*
*
* This is a shortened form for calling asString().orElse(other ) .
*
* @param other The value to be returned if there is no value present, may be null .
* @return The value, if present, otherwise other.
*/
public String orElse(String other) {
return asString().orElse(other);
}
/**
* Returns the value of this part as a string.
*
* @return The value of this part as a string, or {@link Optional#empty()} if the part was not present.
*/
public Optional asString() {
return optional(getValue());
}
/**
* Converts this part to the specified POJO type using the request {@link HttpPartParser} and optional schema.
*
*
* See Complex Data Types for information on defining complex generic types of {@link Map Maps} and {@link Collection Collections}.
*
* @param The type to convert to.
* @param type The type to convert to.
* @param args The type parameters.
* @return The converted type, or {@link Optional#empty()} if the part is not present.
* @throws BasicHttpException If value could not be parsed.
*/
public Optional as(Type type, Type...args) throws BasicHttpException {
return as(request.getBeanSession().getClassMeta(type, args));
}
/**
* Converts this part to the specified POJO type using the request {@link HttpPartParser} and optional schema.
*
*
* If the specified type is an HTTP part type (extends from {@link org.apache.http.Header}/{@link NameValuePair}), then looks for
* one of the following constructors:
*
* public T(String name , String value );
*
*
*
* If it doesn't find one of those constructors, then it parses it into the specified type using the part parser.
*
* @param The type to convert to.
* @param type The type to convert to.
* @return The converted type, or {@link Optional#empty()} if the part is not present.
* @throws BasicHttpException If value could not be parsed.
*/
public Optional as(Class type) throws BasicHttpException {
return as(request.getBeanSession().getClassMeta(type));
}
/**
* Converts this part to the specified POJO type using the request {@link HttpPartParser} and optional schema.
*
*
* If the specified type is an HTTP part type (extends from {@link org.apache.http.Header}/{@link NameValuePair}), then looks for
* one of the following constructors:
*
* public T(String name , String value );
*
*
*
* If it doesn't find one of those constructors, then it parses it into the specified type using the part parser.
*
* @param The type to convert to.
* @param type The type to convert to.
* @return The converted type, or {@link Optional#empty()} if the part is not present.
* @throws BasicHttpException If value could not be parsed.
*/
public Optional as(ClassMeta type) throws BasicHttpException {
try {
if (HttpParts.isHttpPart(partType, type)) {
ConstructorInfo cc = HttpParts.getConstructor(type).orElse(null);
if (cc != null) {
if (! isPresent())
return empty();
if (cc.hasParamTypes(String.class))
return optional(cc.invoke(get()));
if (cc.hasParamTypes(String.class, String.class))
return optional(cc.invoke(getName(), get()));
}
}
return optional(parser.parse(HEADER, schema, orElse(null), type));
} catch (ParseException e) {
throw new BadRequest(e, "Could not parse {0} parameter ''{1}''.", partType.toString().toLowerCase(), getName());
}
}
/**
* Matches the specified pattern against this part value.
*
* Example:
*
* Matcher matcher = request
* .getHeader("Content-Type" )
* .asMatcher(Pattern.compile ("application/(.*)" ));
*
* if (matcher .matches()) {
* String mediaType = matcher .group(1);
* }
*
*
* @param pattern The regular expression pattern to match.
* @return The matcher.
* @throws BasicHttpException If a connection error occurred.
*/
public Matcher asMatcher(Pattern pattern) throws BasicHttpException {
return pattern.matcher(orElse(""));
}
/**
* Matches the specified pattern against this part value.
*
* Example:
*
* Matcher matcher = request
* .getHeader("Content-Type" )
* .asMatcher("application/(.*)" );
*
* if (matcher .matches()) {
* String mediaType = matcher .group(1);
* }
*
*
* @param regex The regular expression pattern to match.
* @return The matcher.
* @throws BasicHttpException If a connection error occurred.
*/
public Matcher asMatcher(String regex) throws BasicHttpException {
return asMatcher(regex, 0);
}
/**
* Matches the specified pattern against this part value.
*
* Example:
*
* Matcher matcher = request
* .getHeader("Content-Type" )
* .asMatcher("application/(.*)" , CASE_INSENSITIVE );
*
* if (matcher .matches()) {
* String mediaType = matcher .group(1);
* }
*
*
* @param regex The regular expression pattern to match.
* @param flags Pattern match flags. See {@link Pattern#compile(String, int)}.
* @return The matcher.
* @throws BasicHttpException If a connection error occurred.
*/
public Matcher asMatcher(String regex, int flags) throws BasicHttpException {
return asMatcher(Pattern.compile(regex, flags));
}
/**
* Returns the value of this parameter as an integer.
*
* @return The value of this parameter as an integer, or {@link Optional#empty()} if the parameter was not present.
*/
public Optional asInteger() {
return asIntegerPart().asInteger();
}
/**
* Returns the value of this parameter as a boolean.
*
* @return The value of this parameter as a boolean, or {@link Optional#empty()} if the parameter was not present.
*/
public Optional asBoolean() {
return asBooleanPart().asBoolean();
}
/**
* Returns the value of this parameter as a long.
*
* @return The value of this parameter as a long, or {@link Optional#empty()} if the parameter was not present.
*/
public Optional asLong() {
return asLongPart().asLong();
}
/**
* Returns the value of this parameter as a date.
*
* @return The value of this parameter as a date, or {@link Optional#empty()} if the parameter was not present.
*/
public Optional asDate() {
return asDatePart().asZonedDateTime();
}
/**
* Returns the value of this parameter as a list from a comma-delimited string.
*
* @return The value of this parameter as a list from a comma-delimited string, or {@link Optional#empty()} if the parameter was not present.
*/
public Optional> asCsvArray() {
return asCsvArrayPart().asList();
}
/**
* Returns the value of this parameter as a {@link BasicCsvArrayPart}.
*
* @return The value of this parameter as a {@link BasicCsvArrayPart}, never null .
*/
public BasicCsvArrayPart asCsvArrayPart() {
return new BasicCsvArrayPart(getName(), getValue());
}
/**
* Returns the value of this parameter as a {@link BasicDatePart}.
*
* @return The value of this parameter as a {@link BasicDatePart}, never null .
*/
public BasicDatePart asDatePart() {
return new BasicDatePart(getName(), getValue());
}
/**
* Returns the value of this parameter as a {@link BasicIntegerPart}.
*
* @return The value of this parameter as a {@link BasicIntegerPart}, never null .
*/
public BasicIntegerPart asIntegerPart() {
return new BasicIntegerPart(getName(), getValue());
}
/**
* Returns the value of this parameter as a {@link BasicBooleanPart}.
*
* @return The value of this parameter as a {@link BasicBooleanPart}, never null .
*/
public BasicBooleanPart asBooleanPart() {
return new BasicBooleanPart(getName(), getValue());
}
/**
* Returns the value of this parameter as a {@link BasicLongPart}.
*
* @return The value of this parameter as a {@link BasicLongPart}, never null .
*/
public BasicLongPart asLongPart() {
return new BasicLongPart(getName(), getValue());
}
/**
* Returns the value of this parameter as a {@link BasicStringPart}.
*
* @return The value of this parameter as a {@link BasicStringPart}, never null .
*/
public BasicStringPart asStringPart() {
return new BasicStringPart(getName(), getValue());
}
/**
* Returns the value of this parameter as a {@link BasicUriPart}.
*
* @return The value of this parameter as a {@link BasicUriPart}, never null .
*/
public BasicUriPart asUriPart() {
return new BasicUriPart(getName(), getValue());
}
//------------------------------------------------------------------------------------------------------------------
// Assertions
//------------------------------------------------------------------------------------------------------------------
/**
* Provides the ability to perform fluent-style assertions on this parameter.
*
* Examples:
*
* request
* .getQueryParam("foo" )
* .assertString().contains("bar" );
*
*
*
* The assertion test returns the original object allowing you to chain multiple requests like so:
*
* String foo = request
* .getQueryParam("foo" )
* .assertString().contains("bar" )
* .asString().get();
*
*
* @return A new fluent assertion object.
*/
public FluentStringAssertion assertString() {
return new FluentStringAssertion<>(orElse(null), this);
}
/**
* Provides the ability to perform fluent-style assertions on an integer parameter.
*
* Examples:
*
* request
* .getQueryParam("age" )
* .assertInteger().isGreaterThan(1);
*
*
* @return A new fluent assertion object.
*/
public FluentIntegerAssertion assertInteger() {
return new FluentIntegerAssertion<>(asIntegerPart().asInteger().orElse(null), this);
}
/**
* Provides the ability to perform fluent-style assertions on a long parameter.
*
* Examples:
*
* request
* .getQueryParam("length" )
* .assertLong().isLessThan(100000);
*
*
* @return A new fluent assertion object.
*/
public FluentLongAssertion assertLong() {
return new FluentLongAssertion<>(asLongPart().asLong().orElse(null), this);
}
/**
* Provides the ability to perform fluent-style assertions on a date parameter.
*
* Examples:
*
* request
* .getQueryParam("time" )
* .assertDate().isAfterNow();
*
*
* @return A new fluent assertion object.
*/
public FluentZonedDateTimeAssertion assertDate() {
return new FluentZonedDateTimeAssertion<>(asDatePart().asZonedDateTime().orElse(null), this);
}
/**
* Provides the ability to perform fluent-style assertions on comma-separated string parameters.
*
* Examples:
*
* request
* .getQueryParam("allow" )
* .assertCsvArray().contains("GET" );
*
*
* @return A new fluent assertion object.
*/
public FluentListAssertion assertCsvArray() {
return new FluentListAssertion<>(asCsvArrayPart().asList().orElse(null), this);
}
/**
* Returns the request that created this part.
*
* @return The request that created this part.
*/
protected RestRequest getRequest() {
return request;
}
/**
* Gets the name of this part.
*
* @return The name of this part, never null .
*/
public String getName() {
return name;
}
@Override /* Object */
public String toString() {
return getName() + "=" + getValue();
}
//
//
}