// ***************************************************************************************************************************
// * 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.client;

import static org.apache.juneau.common.internal.IOUtils.*;
import static org.apache.juneau.common.internal.StringUtils.*;
import static org.apache.juneau.common.internal.ThrowableUtils.*;

import java.io.*;
import java.lang.reflect.*;
import java.nio.charset.*;
import java.util.concurrent.*;
import java.util.regex.*;
import java.util.regex.Matcher;

import org.apache.http.*;
import org.apache.http.conn.*;
import org.apache.juneau.*;
import org.apache.juneau.assertions.*;
import org.apache.juneau.collections.*;
import org.apache.juneau.common.internal.*;
import org.apache.juneau.http.entity.*;
import org.apache.juneau.http.resource.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.oapi.*;
import org.apache.juneau.objecttools.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.parser.ParseException;
import org.apache.juneau.reflect.*;
import org.apache.juneau.rest.client.assertion.*;

/**
 * Represents the body of an HTTP response.
 *
 * <p>
 * An extension of an HttpClient {@link HttpEntity} that provides various support for converting the body to POJOs and
 * other convenience methods.
 *
 * <h5 class='section'>See Also:</h5><ul>
 * 	<li class='link'><a class="doclink" href="../../../../../index.html#juneau-rest-client">juneau-rest-client</a>
 * </ul>
 */
public class ResponseContent implements HttpEntity {

	private static final HttpEntity NULL_ENTITY = new HttpEntity() {

		@Override
		public boolean isRepeatable() {
			return false;
		}

		@Override
		public boolean isChunked() {
			return false;
		}

		@Override
		public long getContentLength() {
			return -1;
		}

		@Override
		public Header getContentType() {
			return ResponseHeader.NULL_HEADER;
		}

		@Override
		public Header getContentEncoding() {
			return ResponseHeader.NULL_HEADER;
		}

		@Override
		public InputStream getContent() throws IOException, UnsupportedOperationException {
			return new ByteArrayInputStream(new byte[0]);
		}

		@Override
		public void writeTo(OutputStream outstream) throws IOException {}

		@Override
		public boolean isStreaming() {
			return false;
		}

		@Override
		public void consumeContent() throws IOException {}
	};

	private final RestClient client;
	final RestRequest request;
	final RestResponse response;
	private final HttpEntity entity;
	private HttpPartSchema schema;
	private Parser parser;
	private byte[] body;
	private boolean cached;
	boolean isConsumed;

	/**
	 * Constructor.
	 *
	 * @param client The client used to build this request.
	 * @param request The request object.
	 * @param response The response object.
	 * @param parser The parser to use to consume the body.  Can be <jk>null</jk>.
	 */
	public ResponseContent(RestClient client, RestRequest request, RestResponse response, Parser parser) {
		this.client = client;
		this.request = request;
		this.response = response;
		this.parser = parser;
		this.entity = ObjectUtils.firstNonNull(response.asHttpResponse().getEntity(), NULL_ENTITY);
	}

