DelegatingHttpValues.java

/***************************************************************************
   Copyright 2009 Emily Estes

   Licensed 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 net.metanotion.web.concrete;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.metanotion.util.ChainedIterator;

import net.metanotion.web.HttpValues;

/** An HttpValues implementation that wraps and delegates to other instances and allows an object to transform an HTTP
response. */
public final class DelegatingHttpValues implements HttpValues {
	private static final List<Map.Entry<String,Object>> EMPTY_LIST =
		Collections.unmodifiableList(new ArrayList<Map.Entry<String,Object>>());

	private final List<Map.Entry<String,Object>> headers;
	private final List<Map.Entry<String,Object>> cookies;
	private final Integer sc;
	private final Object result;
	private final HttpValues hv;

	/** Wrap an Http values object(so we can start using it in a wrapper chain most likely).
		@param output The Http response we're wrapping.
	*/
	public DelegatingHttpValues(final HttpValues output) {
		this(EMPTY_LIST, EMPTY_LIST, null, null, output);
	}

	/** Create a new Http Values object that ADDS new headers and/or cookies.
		@param headers The headers to add to the response. Pass an empty list if you don't want to add any headers.
		@param cookies The cookies to add to the response. Pass an empty list if you don't want to add any cookies.
		@param output The HTTP response we're wrapping.
	*/
	public DelegatingHttpValues(final List<Map.Entry<String,Object>> headers,
			final List<Map.Entry<String,Object>> cookies,
			final HttpValues output) {
		this(headers, cookies, null, null, output);
	}

	/** Create a new Http Values object that adds new headers, cookies, and changes the Http status code.
		@param headers The headers to add to the response. Pass an empty list if you don't want to add any headers.
		@param cookies The cookies to add to the response. Pass an empty list if you don't want to add any cookies.
		@param status The HTTP status code to return instead of the <code>output.getHttpStatus()</code> value.
		@param output The HTTP response we're wrapping.
	*/
	public DelegatingHttpValues(final List<Map.Entry<String,Object>> headers,
			final List<Map.Entry<String,Object>> cookies,
			final int status,
			final HttpValues output) {
		this(headers, cookies, status, null, output);
	}

	/** Create a new Http Values object that adds new headers, cookies, changes the Http status code, and/or replaces
		the content of the response.
		@param headers The headers to add to the response. Pass an empty list if you don't want to add any headers.
		@param cookies The cookies to add to the response. Pass an empty list if you don't want to add any cookies.
		@param status The HTTP status code to return instead of the <code>output.getHttpStatus()</code> value.
		@param result The new HTTP content to return instead of the <code>output.getResult()</code> value.
		@param output The HTTP response we're wrapping.
	*/
	public DelegatingHttpValues(final List<Map.Entry<String,Object>> headers,
			final List<Map.Entry<String,Object>> cookies,
			final Integer status,
			final Object result,
			final HttpValues output) {
		this.headers = headers;
		this.cookies = cookies;
		this.sc = status;
		this.result = result;
		this.hv = output;
	}

	// HttpValues
	@Override public Iterator<Map.Entry<String,Object>> listHeaders() {
		return new ChainedIterator<Map.Entry<String,Object>>(Arrays.asList(hv.listHeaders(), headers.iterator()));
	}

	@Override public Iterator<Map.Entry<String,Object>> listCookies() {
		return new ChainedIterator<Map.Entry<String,Object>>(Arrays.asList(hv.listCookies(), cookies.iterator()));
	}

	@Override public int getHttpStatus() { return ((sc == null) ? hv.getHttpStatus() : sc); }

	@Override public Object unwrap() { return ((result == null) ? hv.unwrap() : result); }

	@Override public HttpValues rewrap(final Object o, final HttpValues httpValues) {
		return (HttpValues) new DelegatingHttpValues(EMPTY_LIST, EMPTY_LIST, hv.getHttpStatus(), o, httpValues);
	}
}