/* 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.geoserver.wms; import java.awt.Color; import java.awt.geom.Point2D; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.geoserver.ows.util.CaseInsensitiveMap; import org.geotools.image.palette.InverseColorMapOp; import org.geotools.styling.Style; import org.geotools.util.DateRange; import org.geotools.util.NumberRange; import org.opengis.filter.Filter; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.vividsolutions.jts.geom.Envelope; /** * Represents a WMS GetMap request. as a extension to the WMS spec 1.1. * * @author Gabriel Roldan * @author Simone Giannecchini * @version $Id$ */ public class GetMapRequest extends WMSRequest { static final Color DEFAULT_BG = Color.white; public static final String SE_XML = "SE_XML"; /** set of mandatory request's parameters */ private MandatoryParameters mandatoryParams = new MandatoryParameters(); /** set of optionals request's parameters */ private OptionalParameters optionalParams = new OptionalParameters(); /** format options */ private Map<String, Object> formatOptions = new CaseInsensitiveMap(new HashMap()); /** SLD replacement */ private Map /* <String,Object> */env = new HashMap(); /** sql view parameters */ private List<Map<String, String>> viewParams = null; private Map<String, String> httpRequestHeaders; public GetMapRequest() { super("GetMap"); } public Envelope getBbox() { return this.mandatoryParams.bbox; } public java.awt.Color getBgColor() { return this.optionalParams.bgColor; } /** * DJB: spec says SRS is *required*, so if they dont specify one, we should throw an error * instead we use "NONE" - which is no-projection. Previous behavior was to the WSG84 lat/long * (4326) * * @return request CRS, or <code>null</code> if not set. TODO: make CRS manditory as for spec * conformance */ public CoordinateReferenceSystem getCrs() { return this.optionalParams.crs; } public String getSRS() { return this.optionalParams.srs; } public String getExceptions() { return this.optionalParams.exceptions; } public String getFormat() { return this.mandatoryParams.format; } /** * Map of String,Object which contains kvp's which are specific to a particular output format. */ public Map getFormatOptions() { return formatOptions == null ? Collections.EMPTY_MAP : formatOptions; } /** * Map of strings that make up the SLD enviroment for variable substitution * * @return */ public Map getEnv() { return env; } /** * Map of strings that contain the parameter values for SQL views * * @return */ public List<Map<String, String>> getViewParams() { return viewParams; } public int getHeight() { return this.mandatoryParams.height; } /** * @return the non null list of layers, may be empty */ public List<MapLayerInfo> getLayers() { List<MapLayerInfo> layers = mandatoryParams.layers; return layers; } /** * Gets a list of the styles to be returned by the server. * * @return A list of {@link Style} */ public List<Style> getStyles() { return this.mandatoryParams.styles; } /** * Gets the url specified by the "SLD" parameter. */ public URL getSld() { return this.optionalParams.sld; } /** * Gets the string specified the "SLD_BODY" parameter. */ public String getSldBody() { return this.optionalParams.sldBody; } /** * Gets the string specified by the "SLD_VERSION" parameter. */ public String getSldVersion() { return this.optionalParams.sldVersion; } /** * Gets the value of the "VALIDATESCHEMA" parameter which controls wether the value of the "SLD * paramter is schema validated. */ public Boolean getValidateSchema() { return this.optionalParams.validateSLD; } /** * Gets a list of the the filters that will be applied to each layer before rendering * * @return - * @deprecated use {@link #getFilter()}. */ public List getFilters() { return this.optionalParams.filters; } /** * Gets a list of the the filters that will be applied to each layer before rendering * * @return A list of {@link Filter}. * */ public List getFilter() { return this.optionalParams.filters; } /** * Gets a list of the cql filtesr that will be applied to each layer before rendering. * * @return A list of {@link Filter}. * */ public List getCQLFilter() { return this.optionalParams.cqlFilters; } /** * Gets a list of the feature ids that will be used to filter each layer before rendering. * * @return A list of {@link String}. */ public List getFeatureId() { return this.optionalParams.featureIds; } public boolean isTransparent() { return this.optionalParams.transparent; } /** * <a href="http://wiki.osgeo.org/index.php/WMS_Tiling_Client_Recommendation">WMS-C * specification</a> tiling hint * */ public boolean isTiled() { return this.optionalParams.tiled; } public Point2D getTilesOrigin() { return this.optionalParams.tilesOrigin; } public int getBuffer() { return this.optionalParams.buffer; } public InverseColorMapOp getPalette() { return this.optionalParams.paletteInverter; } public int getWidth() { return this.mandatoryParams.width; } /** * @return the KML/KMZ score value for image vs. vector response * @deprecated use <code>getFormatOptions().get( "kmscore" )</code> */ public int getKMScore() { Integer kmscore = (Integer) getFormatOptions().get("kmscore"); if (kmscore != null) { return kmscore.intValue(); } return 40; // old default } /** * @return true: return full attribution for placemark <description> * @deprecated use <code>getFormatOptions().get( "kmattr" )</code> */ public boolean getKMattr() { Boolean kmattr = (Boolean) getFormatOptions().get("kmattr"); if (kmattr != null) { return kmattr.booleanValue(); } return true; // old default } // /** // * @return super overlay flag, <code>true</code> if super overlay requested. // * @deprecated use <code>getFormatOptions().get( "superoverlay" )</code> // */ // public boolean getSuperOverlay() { // Boolean superOverlay = (Boolean) getFormatOptions().get("superoverlay"); // // if (superOverlay != null) { // return superOverlay.booleanValue(); // } // // return false; //old default // } /** * @return kml legend flag, <code>true</code> if legend is enabled. * @deprecated use <code>getFormatOptions().get( "legend" )</code> */ public boolean getLegend() { Boolean legend = (Boolean) getFormatOptions().get("legend"); if (legend != null) { return legend.booleanValue(); } return false; // old default } /** * @return The time request parameter. The list may contain {@link Date} or {@link DateRange} objects */ public List<Object> getTime() { return this.optionalParams.time; } /** * Returns the chosen elevations. The list may contain {@link Date} or {@link NumberRange} objects * @return */ public List<Object> getElevation() { return this.optionalParams.elevation; } /** * Returs the feature version optional parameter * * @return */ public String getFeatureVersion() { return this.optionalParams.featureVersion; } /** * Returns the remote OWS type * * @return */ public String getRemoteOwsType() { return optionalParams.remoteOwsType; } /** * Returs the remote OWS URL * * @return */ public URL getRemoteOwsURL() { return optionalParams.remoteOwsURL; } public void setBbox(Envelope bbox) { this.mandatoryParams.bbox = bbox; } public void setBgColor(java.awt.Color bgColor) { this.optionalParams.bgColor = bgColor; } public void setCrs(CoordinateReferenceSystem crs) { this.optionalParams.crs = crs; } public void setSRS(String srs) { this.optionalParams.srs = srs; } public void setExceptions(String exceptions) { this.optionalParams.exceptions = exceptions; } /** * Sets the GetMap request value for the FORMAT parameter, which is the MIME type for the kind * of image required. */ public void setFormat(String format) { this.mandatoryParams.format = format; } /** * Sets the format options. * * @param formatOptions * A map of String,Object * @see #getFormatOptions() */ public void setFormatOptions(Map formatOptions) { this.formatOptions = formatOptions; } /** * Sets the SLD environment substitution * * @param enviroment */ public void setEnv(Map enviroment) { this.env = enviroment; } /** * Sets the SQL views parameters * * @param viewParams */ public void setViewParams(List<Map<String, String>> viewParams) { this.viewParams = viewParams; } public void setHeight(int height) { this.mandatoryParams.height = height; } public void setHeight(Integer height) { this.mandatoryParams.height = height.intValue(); } public void setLayers(List<MapLayerInfo> layers) { this.mandatoryParams.layers = layers == null ? Collections.EMPTY_LIST : layers; } public void setStyles(List<Style> styles) { this.mandatoryParams.styles = styles == null ? Collections.EMPTY_LIST : new ArrayList<Style>(styles); } /** * Sets the url specified by the "SLD" parameter. */ public void setSld(URL sld) { this.optionalParams.sld = sld; } /** * Sets the string specified by the "SLD_BODY" parameter */ public void setSldBody(String sldBody) { this.optionalParams.sldBody = sldBody; } /** * Sets the string specified by the "SLD_VERSION" parameter */ public void setSldVersion(String sldVersion) { this.optionalParams.sldVersion = sldVersion; } /** * Sets the flag to validate the "SLD" parameter or not. //TODO */ public void setValidateSchema(Boolean validateSLD) { this.optionalParams.validateSLD = validateSLD; } /** * Sets a list of filters, one for each layer * * @param filters * A list of {@link Filter}. * @deprecated use {@link #setFilter(List)}. */ public void setFilters(List filters) { setFilter(filters); } /** * Sets a list of filters, one for each layer * * @param filters * A list of {@link Filter}. */ public void setFilter(List filters) { this.optionalParams.filters = filters; } /** * Sets a list of filters ( cql ), one for each layer. * * @param cqlFilters * A list of {@link Filter}. */ public void setCQLFilter(List cqlFilters) { this.optionalParams.cqlFilters = cqlFilters; } /** * Sets a list of feature ids, one for each layer. * * @param featureIds * A list of {@link String}. */ public void setFeatureId(List featureIds) { this.optionalParams.featureIds = featureIds; } public void setTransparent(boolean transparent) { this.optionalParams.transparent = transparent; } public void setTransparent(Boolean transparent) { this.optionalParams.transparent = (transparent != null) ? transparent.booleanValue() : false; } public void setBuffer(int buffer) { this.optionalParams.buffer = buffer; } public void setPalette(InverseColorMapOp paletteInverter) { this.optionalParams.paletteInverter = paletteInverter; } public void setBuffer(Integer buffer) { this.optionalParams.buffer = (buffer != null) ? buffer.intValue() : 0; } public void setTiled(boolean tiled) { this.optionalParams.tiled = tiled; } public void setTiled(Boolean tiled) { this.optionalParams.tiled = (tiled != null) ? tiled.booleanValue() : false; } public void setTilesOrigin(Point2D origin) { this.optionalParams.tilesOrigin = origin; } public void setWidth(int width) { this.mandatoryParams.width = width; } public void setWidth(Integer width) { this.mandatoryParams.width = width.intValue(); } /** * @param score * the KML/KMZ score value for image vs. vector response, from 0 to 100 * @deprecated use <code>getFormatOptions().put( "kmscore", new Integer( score ) );</code> */ public void setKMScore(int score) { getFormatOptions().put("kmscore", new Integer(score)); } /** * @param on * true: full attribution; false: no attribution * @deprecated use <code>getFormatOptions().put( "kmattr", new Boolean( on ) );</code> */ public void setKMattr(boolean on) { getFormatOptions().put("kmattr", new Boolean(on)); } /** * Sets the super overlay parameter on the request. * * @deprecated use * <code>getFormatOptions().put( "superoverlay", new Boolean( superOverlay ) );</code> */ public void setSuperOverlay(boolean superOverlay) { getFormatOptions().put("superoverlay", new Boolean(superOverlay)); } /** * Sets the kml legend parameter of the request. * * @deprecated use <code>getFormatOptions().put( "legend", new Boolean( legend ) );</code> */ public void setLegend(boolean legend) { getFormatOptions().put("legend", new Boolean(legend)); } /** * Sets the time request parameter (a list of Date or DateRange objects) * */ public void setTime(List<Object> time) { this.optionalParams.time = new ArrayList<Object>(time); } /** * Sets the elevation request parameter. */ public void setElevation(double elevation) { this.optionalParams.elevation = new ArrayList<Object>(); this.optionalParams.elevation.add(elevation); } /** * Sets the elevation set as a request parameter. */ public void setElevation(List<Object> elevation) { this.optionalParams.elevation = new ArrayList<Object>(elevation); } /** * Sets the feature version optional param * * @param featureVersion */ public void setFeatureVersion(String featureVersion) { this.optionalParams.featureVersion = featureVersion; } public void setRemoteOwsType(String remoteOwsType) { this.optionalParams.remoteOwsType = remoteOwsType; } public void setRemoteOwsURL(URL remoteOwsURL) { this.optionalParams.remoteOwsURL = remoteOwsURL; } /** * Sets the maximum number of features to fetch in this request. * <p> * This property only applies if the reqeust is for a vector layer. * </p> */ public void setMaxFeatures(Integer maxFeatures) { this.optionalParams.maxFeatures = maxFeatures; } /** * The maximum number of features to fetch in this request. */ public Integer getMaxFeatures() { return this.optionalParams.maxFeatures; } /** * Sets the offset or start index at which to start returning features in the request. * <p> * It is used in conjunction with {@link #getMaxFeatures()} to page through a feature set. This * property only applies if the request is for a vector layer. * </p> */ public void setStartIndex(Integer startIndex) { this.optionalParams.startIndex = startIndex; } /** * The offset or start index at which to start returning features in the request. */ public Integer getStartIndex() { return this.optionalParams.startIndex; } public double getAngle() { return this.optionalParams.angle; } /** * Sets the map rotation * * @param rotation */ public void setAngle(double rotation) { this.optionalParams.angle = rotation; } private class MandatoryParameters { /** ordered list of requested layers */ List<MapLayerInfo> layers = Collections.emptyList(); /** * ordered list of requested layers' styles, in a one to one relationship with * <code>layers</code> */ List<Style> styles = Collections.emptyList(); Envelope bbox; int width; int height; String format; } private class OptionalParameters { /** * Tells us whether or not we should loop forever in an ani,mated gif * <p> * Defaults to true * */ Boolean animatedGIFLoopContinuosly; /** * Tells us the delay in ms between two frames of an animated gif. * <p> * Default to 1s */ Integer animatedGIFDelay; /** * the map's background color requested, or the default (white) if not specified */ Color bgColor = DEFAULT_BG; /** from SRS (1.1) or CRS (1.2) param */ CoordinateReferenceSystem crs; /** EPSG code for the SRS */ String srs; /** vendor extensions, allows to filter each layer with a user defined filter */ List filters; /** cql filters */ List cqlFilters; /** feature id filters */ List featureIds; String exceptions = SE_XML; boolean transparent = false; /** * Tiling hint, according to the <a * href="http://wiki.osgeo.org/index.php/WMS_Tiling_Client_Recommendation">WMS-C * specification</a> */ boolean tiled; /** * Temporary hack since finding a good tiling origin would require us to compute the bbox on * the fly TODO: remove this once we cache the real bbox of vector layers */ public Point2D tilesOrigin; /** the rendering buffer, in pixels **/ int buffer; /** The paletteInverter used for rendering, if any */ InverseColorMapOp paletteInverter; /** * time parameter, a list since many pattern setup can be possible, see for * example http://mapserver.gis.umn.edu/docs/howto/wms_time_support/#time-patterns. * Can contain {@link Date} or {@link DateRange} objects. */ List<Object> time = Collections.emptyList(); /** elevation parameter, can also be a list, can contain {@link Double} or {@link NumberRange} */ List<Object> elevation = Collections.emptyList(); /** * SLD parameter */ URL sld; /** * SLD_BODY parameter */ String sldBody; /** * SLD_VERSION parameter */ String sldVersion; /** flag to validate SLD parameter */ Boolean validateSLD = Boolean.FALSE; /** feature version (for versioned requests) */ String featureVersion; /** Remote OWS type */ String remoteOwsType; /** Remote OWS url */ URL remoteOwsURL; /** paging parameters */ Integer maxFeatures; Integer startIndex; /** map rotation */ double angle; } /** * Standard override of toString() * * @return a String representation of this request. */ public String toString() { StringBuffer returnString = new StringBuffer("\nGetMap Request"); returnString.append("\n version: " + version); returnString.append("\n output format: " + mandatoryParams.format); returnString.append("\n width height: " + mandatoryParams.width + "," + mandatoryParams.height); returnString.append("\n bbox: " + mandatoryParams.bbox); returnString.append("\n layers: "); for (Iterator<MapLayerInfo> i = mandatoryParams.layers.iterator(); i.hasNext();) { returnString.append(i.next().getName()); if (i.hasNext()) { returnString.append(","); } } returnString.append("\n styles: "); for (Iterator it = mandatoryParams.styles.iterator(); it.hasNext();) { Style s = (Style) it.next(); returnString.append(s.getName()); if (it.hasNext()) { returnString.append(","); } } // returnString.append("\n inside: " + filter.toString()); return returnString.toString(); } public String getHttpRequestHeader(String headerName) { return httpRequestHeaders == null ? null : httpRequestHeaders.get(headerName); } public void putHttpRequestHeader(String headerName, String value) { if (httpRequestHeaders == null) { httpRequestHeaders = new HashMap<String, String>(); } httpRequestHeaders.put(headerName, value); } }