/* Copyright (c) 2001, 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.vfny.geoserver.wms.responses;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
import org.geotools.map.MapLayer;
import org.geotools.renderer.GTRenderer;
import org.vfny.geoserver.wms.GetMapProducer;
import org.vfny.geoserver.wms.WMSMapContext;
/**
*
* @author Simone Giannecchini, GeoSolutions
*
*/
public abstract class AbstractGetMapProducer implements GetMapProducer {
/**
* Holds the map context passed to produceMap, so subclasses can use it if
* they need it from inside {@linkPlain #formatImageOutputStream(String,
* BufferedImage, OutputStream)}
*/
protected WMSMapContext mapContext;
/**
* set to <code>true</code> on <code>abort()</code> so
* <code>produceMap</code> leaves the image being worked on to the garbage
* collector.
*/
protected boolean abortRequested;
/**
* The one to do the magic of rendering a map
*/
protected GTRenderer renderer;
/**
* Set in produceMap(...) from the requested output format, it's holded just
* to be sure that method has been called before getContentType() thus
* supporting the workflow contract of the request processing
*/
protected String requestedOutputFormat;
private final String mime;
/**
* The list of GetCapabilities stated format names for this map producer.
*/
private final Set<String> outputFormatNames;
protected AbstractGetMapProducer(final String mime, final String outputFormat) {
this(mime, new String[] { outputFormat });
}
protected AbstractGetMapProducer(final String mime, final String[] outputFormats) {
this(mime,outputFormats != null ? Arrays.asList(outputFormats) : null);
}
protected AbstractGetMapProducer(final String mime, Collection<String> outputFormats ) {
this.mime = mime;
if( outputFormats == null ) {
outputFormats = Collections.emptySet();
}
// Using a set that performs case insensitive look ups directly.
Set<String> names = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
names.addAll(outputFormats);
outputFormatNames = Collections.unmodifiableSet(names);
}
protected AbstractGetMapProducer() {
this(null, (String[]) null);
}
/**
* @see GetMapProducer#setMapContext(WMSMapContext)
*/
public void setMapContext(WMSMapContext mapContext) {
this.mapContext = mapContext;
}
/**
* @see GetMapProducer#getMapContext()
*/
public WMSMapContext getMapContext() {
return this.mapContext;
}
/**
* Halts the loading. Right now just calls renderer.stopRendering.
*/
public void abort() {
this.abortRequested = true;
if (this.renderer != null) {
this.renderer.stopRendering();
}
}
/**
* returns the content encoding for the output data (null for this class)
*
* @return <code>null</code> since no special encoding is performed while
* writting to the output stream. Do not confuse this with
* getMimeType().
*/
public String getContentEncoding() {
return null;
}
/**
* @see GetMapProducer#getContentType()
*/
public String getContentType() {
return mime;
}
/**
* @see GetMapProducer#getOutputFormat()
*/
public String getOutputFormat() {
return requestedOutputFormat == null ? getContentType() : requestedOutputFormat;
}
/**
* @see GetMapProducer#setOutputFormat(String)
*/
public void setOutputFormat(final String outputFormat) {
// this lookup is made in a case insensitive manner, see
// outputFormatNames definition
if (outputFormatNames.contains(outputFormat)) {
this.requestedOutputFormat = outputFormat;
}else{
throw new IllegalArgumentException(outputFormat + " is not a recognized output "
+ "format for " + getClass().getSimpleName());
}
}
/**
* @see GetMapProducer#getContentDisposition()
* @return {@code null}, subclasses should override as needed
*/
public String getContentDisposition() {
return null;
}
/**
* Utility method to build a standard content disposition header.
* It will concatenate the titles of the various layers in the map context,
* or generate "geoserver" instead (in the event no layer title is set).
* The file name will be followed by the extension provided, for example,
* to generate layer.pdf extension will be ".pdf"
* @param extension
* @return
*/
protected String getContentDisposition(String extension) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < mapContext.getLayerCount(); i++) {
MapLayer layer = mapContext.getLayer(i);
String title = layer.getTitle();
if (title != null && !title.equals("")) {
sb.append(title).append("_");
}
}
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
return "attachment; filename=" + sb.toString() + extension;
}
return "attachment; filename=geoserver" + extension;
}
/**
* @see GetMapProducer#getOutputFormatNames()
*/
@SuppressWarnings("unchecked")
public Set<String> getOutputFormatNames() {
return outputFormatNames;
}
}