/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package de.cismet.cismap.commons.raster.wms;
import edu.umd.cs.piccolo.PNode;
import org.apache.log4j.Logger;
import org.jdom.Attribute;
import org.jdom.DataConversionException;
import org.jdom.Element;
import org.openide.util.NbBundle;
import java.awt.EventQueue;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.swing.tree.TreePath;
import de.cismet.cismap.commons.ChildrenProvider;
import de.cismet.cismap.commons.LayerInfoProvider;
import de.cismet.cismap.commons.RetrievalServiceLayer;
import de.cismet.cismap.commons.interaction.CismapBroker;
import de.cismet.cismap.commons.interaction.events.ActiveLayerEvent;
import de.cismet.cismap.commons.interaction.events.StatusEvent;
import de.cismet.cismap.commons.preferences.CapabilityLink;
import de.cismet.cismap.commons.rasterservice.ImageRetrieval;
import de.cismet.cismap.commons.rasterservice.RasterMapService;
import de.cismet.cismap.commons.retrieval.RetrievalEvent;
import de.cismet.cismap.commons.wms.capabilities.Layer;
import de.cismet.cismap.commons.wms.capabilities.Operation;
import de.cismet.cismap.commons.wms.capabilities.Style;
import de.cismet.cismap.commons.wms.capabilities.WMSCapabilities;
import de.cismet.cismap.commons.wms.capabilities.WMSCapabilitiesFactory;
import de.cismet.tools.PropertyEqualsProvider;
/**
* DOCUMENT ME!
*
* @author thorsten.hell@cismet.de
* @version $Revision$, $Date$
*/
public final class WMSServiceLayer extends AbstractWMSServiceLayer implements RetrievalServiceLayer,
RasterMapService,
PropertyEqualsProvider,
LayerInfoProvider,
ChildrenProvider {
//~ Static fields/initializers ---------------------------------------------
private static final transient Logger LOG = Logger.getLogger(WMSServiceLayer.class);
private static final String TEMPLATETOKEN_WIDTH = "<cismap:width>"; // NOI18N
private static final String TEMPLATETOKEN_HEIGHT = "<cismap:height>"; // NOI18N
private static final String TEMPLATETOKEN_BOUNDINGBOX_LL_X = "<cismap:boundingBox_ll_x>"; // NOI18N
private static final String TEMPLATETOKEN_BOUNDINGBOX_LL_Y = "<cismap:boundingBox_ll_y>"; // NOI18N
private static final String TEMPLATETOKEN_BOUNDINGBOX_UR_X = "<cismap:boundingBox_ur_x>"; // NOI18N
private static final String TEMPLATETOKEN_BOUNDINGBOX_UR_Y = "<cismap:boundingBox_ur_y>"; // NOI18N
private static final String TEMPLATETOKEN_SRS = "<cismap:srs>"; // NOI18N
private static final String TEMPLATETOKEN_CUSTOMSTYLE = "<cismap:customStyle>"; // NOI18N
public static final String TEMPLATETOKEN_CUSTOMSTYLE_LAYERNAME = "<cismap:layerName>"; // NOI18N
public static final String TEMPLATETOKEN_CUSTOMSTYLE_TITLE = "<cismap:title>"; // NOI18N
private static final String EPSG_NAMESPACE = "http://www.opengis.net/gml/srs/epsg.xml"; // NOI18N
private static final String TEMPLATE_GETMAP_PAYLOAD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<GetMap xmlns:ows=\"http://www.opengis.net/ows\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"1.1.1\" service=\"WMS\">"
+ TEMPLATETOKEN_CUSTOMSTYLE
+ "<BoundingBox srsName=\"" + EPSG_NAMESPACE + "#" + TEMPLATETOKEN_SRS + "\">"
+ "<gml:coord>"
+ "<gml:X>" + TEMPLATETOKEN_BOUNDINGBOX_LL_X + "</gml:X>"
+ "<gml:Y>" + TEMPLATETOKEN_BOUNDINGBOX_LL_Y + "</gml:Y>"
+ "</gml:coord>"
+ "<gml:coord>"
+ "<gml:X>" + TEMPLATETOKEN_BOUNDINGBOX_UR_X + "</gml:X>"
+ "<gml:Y>" + TEMPLATETOKEN_BOUNDINGBOX_UR_Y + "</gml:Y>"
+ "</gml:coord>"
+ "</BoundingBox>"
+ "<Output>"
+ "<Format>image/png</Format>"
+ "<Size>"
+ "<Width>" + TEMPLATETOKEN_WIDTH + "</Width>"
+ "<Height>" + TEMPLATETOKEN_HEIGHT + "</Height>"
+ "</Size>"
+ "<Transparent>true</Transparent>"
+ "</Output>"
+ "<Exceptions>application/vnd.ogc.se+xml</Exceptions>"
+ "</GetMap>";
//~ Instance fields --------------------------------------------------------
List wmsLayers = new ArrayList();
List ogcLayers = new ArrayList();
Object retrievalBlocker = new Object();
private PNode imageObject = new PNode();
private String imageFormat = null;
private String backgroundColor = null;
private String exceptionsFormat = null;
private boolean transparentImage = true;
private String srs;
private String title;
private WMSCapabilities wmsCapabilities;
private String capabilitiesUrl;
private String customSLD;
// Used by clone()
private List treePaths;
private Element wmsServiceLayerElement;
private HashMap<String, WMSCapabilities> capabilities;
private List<WMSLayer> dummyLayer = new ArrayList<WMSLayer>();
private boolean reverseAxisOrder = false;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new WMSServiceLayer object.
*/
public WMSServiceLayer() {
}
/**
* Creates a new WMSServiceLayer object.
*
* @param treePaths DOCUMENT ME!
*/
public WMSServiceLayer(final List treePaths) {
this(treePaths, true, false);
}
/**
* Creates a new WMSServiceLayer object.
*
* @param l The layer from which to create a WMSServiceLayer.
*/
public WMSServiceLayer(final Layer l) {
setTitle(l.getTitle());
setName(l.getName());
addLayer(l);
}
/**
* Creates a new WMSServiceLayer object.
*
* @param wmsServiceLayerElement DOCUMENT ME!
* @param capabilities DOCUMENT ME!
*/
public WMSServiceLayer(final Element wmsServiceLayerElement, final HashMap<String, WMSCapabilities> capabilities) {
this.wmsServiceLayerElement = wmsServiceLayerElement;
this.capabilities = capabilities;
// a dummy object without a capabilities document will be created
init(wmsServiceLayerElement, capabilities, false);
}
/**
* Creates a new WMSServiceLayer object.
*
* @param treePaths DOCUMENT ME!
* @param reverseLayerOrder DOCUMENT ME!
* @param reverseSubLayerOrder DOCUMENT ME!
*/
public WMSServiceLayer(final List treePaths, final boolean reverseLayerOrder, final boolean reverseSubLayerOrder) {
this.treePaths = treePaths;
if (treePaths != null) {
if (treePaths.size() > 1) {
setName("Layerzusammenstellung"); // NOI18N
}
int i = (reverseLayerOrder ? (treePaths.size() - 1) : 0);
while ((reverseLayerOrder ? (i >= 0) : (i < treePaths.size()))) {
final Object next = treePaths.get(i);
if (next instanceof TreePath) {
final TreePath nextTreePath = (TreePath)next;
if (nextTreePath.getLastPathComponent() instanceof Layer) {
final Layer nextLayer = (Layer)nextTreePath.getLastPathComponent();
addLayer(nextLayer, null, true, false, true, reverseSubLayerOrder);
if (getName() == null) {
setName(nextLayer.getTitle());
}
} else if (nextTreePath.getLastPathComponent() instanceof Style) {
final Style nextStyle = (Style)nextTreePath.getLastPathComponent();
if (nextTreePath.getPathComponent(nextTreePath.getPathCount() - 2) instanceof Layer) {
final Layer nextLayer = ((Layer)nextTreePath.getPathComponent(
nextTreePath.getPathCount()
- 2));
addLayer(nextLayer, nextStyle);
if (getName() == null) {
setName(nextLayer.getTitle());
}
}
}
}
if (reverseLayerOrder) {
--i;
} else {
++i;
}
}
}
}
//~ Methods ----------------------------------------------------------------
/**
* Sets the tile of this layer. TODO: Move to upper class
*
* @param title The title.
*/
public void setTitle(final String title) {
this.title = title;
}
/**
* Returns the title of this layer.
*
* @return The title.
*/
public String getTitle() {
return title;
}
/**
* DOCUMENT ME!
*
* @param wmsServiceLayerElement DOCUMENT ME!
* @param capabilities DOCUMENT ME!
* @param loadCapDoc refCaps DOCUMENT ME!
*/
private void init(final Element wmsServiceLayerElement,
final HashMap<String, WMSCapabilities> capabilities,
final boolean loadCapDoc) {
setName(wmsServiceLayerElement.getAttribute("name").getValue()); // NOI18N
final Attribute attributeTitle = wmsServiceLayerElement.getAttribute("title"); // NOI18N
if (attributeTitle != null) {
setTitle(attributeTitle.getValue());
}
final Attribute attributeReverseAxisOrder = wmsServiceLayerElement.getAttribute("reverseAxisOrder"); // NOI18N
if (attributeReverseAxisOrder != null) {
try {
this.reverseAxisOrder = attributeReverseAxisOrder.getBooleanValue();
} catch (DataConversionException e) {
LOG.error("Cannot parse the reverse axis order", e);
}
}
try {
setVisible(wmsServiceLayerElement.getAttribute("visible").getBooleanValue()); // NOI18N
} catch (DataConversionException ex) {
}
try {
setTranslucency(wmsServiceLayerElement.getAttribute("translucency").getFloatValue()); // NOI18N
} catch (DataConversionException ex) {
}
try {
final Float minOpacity = CismapBroker.getInstance().getMinOpacityToStayEnabled();
if ((minOpacity != null) && ((getTranslucency() <= minOpacity) || !isVisible())) {
this.setEnabled(false); // NOI18N
} else {
setEnabled(wmsServiceLayerElement.getAttribute("enabled").getBooleanValue()); // NOI18N
}
} catch (DataConversionException ex) {
}
setBackgroundColor(wmsServiceLayerElement.getAttribute("bgColor").getValue()); // NOI18N
setImageFormat(wmsServiceLayerElement.getAttribute("imageFormat").getValue()); // NOI18N
setExceptionsFormat(wmsServiceLayerElement.getAttribute("exceptionFormat").getValue()); // NOI18N
final CapabilityLink cp = new CapabilityLink(wmsServiceLayerElement);
WMSCapabilities wmsCaps = capabilities.get(cp.getLink());
if (loadCapDoc && (wmsCaps == null)) {
try {
wmsCaps = createCapabilitiesDocument();
capabilities.put(cp.getLink(), wmsCaps);
} catch (final Exception e) {
errorObject = e.getMessage();
LOG.error("Error while initialising a WMSServiceLayer object.", e);
}
}
setWmsCapabilities(wmsCaps);
setCapabilitiesUrl(cp.getLink());
// Grundeinstellungen sind gemacht, Jetzt fehlen noch die Layer
final List layerList = wmsServiceLayerElement.getChildren("wmsLayer"); // NOI18N
final Iterator<Element> it = layerList.iterator();
wmsLayers.clear();
ogcLayers.clear();
dummyLayer.clear();
while (it.hasNext()) {
final Element elem = it.next();
final String lName = elem.getAttribute("name").getValue(); // NOI18N
String styleName = null;
boolean isEnabled = true;
boolean info = false;
try {
isEnabled = elem.getAttribute("enabled").getBooleanValue(); // NOI18N
} catch (Exception ex) {
}
try {
info = elem.getAttribute("info").getBooleanValue(); // NOI18N
} catch (Exception ex) {
}
try {
styleName = elem.getAttribute("style").getValue(); // NOI18N
} catch (Exception ex) {
}
if (wmsCaps != null) {
final Layer l = searchForLayer(getWmsCapabilities().getLayer(), lName);
if (l != null) {
if (layerList.size() == 1) {
setName(l.getTitle());
}
Style style = null;
if (styleName != null) {
style = l.getStyleResource(styleName);
}
this.addLayer(l, style, isEnabled, info, false);
}
} else {
this.addLayer(lName, styleName, true, info);
}
}
setEnabled(isEnabled());
}
/**
* DOCUMENT ME!
*
* @param nextLayer DOCUMENT ME!
* @param selectedStyle DOCUMENT ME!
* @param enabled DOCUMENT ME!
* @param info DOCUMENT ME!
*/
protected void addLayer(final Layer nextLayer,
final Style selectedStyle,
final boolean enabled,
final boolean info) {
addLayer(nextLayer, selectedStyle, enabled, info, true);
}
/**
* DOCUMENT ME!
*
* @param nextLayer DOCUMENT ME!
* @param selectedStyle DOCUMENT ME!
* @param enabled DOCUMENT ME!
* @param info DOCUMENT ME!
* @param addSubLayer DOCUMENT ME!
*/
protected void addLayer(final Layer nextLayer,
final Style selectedStyle,
final boolean enabled,
final boolean info,
final boolean addSubLayer) {
addLayer(nextLayer, selectedStyle, enabled, info, addSubLayer, false);
}
/**
* DOCUMENT ME!
*
* @param nextLayer DOCUMENT ME!
* @param selectedStyle DOCUMENT ME!
* @param enabled DOCUMENT ME!
* @param info DOCUMENT ME!
* @param addSubLayer DOCUMENT ME!
* @param reverseSubLayerOrder DOCUMENT ME!
*/
protected void addLayer(final Layer nextLayer,
Style selectedStyle,
final boolean enabled,
final boolean info,
final boolean addSubLayer,
final boolean reverseSubLayerOrder) {
if ((nextLayer.getName() != null) && !nextLayer.getName().equals("")) // NOI18N
{
if (selectedStyle == null) {
if ((nextLayer.getStyles() != null) && (nextLayer.getStyles().length > 0)
&& (nextLayer.getStyles()[0] != null)) {
selectedStyle = nextLayer.getStyles()[0];
}
}
final WMSLayer wmsLayer = new WMSLayer(nextLayer, selectedStyle);
wmsLayer.setEnabled(enabled);
wmsLayer.setParentServiceLayer(this);
wmsLayer.setQuerySelected(info);
if (ogcLayers.indexOf(wmsLayer.getOgcCapabilitiesLayer()) < 0) {
wmsLayers.add(wmsLayer);
ogcLayers.add(wmsLayer.getOgcCapabilitiesLayer());
}
EventQueue.invokeLater(new Thread("fireLayerInformationStatusChanged") {
@Override
public void run() {
final ActiveLayerEvent ale = new ActiveLayerEvent();
ale.setLayer(wmsLayer);
CismapBroker.getInstance().fireLayerInformationStatusChanged(ale);
}
});
}
if (addSubLayer) {
if (reverseSubLayerOrder) {
for (int i = nextLayer.getChildren().length - 1; i >= 0; --i) {
final Layer childLayer = nextLayer.getChildren()[i];
addLayer(childLayer, null, true, false, true, true);
}
} else {
for (int i = 0; i < nextLayer.getChildren().length; ++i) {
final Layer childLayer = nextLayer.getChildren()[i];
addLayer(childLayer);
}
}
}
}
/**
* DOCUMENT ME!
*
* @param name nextLayer DOCUMENT ME!
* @param styleName DOCUMENT ME!
* @param enabled DOCUMENT ME!
* @param info DOCUMENT ME!
*/
protected void addLayer(final String name, final String styleName, final boolean enabled, final boolean info) {
final WMSLayer wmsLayer = new WMSLayer(name, styleName, enabled, info);
wmsLayer.setEnabled(enabled);
wmsLayer.setParentServiceLayer(this);
wmsLayer.setQuerySelected(false);
dummyLayer.add(wmsLayer);
}
/**
* DOCUMENT ME!
*
* @param nextLayer DOCUMENT ME!
* @param selectedStyle DOCUMENT ME!
*/
protected void addLayer(final Layer nextLayer, final Style selectedStyle) {
addLayer(nextLayer, selectedStyle, true, false);
}
/**
* DOCUMENT ME!
*
* @param nextLayer DOCUMENT ME!
*/
protected void addLayer(final Layer nextLayer) {
addLayer(nextLayer, null);
}
/**
* DOCUMENT ME!
*
* @param layer DOCUMENT ME!
*/
public void removeLayer(final WMSLayer layer) {
wmsLayers.remove(layer);
ogcLayers.remove(layer.getOgcCapabilitiesLayer());
disableWhenChildrenDisabled();
}
@Override
public void setEnabled(final boolean enabled) {
super.setEnabled(enabled);
// if enabled is true and no sublayer is enabled, then enable all sublayer
if (enabled) {
boolean enableAll = true;
Iterator it = getWMSLayers().iterator();
while (it.hasNext()) {
final Object o = it.next();
if (o instanceof WMSLayer) {
if (((WMSLayer)o).isEnabled()) {
enableAll = false;
break;
}
}
}
if (enableAll) {
it = getWMSLayers().iterator();
while (it.hasNext()) {
final Object o = it.next();
if (o instanceof WMSLayer) {
((WMSLayer)o).setEnabled(enabled);
}
}
}
}
}
/**
* disables the layer, if all child layers are disabled.
*/
public void disableWhenChildrenDisabled() {
boolean childrenDisabled = true;
final Iterator it = getWMSLayers().iterator();
while (it.hasNext()) {
final Object o = it.next();
if (o instanceof WMSLayer) {
if (((WMSLayer)o).isEnabled()) {
childrenDisabled = false;
break;
}
}
}
if (childrenDisabled) {
setEnabled(false);
}
}
@Override
public String toString() {
if (name != null) {
return name;
} else {
return "..."; // NOI18N
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public List getWMSLayers() {
if (isDummy()) {
return dummyLayer;
} else {
return wmsLayers;
}
}
@Override
public void retrieve(final boolean forced) {
if (isDummy()) {
init(wmsServiceLayerElement, capabilities, true);
if (!isDummy()) {
setEnabled(true);
dummyLayer.clear();
final StatusEvent se = new StatusEvent(StatusEvent.AWAKED_FROM_DUMMY, this);
CismapBroker.getInstance().fireStatusValueChanged(se);
} else {
retrievalError(new RetrievalEvent());
return;
}
}
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("retrieve()", new Exception()); // NOI18N
}
}
setRefreshNeeded(false);
final String getMapUrl = getGetMapUrl(customSLD != null);
if (getMapUrl == null) {
final RetrievalEvent e = new RetrievalEvent();
e.setInitialisationEvent(true);
e.setPercentageDone(0);
e.setHasErrors(true);
e.setRetrievedObject(NbBundle.getMessage(WMSServiceLayer.class, "WMSServiceLayer.retrieve.urlNotFound"));
fireRetrievalError(e);
return;
}
final String getMapPayload = getGetMapPayload();
if ((ir != null) && ir.isAlive() && ir.getUrl().equals(getMapUrl) && !forced) {
if (LOG.isDebugEnabled()) {
LOG.debug("Multiple invocations with the same url. Skipping this invocation."); // NOI18N
}
} else if ((width < 1) || (height < 1)) {
if (LOG.isDebugEnabled()) {
// NoOp. Otherwise the wms will response with an exception.
LOG.debug("Width or height is less than 1. Skipping retrieval.");
}
} else {
if ((ir != null) && ir.isAlive()) {
ir.youngerWMSCall();
ir.interrupt();
retrievalAborted(new RetrievalEvent());
}
ir = new ImageRetrieval(this);
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("getGetMapURL(): " + getMapUrl); // NOI18N
}
}
ir.setUrl(getMapUrl);
if (getMapPayload != null) {
ir.setPayload(getMapPayload);
}
// new
ir.setWMSCapabilities(getWmsCapabilities());
if (DEBUG) {
if (LOG.isDebugEnabled()) {
LOG.debug("ir.start();"); // NOI18N
}
}
ir.setPriority(Thread.NORM_PRIORITY);
ir.start();
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
private WMSCapabilities createCapabilitiesDocument() throws Exception {
final WMSCapabilitiesFactory factory = new WMSCapabilitiesFactory();
final CapabilityLink link = new CapabilityLink(wmsServiceLayerElement);
return factory.createCapabilities(link.getLink());
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public String getImageFormat() {
return imageFormat;
}
/**
* DOCUMENT ME!
*
* @param imageFormat DOCUMENT ME!
*/
public void setImageFormat(final String imageFormat) {
this.imageFormat = imageFormat;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public String getBackgroundColor() {
if (backgroundColor != null) {
return backgroundColor;
} else {
LOG.warn("backgroundcolor was null. Set it to 0xF0F0F0"); // NOI18N
backgroundColor = "0xF0F0F0"; // NOI18N
return backgroundColor;
}
}
/**
* DOCUMENT ME!
*
* @param backgroundColor DOCUMENT ME!
*/
public void setBackgroundColor(final String backgroundColor) {
this.backgroundColor = backgroundColor;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public String getExceptionsFormat() {
return exceptionsFormat;
}
/**
* DOCUMENT ME!
*
* @param exceptionsFormat DOCUMENT ME!
*/
public void setExceptionsFormat(final String exceptionsFormat) {
final List<String> exceptions = ((wmsCapabilities != null) ? wmsCapabilities.getExceptions() : null);
if ((exceptionsFormat != null) && (exceptions != null) && (exceptions.size() > 0)
&& !exceptions.contains(exceptionsFormat)) {
// the preferred exception format is not supported. Use an other one
String format = null;
for (final String tmp : exceptions) {
if (tmp.toLowerCase().indexOf(exceptionsFormat.toLowerCase()) != -1) {
format = tmp;
// The right format is found
break;
} else if (tmp.toLowerCase().indexOf("xml") != -1) {
format = tmp;
}
}
if (format == null) {
format = exceptions.get(0);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Preferred exception format is not supported. Use format: " + format);
}
this.exceptionsFormat = format;
} else {
this.exceptionsFormat = exceptionsFormat;
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public String getSrs() {
return srs;
}
/**
* DOCUMENT ME!
*
* @param srs DOCUMENT ME!
*/
public void setSrs(final String srs) {
this.srs = srs;
}
/**
* Generates the URL for the GetMap request.
*
* @param minimalUrl Specifies if the generated url shall only contain the necessary parameters.
*
* @return The GetMap request url.
*/
private String getGetMapUrl(final boolean minimalUrl) {
final String mapPrefix = getGetMapPrefix();
if (mapPrefix == null) {
return null;
}
final StringBuilder url = new StringBuilder(mapPrefix);
if ((bb == null) || (url == null) || (url.length() == 0)) {
return null;
}
if (url.indexOf("?") < 0) {
url.append("?"); // NOI18N
}
final String version = getWmsCapabilities().getVersion();
if (version.trim().equals("1.0.0") || version.trim().equals("1.0") || version.trim().equals("1")) {
url.append("&WMTVER=1.0.0&REQUEST=map"); // NOI18N
} else {
url.append("&VERSION=").append(version);
url.append("&REQUEST=GetMap"); // NOI18N
}
url.append("&BBOX=").append(bb.getURLString()); // NOI18N
url.append("&WIDTH=").append(width); // NOI18N
url.append("&HEIGHT=").append(height); // NOI18N
if (minimalUrl) {
return url.toString();
}
if (version.trim().equals("1.3") || version.trim().equals("1.3.0")) {
url.append("&CRS="); // NOI18N
} else {
url.append("&SRS="); // NOI18N
}
url.append(srs);
url.append("&FORMAT=").append(imageFormat); // NOI18N
url.append("&TRANSPARENT=").append(Boolean.valueOf(transparentImage).toString().toUpperCase()); // NOI18N
url.append("&BGCOLOR=").append(getBackgroundColor()); // NOI18N
url.append("&EXCEPTIONS=").append(exceptionsFormat); // NOI18N
url.append(getLayersString());
if (hasEveryLayerAStyle()) {
// the styles parameter must contain the same number of values as the layers parameter.
// If this requirement cannot be fulfilled, the style parameter should be sent without a value due
// to generate a valid request.
url.append(getStylesString());
} else {
if (LOG.isDebugEnabled()) {
LOG.debug(
"style parameter was added without a value to the getMap Request, because not every layer, " // NOI18N
+ "which is used within the request has a selected style"); // NOI18N
}
url.append("&STYLES=");
}
return url.toString();
}
/**
* Generates the payload for the GetMap request. The payload will only be generated if there is a custom SLD, a SRS
* and a bounding box set.
*
* @return The payload for the GetMap request.
*/
private String getGetMapPayload() {
if ((customSLD == null) || (srs == null) || (bb == null)) {
return null;
}
String result = TEMPLATE_GETMAP_PAYLOAD;
result = result.replaceAll(
TEMPLATETOKEN_CUSTOMSTYLE,
customSLD.replaceAll(TEMPLATETOKEN_CUSTOMSTYLE_LAYERNAME, name));
result = result.replaceAll(
TEMPLATETOKEN_SRS,
srs.startsWith("EPSG:") ? srs.substring(srs.indexOf(':') + 1) : srs);
result = result.replaceAll(TEMPLATETOKEN_BOUNDINGBOX_LL_X, Double.toString(bb.getX1()));
result = result.replaceAll(TEMPLATETOKEN_BOUNDINGBOX_LL_Y, Double.toString(bb.getY1()));
result = result.replaceAll(TEMPLATETOKEN_BOUNDINGBOX_UR_X, Double.toString(bb.getX2()));
result = result.replaceAll(TEMPLATETOKEN_BOUNDINGBOX_UR_Y, Double.toString(bb.getY2()));
result = result.replaceAll(TEMPLATETOKEN_WIDTH, Integer.toString(width));
result = result.replaceAll(TEMPLATETOKEN_HEIGHT, Integer.toString(height));
return result;
}
/**
* DOCUMENT ME!
*
* @param x DOCUMENT ME!
* @param y DOCUMENT ME!
* @param l DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public String getGetFeatureInfoUrl(final int x, final int y, final WMSLayer l) {
return getGetFeatureInfoUrl_internal(x, y, l, "text/html");
}
/**
* DOCUMENT ME!
*
* @param x DOCUMENT ME!
* @param y DOCUMENT ME!
* @param l DOCUMENT ME!
* @param format DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public String getGetFeatureInfoUrl(final int x, final int y, final WMSLayer l, final String format) {
return getGetFeatureInfoUrl_internal(x, y, l, format);
}
/**
* DOCUMENT ME!
*
* @param x DOCUMENT ME!
* @param y DOCUMENT ME!
* @param l DOCUMENT ME!
* @param format DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private String getGetFeatureInfoUrl_internal(final int x, final int y, final WMSLayer l, final String format) {
String url = getGetFeatureInfoPrefix();
if ((bb != null) && (url != null)) {
if (url.indexOf("?") < 0) // NOI18N
{
url += "?"; // NOI18N
}
final String version = getWmsCapabilities().getVersion();
if (version.trim().equals("1.0.0") || version.trim().equals("1.0") || version.trim().equals("1")) // NOI18N
{
url += "&WMTVER=1.0.0&REQUEST=feature_info"; // NOI18N
} else {
url += "&VERSION=" + version + "&REQUEST=GetFeatureInfo"; // NOI18N
}
url += "&BBOX=" + bb.getURLString(); // NOI18N
url += "&WIDTH=" + width; // NOI18N
url += "&HEIGHT=" + height; // NOI18N
if (version.trim().equals("1.3") || version.trim().equals("1.3.0")) {
url += "&CRS=" + srs; // NOI18N
} else {
url += "&SRS=" + srs; // NOI18N
}
url += "&FORMAT=" + imageFormat; // NOI18N
url += "&TRANSPARENT=" + Boolean.valueOf(transparentImage).toString().toUpperCase(); // NOI18N
url += "&BGCOLOR=" + backgroundColor; // NOI18N
url += "&EXCEPTIONS=" + exceptionsFormat; // exceptionsFormat;
url += "&FEATURE_COUNT=99";
url += getLayersString();
if (hasEveryLayerAStyle()) {
// the styles parameter must have the same number of values as the layers parameter.
// If this requirement cannot be fulfilled, the optional style parameter should be omitted due
// to generate a valid request.
url += getStylesString();
}
url += "&QUERY_LAYERS=" + l.getOgcCapabilitiesLayer().getName(); // NOI18N
url += "&INFO_FORMAT=" + format; // NOI18N
if (version.trim().equals("1.3") || version.trim().equals("1.3.0")) {
url += "&I=" + x; // NOI18N
url += "&J=" + y; // NOI18N
} else {
url += "&X=" + x; // NOI18N
url += "&Y=" + y; // NOI18N
}
return url;
} else {
return null;
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private String getGetMapPrefix() {
try {
String prefix = null;
if ((getWmsCapabilities() != null) && (getWmsCapabilities().getRequest() != null)) {
final Operation op = getWmsCapabilities().getRequest().getMapOperation();
if (op != null) {
// ToDo UGLY WINNING WSS schneidet wenn es get und post gibt das geht.
if (op.getGet() != null) {
prefix = op.getGet().toString();
} else if (op.getPost() != null) {
prefix = op.getPost().toString();
} else {
return null;
}
}
}
return prefix;
} catch (Throwable npe) {
LOG.warn("Throwable in getMapPrefix", npe); // NOI18N
return null;
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private String getGetFeatureInfoPrefix() {
try {
final Operation op = getWmsCapabilities().getRequest().getFeatureInfoOperation();
String prefix = null;
if (op != null) {
prefix = op.getGet().toString();
}
return prefix;
} catch (NullPointerException npe) {
LOG.warn("NPE in getGetMapPrefix()", npe); // NOI18N
return null;
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private String getLayersString() {
final StringBuilder layerString = new StringBuilder(""); // NOI18N
int counter = 0;
final Iterator it = getWMSLayers().iterator();
while (it.hasNext()) {
final Object o = it.next();
if ((o instanceof WMSLayer) && ((WMSLayer)o).isEnabled()) {
counter++;
if (counter > 1) {
layerString.append(","); // NOI18N
}
if (!isDummy()) {
layerString.append(((WMSLayer)o).getOgcCapabilitiesLayer().getName().replaceAll(" ", "%20")); // NOI18N
} else {
layerString.append(((WMSLayer)o).toString().replaceAll(" ", "%20")); // NOI18N
}
}
}
if (counter > 0) {
return "&LAYERS=" + layerString.toString(); // NOI18N
} else {
return ""; // NOI18N
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private String getStylesString() {
final StringBuilder stylesString = new StringBuilder(""); // NOI18N
int counter = 0;
final Iterator it = getWMSLayers().iterator();
while (it.hasNext()) {
final Object o = it.next();
if ((o instanceof WMSLayer) && ((WMSLayer)o).isEnabled()) {
if ((!isDummy() && (((WMSLayer)o).getSelectedStyle() != null))
|| (isDummy() && (((WMSLayer)o).getStyleName() != null))) {
counter++;
if (counter > 1) {
stylesString.append(","); // NOI18N
}
if (!isDummy()) {
stylesString.append(((WMSLayer)o).getSelectedStyle().getName().replaceAll(" ", "%20")); // NOI18N
} else {
stylesString.append(((WMSLayer)o).getStyleName().replaceAll(" ", "%20")); // NOI18N
}
}
}
}
return "&STYLES=" + stylesString.toString(); // LDS Bugfix//NOI18N
}
/**
* DOCUMENT ME!
*
* @return true, if every of the given layer has a selected style
*/
private boolean hasEveryLayerAStyle() {
final Iterator it = getWMSLayers().iterator();
while (it.hasNext()) {
final Object o = it.next();
if ((o instanceof WMSLayer) && ((WMSLayer)o).isEnabled()) {
if (((WMSLayer)o).getSelectedStyle() == null) {
return false;
}
}
}
return true;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public WMSCapabilities getWmsCapabilities() {
return wmsCapabilities;
}
/**
* DOCUMENT ME!
*
* @param wmsCapabilities DOCUMENT ME!
*/
public void setWmsCapabilities(final WMSCapabilities wmsCapabilities) {
this.wmsCapabilities = wmsCapabilities;
}
@Override
public void setPNode(final PNode imageObject) {
final boolean vis = imageObject.getVisible();
this.imageObject = imageObject;
imageObject.setVisible(vis);
}
@Override
public PNode getPNode() {
return imageObject;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public String getCapabilitiesUrl() {
return capabilitiesUrl;
}
/**
* DOCUMENT ME!
*
* @param capabilitiesUrl DOCUMENT ME!
*/
public void setCapabilitiesUrl(final String capabilitiesUrl) {
this.capabilitiesUrl = capabilitiesUrl;
}
/**
* DOCUMENT ME!
*
* @param customSLD DOCUMENT ME!
*/
public void setCustomSLD(final String customSLD) {
this.customSLD = customSLD;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Element getElement() {
try {
final Element layerConf = new Element("WMSServiceLayer"); // NOI18N
layerConf.setAttribute("name", getName()); // NOI18N
layerConf.setAttribute("title", (title == null) ? "" : title); // NOI18N
layerConf.setAttribute("visible", Boolean.valueOf(getPNode().getVisible()).toString()); // NOI18N
layerConf.setAttribute("enabled", Boolean.valueOf(isEnabled()).toString()); // NOI18N
layerConf.setAttribute("translucency", new Float(getTranslucency()).toString()); // NOI18N
layerConf.setAttribute("bgColor", getBackgroundColor()); // NOI18N
layerConf.setAttribute("imageFormat", getImageFormat()); // NOI18N
layerConf.setAttribute("exceptionFormat", getExceptionsFormat()); // NOI18N
final CapabilityLink capLink = new CapabilityLink(
CapabilityLink.OGC,
getCapabilitiesUrl(),
reverseAxisOrder,
false);
layerConf.addContent(capLink.getElement());
final Iterator lit = getWMSLayers().iterator();
while (lit.hasNext()) {
final Object elem = lit.next();
if (elem instanceof WMSLayer) {
final WMSLayer wmsLayer = (WMSLayer)elem;
final Element wmsLayerConf = new Element("wmsLayer"); // NOI18N
if (!isDummy()) {
wmsLayerConf.setAttribute("name", wmsLayer.getOgcCapabilitiesLayer().getName()); // NOI18N
wmsLayerConf.setAttribute("title", wmsLayer.getOgcCapabilitiesLayer().getTitle()); // NOI18N
} else {
wmsLayerConf.setAttribute("name", wmsLayer.toString()); // NOI18N
wmsLayerConf.setAttribute("title", wmsLayer.toString()); // NOI18N
}
wmsLayerConf.setAttribute("enabled", Boolean.valueOf(wmsLayer.isEnabled()).toString()); // NOI18N
try {
if (!isDummy()) {
wmsLayerConf.setAttribute("style", wmsLayer.getSelectedStyle().getName()); // NOI18N
} else {
wmsLayerConf.setAttribute("style", wmsLayer.getStyleName()); // NOI18N
}
} catch (Exception e) {
// nothing to do. The layer has no style.
// So no style is saved and the default style is used after loading
}
wmsLayerConf.setAttribute("info", Boolean.valueOf(wmsLayer.isQuerySelected()).toString()); // NOI18N
layerConf.addContent(wmsLayerConf);
}
}
return layerConf;
} catch (Exception e) {
LOG.error("Exception while saving layer", e);
return new Element("WMSServiceLayer");
}
}
/**
* DOCUMENT ME!
*
* @param layer DOCUMENT ME!
* @param name DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private Layer searchForLayer(final Layer layer, final String name) {
if ((layer.getName() != null) && layer.getName().equals(name)) {
return layer;
} else {
final Layer[] lArr = layer.getChildren();
for (int i = 0; i < lArr.length; i++) {
final Layer l = searchForLayer(lArr[i], name);
if (l != null) {
return l;
}
}
return null;
}
}
@Override
public Object clone() {
WMSServiceLayer w = null;
if (treePaths != null) {
w = new WMSServiceLayer(treePaths);
} else {
w = new WMSServiceLayer(wmsServiceLayerElement, capabilities);
}
w.bb = bb;
w.capabilitiesUrl = capabilitiesUrl;
w.enabled = enabled;
w.errorObject = errorObject;
w.exceptionsFormat = exceptionsFormat;
w.height = height;
w.imageFormat = imageFormat;
w.visible = visible;
// The cloned service layer and the origin service layer should not use the same pnode,
// because this would lead to problems, if the cloned layer and the origin layer are
// used in 2 different MappingComponents
w.imageObject = null;
w.ir = new ImageRetrieval(w);
w.propertyChangeSupport = new PropertyChangeSupport(this);
w.layerPosition = layerPosition;
w.listeners = new ArrayList(listeners);
w.name = name;
w.ogcLayers = ogcLayers;
w.progress = progress;
w.refreshNeeded = refreshNeeded;
w.srs = srs;
w.translucency = translucency;
w.transparentImage = transparentImage;
w.treePaths = treePaths;
w.width = width;
w.wmsCapabilities = wmsCapabilities;
w.wmsServiceLayerElement = wmsServiceLayerElement;
w.capabilities = capabilities;
w.dummyLayer = dummyLayer;
w.reverseAxisOrder = reverseAxisOrder;
final List<WMSLayer> layers = new ArrayList<WMSLayer>(wmsLayers.size());
for (final Object layerObject : wmsLayers) {
final WMSLayer layer = (WMSLayer)layerObject;
final WMSLayer newLayer = new WMSLayer(layer.getOgcCapabilitiesLayer(), layer.getSelectedStyle());
newLayer.setParentServiceLayer(w);
layers.add(newLayer);
}
w.wmsLayers = layers;
return w;
}
@Override
public boolean propertyEquals(final Object obj) {
// TODO Dieses equals wird 10000 mal aufgerufen
if (obj instanceof WMSServiceLayer) {
final WMSServiceLayer tester = (WMSServiceLayer)obj;
if (getName().equals(tester.getName())
&& ((getGetMapPrefix() == tester.getGetMapPrefix())
|| ((getGetMapPrefix() != null) && getGetMapPrefix().equals(tester.getGetMapPrefix())))
&& getLayersString().equals(tester.getLayersString())
&& getStylesString().equals(tester.getStylesString())) {
return true;
}
}
return false;
}
@Override
public String getLayerURI() {
return getName();
}
@Override
public String getServerURI() {
return getCapabilitiesUrl();
}
@Override
public Collection getChildren() {
return getWMSLayers();
}
@Override
public boolean isLayerQuerySelected() {
return ((WMSLayer)getWMSLayers().get(0)).isQuerySelected();
}
@Override
public void setLayerQuerySelected(final boolean selected) {
((WMSLayer)getWMSLayers().get(0)).setQuerySelected(selected);
}
@Override
public boolean isQueryable() {
return ((getWMSLayers().size() == 1) && ((WMSLayer)getWMSLayers().get(0)).isQueryable());
}
@Override
public Layer getLayerInformation() {
if (wmsCapabilities != null) {
Layer layer = searchForLayer(wmsCapabilities.getLayer(), name);
if (layer == null) {
layer = wmsCapabilities.getLayer();
}
return layer;
}
return null;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isDummy() {
return getWmsCapabilities() == null;
}
}