	//------------------------------------------------------------------------------------------------------------------
	// Setters
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Specifies the parser to use for this body.
	 *
	 * <p>
	 * If not specified, uses the parser defined on the client set via {@link RestClient.Builder#parser(Class)}.
	 *
	 * @param value
	 * 	The new part parser to use for this body.
	 * @return This object.
	 */
	public ResponseContent parser(Parser value) {
		this.parser = value;
		return this;
	}

	/**
	 * Specifies the schema for this body.
	 *
	 * <p>
	 * Used by schema-based parsers such as {@link OpenApiParser}.
	 *
	 * @param value The schema.
	 * @return This object.
	 */
	public ResponseContent schema(HttpPartSchema value) {
		this.schema = value;
		return this;
	}

	/**
	 * Causes the contents of the response body to be stored so that it can be repeatedly read.
	 *
	 * <p>
	 * Calling this method allows methods that read the response body to be called multiple times.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		Multiple calls to this method are ignored.
	 * </ul>
	 *
	 * @return This object.
	 */
	public ResponseContent cache() {
		this.cached = true;
		return this;
	}

	//------------------------------------------------------------------------------------------------------------------
	// Raw streams
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Returns the HTTP response message body as an input stream.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		Once this input stream is exhausted, it will automatically be closed.
	 *  <li class='note'>
	 *		This method can be called multiple times if {@link #cache()} has been called.
	 *  <li class='note'>
	 *		Calling this method multiple times without caching enabled will cause a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} to be thrown.
	 * </ul>
	 *
	 * @return
	 * 	The HTTP response message body input stream, never <jk>null</jk>.
	 * 	<br>For responses without a body(e.g. HTTP 204), returns an empty stream.
	 * @throws IOException If a stream or illegal state exception was thrown.
	 */
	@SuppressWarnings("resource")
	public InputStream asInputStream() throws IOException {
		try {
			if (body != null)
				return new ByteArrayInputStream(body);

			if (cached) {
				body = readBytes(entity.getContent());
				response.close();
				return new ByteArrayInputStream(body);
			}

			if (isConsumed && ! entity.isRepeatable())
				throw new IllegalStateException("Method cannot be called.  Response has already been consumed.  Consider using the RestResponse.cacheBody() method.");

			HttpEntity e = response.asHttpResponse().getEntity();
			InputStream is = e == null ? new ByteArrayInputStream(new byte[0]) : e.getContent();

			is = new EofSensorInputStream(is, new EofSensorWatcher() {
				@Override
				public boolean eofDetected(InputStream wrapped) throws IOException {
					try {
						response.close();
					} catch (RestCallException e) {}
					return true;
				}
				@Override
				public boolean streamClosed(InputStream wrapped) throws IOException {
					try {
						response.close();
					} catch (RestCallException e) {}
					return true;
				}
				@Override
				public boolean streamAbort(InputStream wrapped) throws IOException {
					try {
						response.close();
					} catch (RestCallException e) {}
					return true;
				}
			});

			isConsumed = true;

			return is;
		} catch (UnsupportedOperationException | RestCallException e) {
			throw new IOException(e);
		}
	}

	/**
	 * Returns the HTTP response message body as a reader based on the charset on the <code>Content-Type</code> response header.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed.
	 * 	<li class='note'>
	 * 		Once this input stream is exhausted, it will automatically be closed.
	 *  <li class='note'>
	 *		This method can be called multiple times if {@link #cache()} has been called.
	 *  <li class='note'>
	 *		Calling this method multiple times without caching enabled will cause a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} to be thrown.
	 * </ul>
	 *
	 * @return
	 * 	The HTTP response message body reader, never <jk>null</jk>.
	 * 	<br>For responses without a body(e.g. HTTP 204), returns an empty reader.
	 * @throws IOException If an exception occurred.
	 */
	public Reader asReader() throws IOException {

		// Figure out what the charset of the response is.
		String cs = null;
		String ct = getContentType().orElse(null);

		// First look for "charset=" in Content-Type header of response.
		if (ct != null)
			if (ct.contains("charset="))
				cs = ct.substring(ct.indexOf("charset=")+8).trim();

		return asReader(cs == null ? IOUtils.UTF8 : Charset.forName(cs));
	}

	/**
	 * Returns the HTTP response message body as a reader using the specified charset.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		Once this input stream is exhausted, it will automatically be closed.
	 *  <li class='note'>
	 *		This method can be called multiple times if {@link #cache()} has been called.
	 *  <li class='note'>
	 *		Calling this method multiple times without caching enabled will cause a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} to be thrown.
	 * </ul>
	 *
	 * @param charset
	 * 	The charset to use for the reader.
	 * 	<br>If <jk>null</jk>, <js>"UTF-8"</js> is used.
	 * @return
	 * 	The HTTP response message body reader, never <jk>null</jk>.
	 * 	<br>For responses without a body(e.g. HTTP 204), returns an empty reader.
	 * @throws IOException If an exception occurred.
	 */
	public Reader asReader(Charset charset) throws IOException {
		return new InputStreamReader(asInputStream(), charset == null ? IOUtils.UTF8 : charset);
	}

	/**
	 * Returns the HTTP response message body as a byte array.
	 *
	 * 	The HTTP response message body reader, never <jk>null</jk>.
	 * 	<br>For responses without a body(e.g. HTTP 204), returns an empty array.
	 *
	 * @return The HTTP response body as a byte array.
	 * @throws RestCallException If an exception occurred.
	 */
	public byte[] asBytes() throws RestCallException {
		if (body == null) {
			try {
				if (entity instanceof BasicHttpEntity) {
					body = ((BasicHttpEntity)entity).asBytes();
				} else {
					body = readBytes(entity.getContent());
				}
			} catch (IOException e) {
				throw new RestCallException(response, e, "Could not read response body.");
			} finally {
				response.close();
			}
		}
		return body;
	}


	/**
	 * Pipes the contents of the response to the specified output stream.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 *	<li class='note'>
	 *		The output stream is not automatically closed.
	 * 	<li class='note'>
	 * 		Once the input stream is exhausted, it will automatically be closed.
	 *  <li class='note'>
	 *		This method can be called multiple times if {@link #cache()} has been called.
	 *  <li class='note'>
	 *		Calling this method multiple times without caching enabled will cause a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} to be thrown.
	 * </ul>
	 *
	 * @param os The output stream to pipe the output to.
	 * @return This object.
	 * @throws IOException If an IO exception occurred.
	 */
	public RestResponse pipeTo(OutputStream os) throws IOException {
		pipe(asInputStream(), os);
		return response;
	}

	/**
	 * Pipes the contents of the response to the specified writer.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 *	<li class='note'>
	 *		The writer is not automatically closed.
	 * 	<li class='note'>
	 * 		Once the reader is exhausted, it will automatically be closed.
	 * 	<li class='note'>
	 * 		If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed.
	 *  <li class='note'>
	 *		This method can be called multiple times if {@link #cache()} has been called.
	 *  <li class='note'>
	 *		Calling this method multiple times without caching enabled will cause a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} to be thrown.
	 * </ul>
	 *
	 * @param w The writer to pipe the output to.
	 * @return This object.
	 * @throws IOException If an IO exception occurred.
	 */
	public RestResponse pipeTo(Writer w) throws IOException {
		return pipeTo(w, false);
	}

	/**
	 * Pipes the contents of the response to the specified writer.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 *	<li class='note'>
	 *		The writer is not automatically closed.
	 * 	<li class='note'>
	 * 		Once the reader is exhausted, it will automatically be closed.
	 *  <li class='note'>
	 *		This method can be called multiple times if {@link #cache()} has been called.
	 *  <li class='note'>
	 *		Calling this method multiple times without caching enabled will cause a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} to be thrown.
	 * </ul>
	 *
	 * @param w The writer to pipe the output to.
	 * @param charset
	 * 	The charset to use for the reader.
	 * 	<br>If <jk>null</jk>, <js>"UTF-8"</js> is used.
	 * @return This object.
	 * @throws IOException If an IO exception occurred.
	 */
	public RestResponse pipeTo(Writer w, Charset charset) throws IOException {
		return pipeTo(w, charset, false);
	}

	/**
	 * Pipes the contents of the response to the specified writer.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 *	<li class='note'>
	 *		The writer is not automatically closed.
	 * 	<li class='note'>
	 * 		Once the reader is exhausted, it will automatically be closed.
	 * 	<li class='note'>
	 * 		If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed.
	 *  <li class='note'>
	 *		This method can be called multiple times if {@link #cache()} has been called.
	 *  <li class='note'>
	 *		Calling this method multiple times without caching enabled will cause a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} to be thrown.
	 * </ul>
	 *
	 * @param w The writer to write the output to.
	 * @param byLines Flush the writers after every line of output.
	 * @return This object.
	 * @throws IOException If an IO exception occurred.
	 */
	public RestResponse pipeTo(Writer w, boolean byLines) throws IOException {
		return pipeTo(w, null, byLines);
	}

	/**
	 * Pipes the contents of the response to the specified writer.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 *	<li class='note'>
	 *		The writer is not automatically closed.
	 * 	<li class='note'>
	 * 		Once the reader is exhausted, it will automatically be closed.
	 *  <li class='note'>
	 *		This method can be called multiple times if {@link #cache()} has been called.
	 *  <li class='note'>
	 *		Calling this method multiple times without caching enabled will cause a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} to be thrown.
	 * </ul>
	 *
	 * @param w The writer to pipe the output to.
	 * @param byLines Flush the writers after every line of output.
	 * @param charset
	 * 	The charset to use for the reader.
	 * 	<br>If <jk>null</jk>, <js>"UTF-8"</js> is used.
	 * @return This object.
	 * @throws IOException If an IO exception occurred.
	 */
	public RestResponse pipeTo(Writer w, Charset charset, boolean byLines) throws IOException {
		if (byLines)
			pipeLines(asReader(charset), w);
		else
			pipe(asReader(charset), w);
		return response;
	}

	//------------------------------------------------------------------------------------------------------------------
	// Retrievers
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Parses HTTP body into the specified object type.
	 *
	 * <p>
	 * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps).
	 *
	 * <h5 class='section'>Examples:</h5>
	 * <p class='bjava'>
	 * 	<jc>// Parse into a linked-list of strings.</jc>
	 * 	List&lt;String&gt; <jv>list1</jv> = <jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().as(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a linked-list of beans.</jc>
	 * 	List&lt;MyBean&gt; <jv>list2</jv> = <jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().as(LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a linked-list of linked-lists of strings.</jc>
	 * 	List&lt;List&lt;String&gt;&gt; <jv>list3</jv> = <jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().as(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a map of string keys/values.</jc>
	 * 	Map&lt;String,String&gt; <jv>map1</jv> = <jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().as(TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
	 * 	Map&lt;String,List&lt;MyBean&gt;&gt; <jv>map2</jv> = <jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().as(TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
	 * </p>
	 *
	 * <p>
	 * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type.
	 *
	 * <p>
	 * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value types.
	 *
	 * <p>
	 * The array can be arbitrarily long to indicate arbitrarily complex data structures.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		Use the {@link #as(Class)} method instead if you don't need a parameterized map/collection.
	 * 	<li class='note'>
	 * 		You can also specify any of the following types:
	 * 		<ul class='compact'>
	 * 			<li>{@link ResponseContent}/{@link HttpEntity} - Returns access to this object.
	 * 			<li>{@link Reader} - Returns access to the raw reader of the response.
	 * 			<li>{@link InputStream} - Returns access to the raw input stream of the response.
	 * 			<li>{@link HttpResource} - Response will be converted to an {@link BasicResource}.
	 * 			<li>Any type that takes in an {@link HttpResponse} object.
	 * 		</ul>
	 * 	<li class='note'>
	 *		If {@link #cache()} or {@link RestResponse#cacheContent()} has been called, this method can be can be called multiple times and/or combined with
	 *		other methods that retrieve the content of the response.  Otherwise a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} will be thrown.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after this call.
	 * </ul>
	 *
	 * @param <T> The class type of the object to create.
	 * @param type
	 * 	The object type to create.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * @param args
	 * 	The type arguments of the class if it's a collection or map.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * 	<br>Ignored if the main type is not a map or collection.
	 * @return The parsed object.
	 * @throws RestCallException
	 * 	<ul>
	 * 		<li>If the input contains a syntax error or is malformed, or is not valid for the specified type.
	 * 		<li>If a connection error occurred.
	 * 	</ul>
	 * @see BeanSession#getClassMeta(Class) for argument syntax for maps and collections.
	 */
	public <T> T as(Type type, Type...args) throws RestCallException {
		return as(getClassMeta(type, args));
	}

	/**
	 * Same as {@link #as(Type,Type...)} except optimized for a non-parameterized class.
	 *
	 * <p>
	 * This is the preferred parse method for simple types since you don't need to cast the results.
	 *
	 * <h5 class='section'>Examples:</h5>
	 * <p class='bjava'>
	 * 	<jc>// Parse into a string.</jc>
	 * 	String <jv>string</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().as(String.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a bean.</jc>
	 * 	MyBean <jv>bean</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().as(MyBean.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a bean array.</jc>
	 * 	MyBean[] <jv>beanArray</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().as(MyBean[].<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a linked-list of objects.</jc>
	 * 	List <jv>list</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().as(LinkedList.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a map of object keys/values.</jc>
	 * 	Map <jv>map</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().as(TreeMap.<jk>class</jk>);
	 * </p>
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		You can also specify any of the following types:
	 * 		<ul class='compact'>
	 * 			<li>{@link ResponseContent}/{@link HttpEntity} - Returns access to this object.
	 * 			<li>{@link Reader} - Returns access to the raw reader of the response.
	 * 			<li>{@link InputStream} - Returns access to the raw input stream of the response.
	 * 			<li>{@link HttpResource} - Response will be converted to an {@link BasicResource}.
	 * 			<li>Any type that takes in an {@link HttpResponse} object.
	 * 		</ul>
	 * 	<li class='note'>
	 *		If {@link #cache()} or {@link RestResponse#cacheContent()} has been called, this method can be can be called multiple times and/or combined with
	 *		other methods that retrieve the content of the response.  Otherwise a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} will be thrown.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after this call.
	 * </ul>
	 *
	 * @param <T>
	 * 	The class type of the object being created.
	 * 	See {@link #as(Type,Type...)} for details.
	 * @param type The object type to create.
	 * @return The parsed object.
	 * @throws RestCallException
	 * 	If the input contains a syntax error or is malformed, or is not valid for the specified type, or if a connection
	 * 	error occurred.
	 */
	public <T> T as(Class<T> type) throws RestCallException {
		return as(getClassMeta(type));
	}

	/**
	 * Same as {@link #as(Class)} except allows you to predefine complex data types using the {@link ClassMeta} API.
	 *
	 * <h5 class='section'>Examples:</h5>
	 * <p class='bjava'>
	 * 	BeanContext <jv>beanContext</jv> = BeanContext.<jsf>DEFAULT</jsf>;
	 *
	 * 	<jc>// Parse into a linked-list of strings.</jc>
	 *	ClassMeta&lt;List&lt;String&gt;&gt; <jv>cm1</jv> = <jv>beanContext</jv>.getClassMeta(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
	 * 	List&lt;String&gt; <jv>list1</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().as(<jv>cm1</jv>);
	 *
	 * 	<jc>// Parse into a linked-list of beans.</jc>
	 *	ClassMeta&lt;List&lt;String&gt;&gt; <jv>cm2</jv> = <jv>beanContext</jv>.getClassMeta(LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
	 * 	List&lt;MyBean&gt; <jv>list2</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().as(<jv>cm2</jv>);
	 *
	 * 	<jc>// Parse into a linked-list of linked-lists of strings.</jc>
	 *	ClassMeta&lt;List&lt;String&gt;&gt; <jv>cm3</jv> = <jv>beanContext</jv>.getClassMeta(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
	 * 	List&lt;List&lt;String&gt;&gt; <jv>list3</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().as(<jv>cm3</jv>);
	 *
	 * 	<jc>// Parse into a map of string keys/values.</jc>
	 *	ClassMeta&lt;List&lt;String&gt;&gt; <jv>cm4</jv> = <jv>beanContext</jv>.getClassMeta(TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
	 * 	Map&lt;String,String&gt; <jv>map4</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().as(<jv>cm4</jv>);
	 *
	 * 	<jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
	 *	ClassMeta&lt;List&lt;String&gt;&gt; <jv>cm5</jv> = <jv>beanContext</jv>.getClassMeta(TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
	 * 	Map&lt;String,List&lt;MyBean&gt;&gt; <jv>map5</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().as(<jv>cm5</jv>);
	 * </p>
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 *		If {@link #cache()} or {@link RestResponse#cacheContent()} has been called, this method can be can be called multiple times and/or combined with
	 *		other methods that retrieve the content of the response.  Otherwise a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} will be thrown.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after this call.
	 * </ul>
	 *
	 * @param <T> The class type of the object to create.
	 * @param type The object type to create.
	 * @return The parsed object.
	 * @throws RestCallException
	 * 	<ul>
	 * 		<li>If the input contains a syntax error or is malformed, or is not valid for the specified type.
	 * 		<li>If a connection error occurred.
	 * 	</ul>
	 * @see BeanSession#getClassMeta(Class) for argument syntax for maps and collections.
	 */
	@SuppressWarnings("unchecked")
	public <T> T as(ClassMeta<T> type) throws RestCallException {
		try {
			if (type.is(ResponseContent.class) || type.is(HttpEntity.class))
				return (T)this;

			if (type.is(Reader.class))
				return (T)asReader();

			if (type.is(InputStream.class))
				return (T)asInputStream();

			if (type.is(HttpResponse.class))
				return (T)response;

			if (type.is(HttpResource.class))
				type = (ClassMeta<T>)getClassMeta(BasicResource.class);

			ConstructorInfo ci = type.getInfo().getPublicConstructor(x -> x.hasParamTypes(HttpResponse.class));
			if (ci != null) {
				try {
					return (T)ci.invoke(response);
				} catch (ExecutableException e) {
					throw asRuntimeException(e);
				}
			}

			String ct = firstNonEmpty(response.getHeader("Content-Type").orElse("text/plain"));

			if (parser == null)
				parser = client.getMatchingParser(ct);

			MediaType mt = MediaType.of(ct);

			if (parser == null || (mt.toString().contains("text/plain") && ! parser.canHandle(ct))) {
				if (type.hasStringMutater())
					return type.getStringMutater().mutate(asString());
			}

			if (parser != null) {
				try (Closeable in = parser.isReaderParser() ? asReader() : asInputStream()) {

					T t = parser
						.createSession()
						.properties(JsonMap.create().inner(request.getSessionProperties()))
						.locale(response.getLocale())
						.mediaType(mt)
						.schema(schema)
						.build()
						.parse(in, type);

					// Some HTTP responses have no body, so try to create these beans if they've got no-arg constructors.
					if (t == null && ! type.is(String.class)) {
						ConstructorInfo c = type.getInfo().getPublicConstructor(x -> x.hasNoParams());
						if (c != null) {
							try {
								return c.<T>invoke();
							} catch (ExecutableException e) {
								throw new ParseException(e);
							}
						}
					}

					return t;
				}
			}

			if (type.hasReaderMutater())
				return type.getReaderMutater().mutate(asReader());

			if (type.hasInputStreamMutater())
				return type.getInputStreamMutater().mutate(asInputStream());

			ct = response.getStringHeader("Content-Type").orElse(null);

			if (ct == null && client.hasParsers())
				throw new ParseException("Content-Type not specified in response header.  Cannot find appropriate parser.");

			throw new ParseException("Unsupported media-type in request header ''Content-Type'': ''{0}''", ct);

		} catch (ParseException | IOException e) {
			response.close();
			throw new RestCallException(response, e, "Could not parse response body.");
		}
	}

	/**
	 * Same as {@link #as(Class)} but allows you to run the call asynchronously.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 *		If {@link #cache()} or {@link RestResponse#cacheContent()} has been called, this method can be can be called multiple times and/or combined with
	 *		other methods that retrieve the content of the response.  Otherwise a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} will be thrown.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after the execution of the future.
	 * </ul>
	 *
	 * @param <T> The class type of the object being created.
	 * @param type The object type to create.
	 * @return The future object.
	 * @throws RestCallException If the executor service was not defined.
	 * @see
	 * 	RestClient.Builder#executorService(ExecutorService, boolean) for defining the executor service for creating
	 * 	{@link Future Futures}.
	 */
	public <T> Future<T> asFuture(final Class<T> type) throws RestCallException {
		return client.getExecutorService().submit(
			new Callable<T>() {
				@Override /* Callable */
				public T call() throws Exception {
					return as(type);
				}
			}
		);
	}

	/**
	 * Same as {@link #as(ClassMeta)} but allows you to run the call asynchronously.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 *		If {@link #cache()} or {@link RestResponse#cacheContent()} has been called, this method can be can be called multiple times and/or combined with
	 *		other methods that retrieve the content of the response.  Otherwise a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} will be thrown.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after the execution of the future.
	 * </ul>
	 *
	 * @param <T>
	 * 	The class type of the object being created.
	 * 	See {@link #as(Type, Type...)} for details.
	 * @param type The object type to create.
	 * @return The future object.
	 * @throws RestCallException If the executor service was not defined.
	 * @see
	 * 	RestClient.Builder#executorService(ExecutorService, boolean) for defining the executor service for creating
	 * 	{@link Future Futures}.
	 */
	public <T> Future<T> asFuture(final ClassMeta<T> type) throws RestCallException {
		return client.getExecutorService().submit(
			new Callable<T>() {
				@Override /* Callable */
				public T call() throws Exception {
					return as(type);
				}
			}
		);
	}

	/**
	 * Same as {@link #as(Type,Type...)} but allows you to run the call asynchronously.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 *		If {@link #cache()} or {@link RestResponse#cacheContent()} has been called, this method can be can be called multiple times and/or combined with
	 *		other methods that retrieve the content of the response.  Otherwise a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} will be thrown.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after the execution of the future.
	 * </ul>
	 *
	 * @param <T>
	 * 	The class type of the object being created.
	 * 	See {@link #as(Type, Type...)} for details.
	 * @param type
	 * 	The object type to create.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * @param args
	 * 	The type arguments of the class if it's a collection or map.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * 	<br>Ignored if the main type is not a map or collection.
	 * @return The future object.
	 * @throws RestCallException If the executor service was not defined.
	 * @see
	 * 	RestClient.Builder#executorService(ExecutorService, boolean) for defining the executor service for creating
	 * 	{@link Future Futures}.
	 */
	public <T> Future<T> asFuture(final Type type, final Type...args) throws RestCallException {
		return client.getExecutorService().submit(
			new Callable<T>() {
				@Override /* Callable */
				public T call() throws Exception {
					return as(type, args);
				}
			}
		);
	}

	/**
	 * Returns the contents of this body as a string.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed.
	 *  <li class='note'>
	 *		This method automatically calls {@link #cache()} so that the body can be retrieved multiple times.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after this call.
	 * </ul>
	 *
	 * @return The response as a string.
	 * @throws RestCallException
	 * 	<ul>
	 * 		<li>If the input contains a syntax error or is malformed, or is not valid for the specified type.
	 * 		<li>If a connection error occurred.
	 * 	</ul>
	 */
	public String asString() throws RestCallException {
		cache();
		try (Reader r = asReader()) {
			return read(r);
		} catch (IOException e) {
			response.close();
			throw new RestCallException(response, e, "Could not read response body.");
		}
	}

	/**
	 * Same as {@link #asString()} but allows you to run the call asynchronously.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed.
	 *  <li class='note'>
	 *		This method automatically calls {@link #cache()} so that the body can be retrieved multiple times.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after this call.
	 * </ul>
	 *
	 * @return The future object.
	 * @throws RestCallException If the executor service was not defined.
	 * @see
	 * 	RestClient.Builder#executorService(ExecutorService, boolean) for defining the executor service for creating
	 * 	{@link Future Futures}.
	 */
	public Future<String> asStringFuture() throws RestCallException {
		return client.getExecutorService().submit(
			new Callable<String>() {
				@Override /* Callable */
				public String call() throws Exception {
					return asString();
				}
			}
		);
	}

	/**
	 * Same as {@link #asString()} but truncates the string to the specified length.
	 *
	 * <p>
	 * If truncation occurs, the string will be suffixed with <js>"..."</js>.
	 *
	 * @param length The max length of the returned string.
	 * @return The truncated string.
	 * @throws RestCallException If a problem occurred trying to read from the reader.
	 */
	public String asAbbreviatedString(int length) throws RestCallException {
		return StringUtils.abbreviate(asString(), length);
	}

	/**
	 * Returns the HTTP body content as a simple hexadecimal character string.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode'>
	 * 	0123456789ABCDEF
	 * </p>
	 *
	 * @return The incoming input from the connection as a plain string.
	 * @throws RestCallException If a problem occurred trying to read from the reader.
	 */
	public String asHex() throws RestCallException {
		return toHex(asBytes());
	}

	/**
	 * Returns the HTTP body content as a simple space-delimited hexadecimal character string.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode'>
	 * 	01 23 45 67 89 AB CD EF
	 * </p>
	 *
	 * @return The incoming input from the connection as a plain string.
	 * @throws RestCallException If a problem occurred trying to read from the reader.
	 */
	public String asSpacedHex() throws RestCallException {
		return toSpacedHex(asBytes());
	}

	/**
	 * Parses the output from the body into the specified type and then wraps that in a {@link ObjectRest}.
	 *
	 * <p>
	 * Useful if you want to quickly retrieve a single value from inside of a larger JSON document.
	 *
	 * @param innerType The class type of the POJO being wrapped.
	 * @return The parsed output wrapped in a {@link ObjectRest}.
	 * @throws RestCallException
	 * 	<ul>
	 * 		<li>If the input contains a syntax error or is malformed, or is not valid for the specified type.
	 * 		<li>If a connection error occurred.
	 * 	</ul>
	 */
	public ObjectRest asObjectRest(Class<?> innerType) throws RestCallException {
		return new ObjectRest(as(innerType));
	}

	/**
	 * Converts the output from the connection into an {@link JsonMap} and then wraps that in a {@link ObjectRest}.
	 *
	 * <p>
	 * Useful if you want to quickly retrieve a single value from inside of a larger JSON document.
	 *
	 * @return The parsed output wrapped in a {@link ObjectRest}.
	 * @throws RestCallException
	 * 	<ul>
	 * 		<li>If the input contains a syntax error or is malformed, or is not valid for the specified type.
	 * 		<li>If a connection error occurred.
	 * 	</ul>
	 */
	public ObjectRest asObjectRest() throws RestCallException {
		return asObjectRest(JsonMap.class);
	}

	/**
	 * Converts the contents of the response body to a string and then matches the specified pattern against it.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bjava'>
	 * 	<jc>// Parse response using a regular expression.</jc>
	 * 	Matcher <jv>matcher</jv> = <jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().asMatcher(Pattern.<jsm>compile</jsm>(<js>"foo=(.*)"</js>));
	 *
	 * 	<jk>if</jk> (<jv>matcher</jv>.matches()) {
	 * 		String <jv>foo</jv> = <jv>matcher</jv>.group(1);
	 * 	}
	 * </p>
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed.
	 *  <li class='note'>
	 *		This method automatically calls {@link #cache()} so that the body can be retrieved multiple times.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after this call.
	 * </ul>
	 *
	 * @param pattern The regular expression pattern to match.
	 * @return The matcher.
	 * @throws RestCallException If a connection error occurred.
	 */
	public Matcher asMatcher(Pattern pattern) throws RestCallException {
		return pattern.matcher(asString());
	}

	/**
	 * Converts the contents of the response body to a string and then matches the specified pattern against it.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bjava'>
	 * 	<jc>// Parse response using a regular expression.</jc>
	 * 	Matcher <jv>matcher</jv> = <jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().asMatcher(<js>"foo=(.*)"</js>);
	 *
	 * 	<jk>if</jk> (<jv>matcher</jv>.matches()) {
	 * 		String <jv>foo</jv> = <jv>matcher</jv>.group(1);
	 * 	}
	 * </p>
	 *
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed.
	 *  <li class='note'>
	 *		If {@link #cache()} or {@link RestResponse#cacheContent()} has been called, this method can be can be called multiple times and/or combined with
	 *		other methods that retrieve the content of the response.  Otherwise a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} will be thrown.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after this call.
	 * </ul>
	 *
	 * @param regex The regular expression pattern to match.
	 * @return The matcher.
	 * @throws RestCallException If a connection error occurred.
	 */
	public Matcher asMatcher(String regex) throws RestCallException {
		return asMatcher(regex, 0);
	}

	/**
	 * Converts the contents of the response body to a string and then matches the specified pattern against it.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bjava'>
	 * 	<jc>// Parse response using a regular expression.</jc>
	 * 	Matcher <jv>matcher</jv> = <jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().asMatcher(<js>"foo=(.*)"</js>, <jsf>MULTILINE</jsf> &amp; <jsf>CASE_INSENSITIVE</jsf>);
	 *
	 * 	<jk>if</jk> (<jv>matcher</jv>.matches()) {
	 * 		String <jv>foo</jv> = <jv>matcher</jv>.group(1);
	 * 	}
	 * </p>
	 *
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed.
	 *  <li class='note'>
	 *		If {@link #cache()} or {@link RestResponse#cacheContent()} has been called, this method can be can be called multiple times and/or combined with
	 *		other methods that retrieve the content of the response.  Otherwise a {@link RestCallException}
	 *		with an inner {@link IllegalStateException} will be thrown.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after this call.
	 * </ul>
	 *
	 * @param regex The regular expression pattern to match.
	 * @param flags Pattern match flags.  See {@link Pattern#compile(String, int)}.
	 * @return The matcher.
	 * @throws RestCallException If a connection error occurred.
	 */
	public Matcher asMatcher(String regex, int flags) throws RestCallException {
		return asMatcher(Pattern.compile(regex, flags));
	}

	//------------------------------------------------------------------------------------------------------------------
	// Assertions
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Provides the ability to perform fluent-style assertions on this response body.
	 *
	 * <p>
	 * This method is called directly from the {@link RestResponse#assertContent()} method to instantiate a fluent assertions object.
	 *
	 * <h5 class='section'>Examples:</h5>
	 * <p class='bjava'>
	 * 	<jc>// Validates the response body equals the text "OK".</jc>
	 * 	<jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().assertValue().equals(<js>"OK"</js>);
	 *
	 * 	<jc>// Validates the response body contains the text "OK".</jc>
	 * 	<jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().assertValue().contains(<js>"OK"</js>);
	 *
	 * 	<jc>// Validates the response body passes a predicate test.</jc>
	 * 	<jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().assertValue().is(<jv>x</jv> -&gt; <jv>x</jv>.contains(<js>"OK"</js>));
	 *
	 * 	<jc>// Validates the response body matches a regular expression.</jc>
	 * 	<jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().assertValue().isPattern(<js>".*OK.*"</js>);
	 *
	 * 	<jc>// Validates the response body matches a regular expression using regex flags.</jc>
	 * 	<jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().assertValue().isPattern(<js>".*OK.*"</js>,  <jsf>MULTILINE</jsf> &amp; <jsf>CASE_INSENSITIVE</jsf>);
	 *
	 * 	<jc>// Validates the response body matches a regular expression in the form of an existing Pattern.</jc>
	 * 	Pattern <jv>pattern</jv> = Pattern.<jsm>compile</jsm>(<js>".*OK.*"</js>);
	 * 	<jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().assertValue().isPattern(<jv>pattern</jv>);
	 * </p>
	 *
	 * <p>
	 * The assertion test returns the original response object allowing you to chain multiple requests like so:
	 * <p class='bjava'>
	 * 	<jc>// Validates the response body matches a regular expression.</jc>
	 * 	MyBean <jv>bean</jv> = <jv>client</jv>
	 * 		.get(<jsf>URI</jsf>)
	 * 		.run()
	 * 		.getContent().assertValue().isPattern(<js>".*OK.*"</js>);
	 * 		.getContent().assertValue().isNotPattern(<js>".*ERROR.*"</js>)
	 * 		.getContent().as(MyBean.<jk>class</jk>);
	 * </p>
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>
	 * 		If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed.
	 *  <li class='note'>
	 *		This method automatically calls {@link #cache()} so that the body can be retrieved multiple times.
	 * 	<li class='note'>
	 * 		The input stream is automatically closed after this call.
	 * </ul>
	 *
	 * @return A new fluent assertion object.
	 */
	public FluentResponseBodyAssertion<ResponseContent> assertValue() {
		return new FluentResponseBodyAssertion<>(this, this);
	}

	/**
	 * Shortcut for calling <c>assertValue().asString()</c>.
	 *
	 * @return A new fluent assertion.
	 */
	public FluentStringAssertion<ResponseContent> assertString() {
		return new FluentResponseBodyAssertion<>(this, this).asString();
	}

	/**
	 * Shortcut for calling <c>assertValue().asBytes()</c>.
	 *
	 * @return A new fluent assertion.
	 */
	public FluentByteArrayAssertion<ResponseContent> assertBytes() {
		return new FluentResponseBodyAssertion<>(this, this).asBytes();
	}

	/**
	 * Shortcut for calling <c>assertValue().as(<jv>type</jv>)</c>.
	 *
	 * @param <T> The object type to create.
	 * @param type The object type to create.
	 * @return A new fluent assertion.
	 */
	public <T> FluentAnyAssertion<T,ResponseContent> assertObject(Class<T> type) {
		return new FluentResponseBodyAssertion<>(this, this).as(type);
	}

	/**
	 * Shortcut for calling <c>assertValue().as(<jv>type</jv>, <jv>args</jv>)</c>.
	 *
	 * @param <T> The object type to create.
	 * @param type The object type to create.
	 * @param args Optional type arguments.
	 * @return A new fluent assertion.
	 */
	public <T> FluentAnyAssertion<Object,ResponseContent> assertObject(Type type, Type...args) {
		return new FluentResponseBodyAssertion<>(this, this).as(type, args);
	}

	/**
	 * Returns the response that created this object.
	 *
	 * @return The response that created this object.
	 */
	public RestResponse response() {
		return response;
	}

	//------------------------------------------------------------------------------------------------------------------
	// HttpEntity passthrough methods.
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Tells if the entity is capable of producing its data more than once.
	 *
	 * <p>
	 * A repeatable entity's {@link #getContent()} and {@link #writeTo(OutputStream)} methods can be called more than
	 * once whereas a non-repeatable entity's can not.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 *	<li class='note'>This method always returns <jk>true</jk> if the response body is cached (see {@link #cache()}).
	 * </ul>
	 *
	 * @return <jk>true</jk> if the entity is repeatable, <jk>false</jk> otherwise.
	 */
	@Override /* HttpEntity */
	public boolean isRepeatable() {
		return cached || entity.isRepeatable();
	}

	/**
	 * Tells about chunked encoding for this entity.
	 *
	 * <p>
	 * The primary purpose of this method is to indicate whether chunked encoding should be used when the entity is sent.
	 * <br>For entities that are received, it can also indicate whether the entity was received with chunked encoding.
	 *
	 * <p>
	 * The behavior of wrapping entities is implementation dependent, but should respect the primary purpose.
	 *
	 * @return <jk>true</jk> if chunked encoding is preferred for this entity, or <jk>false</jk> if it is not.
	 */
	@Override /* HttpEntity */
	public boolean isChunked() {
		return entity.isChunked();
	}

	/**
	 * Tells the length of the content, if known.
	 *
	 * @return
	 * 	The number of bytes of the content, or a negative number if unknown.
	 * 	<br>If the content length is known but exceeds {@link Long#MAX_VALUE}, a negative number is returned.
	 */
	@Override /* HttpEntity */
	public long getContentLength() {
		return body != null ? body.length : entity.getContentLength();
	}

	/**
	 * Obtains the <c>Content-Type</c> header, if known.
	 *
	 * <p>
	 * This is the header that should be used when sending the entity, or the one that was received with the entity.
	 * It can include a charset attribute.
	 *
	 * @return The <c>Content-Type</c> header for this entity, or <jk>null</jk> if the content type is unknown.
	 */
	@Override /* HttpEntity */
	public ResponseHeader getContentType() {
		return new ResponseHeader("Content-Type", request, response, entity.getContentType());
	}

	/**
	 * Obtains the Content-Encoding header, if known.
	 *
	 * <p>
	 * This is the header that should be used when sending the entity, or the one that was received with the entity.
	 * <br>Wrapping entities that modify the content encoding should adjust this header accordingly.
	 *
	 * @return The <c>Content-Encoding</c> header for this entity, or <jk>null</jk> if the content encoding is unknown.
	 */
	@Override /* HttpEntity */
	public ResponseHeader getContentEncoding() {
		return new ResponseHeader("Content-Encoding", request, response, entity.getContentEncoding());
	}

	/**
	 * Returns a content stream of the entity.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>This method is equivalent to {@link #asInputStream()} which is the preferred method for fluent-style coding.
	 * 	<li class='note'>This input stream will auto-close once the end of stream has been reached.
	 * 	<li class='note'>It is up to the caller to properly close this stream if not fully consumed.
	 * 	<li class='note'>This method can be called multiple times if the entity is repeatable or the cache flag is set on this object.
	 * 	<li class='note'>Calling this method multiple times on a non-repeatable or cached body will throw a {@link IllegalStateException}.
	 * 		Note that this is different from the HttpClient specs for this method.
	 * </ul>
	 *
	 * @return Content stream of the entity.
	 */
	@Override /* HttpEntity */
	public InputStream getContent() throws IOException, UnsupportedOperationException {
		return asInputStream();
	}

	/**
	 * Writes the entity content out to the output stream.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 * 	<li class='note'>This method is equivalent to {@link #pipeTo(OutputStream)} which is the preferred method for fluent-style coding.
	 * </ul>
	 *
	 * @param outstream The output stream to write entity content to.
	 */
	@Override /* HttpEntity */
	public void writeTo(OutputStream outstream) throws IOException {
		pipeTo(outstream);
	}

	/**
	 * Tells whether this entity depends on an underlying stream.
	 *
	 * <h5 class='section'>Notes:</h5><ul>
	 *	<li class='note'>This method always returns <jk>false</jk> if the response body is cached (see {@link #cache()}.
	 * </ul>
	 *
	 * @return <jk>true</jk> if the entity content is streamed, <jk>false</jk> otherwise.
	 */
	@Override /* HttpEntity */
	public boolean isStreaming() {
		return cached ? false : entity.isStreaming();
	}

	/**
	 * This method is called to indicate that the content of this entity is no longer required.
	 *
	 * <p>
	 * This method is of particular importance for entities being received from a connection.
	 * <br>The entity needs to be consumed completely in order to re-use the connection with keep-alive.
	 *
	 * @throws IOException If an I/O error occurs.
	 * @deprecated Use standard java convention to ensure resource deallocation by calling {@link InputStream#close()} on
	 * the input stream returned by {@link #getContent()}
	 */
	@Override /* HttpEntity */
	@Deprecated
	public void consumeContent() throws IOException {
		entity.consumeContent();
	}

	//------------------------------------------------------------------------------------------------------------------
	// Utility methods
	//------------------------------------------------------------------------------------------------------------------

	private BeanContext getBeanContext() {
		return parser == null ? BeanContext.DEFAULT : parser.getBeanContext();
	}

	private <T> ClassMeta<T> getClassMeta(Class<T> c) {
		return getBeanContext().getClassMeta(c);
	}

	private <T> ClassMeta<T> getClassMeta(Type type, Type...args) {
		return getBeanContext().getClassMeta(type, args);
	}

	@Override
	public String toString() {
		try {
			return asString();
		} catch (RestCallException e) {
			return e.getLocalizedMessage();
		}
	}
}
