/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wms.describelayer;
import static org.geoserver.ows.util.ResponseUtils.appendQueryString;
import static org.geoserver.ows.util.ResponseUtils.buildSchemaURL;
import static org.geoserver.ows.util.ResponseUtils.buildURL;
import java.util.Iterator;
import java.util.List;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import org.geoserver.ows.URLMangler.URLType;
import org.geoserver.wms.DescribeLayerRequest;
import org.geoserver.wms.MapLayerInfo;
import org.geotools.xml.transform.TransformerBase;
import org.geotools.xml.transform.Translator;
import org.xml.sax.ContentHandler;
import org.xml.sax.helpers.AttributesImpl;
/**
* <code>org.geotools.xml.transform.TransformerBase</code> specialized in producing a WMS
* DescribeLayer responses.
*
* @author Gabriel Roldan
* @version $Id$
*/
public class DescribeLayerTransformer extends TransformerBase {
/** The base url upon URLs which point to 'me' should be based. */
private String baseURL;
/**
* Creates a new DescribeLayerTransformer object.
*
* @param serverBaseUrl
* the base URL, usually "http://host:port/geoserver"
*/
public DescribeLayerTransformer(final String baseURL) {
if (baseURL == null) {
throw new NullPointerException("serverBaseUrl");
}
this.baseURL = baseURL;
setNamespaceDeclarationEnabled(false);
}
/**
* Creates and returns a Translator specialized in producing a DescribeLayer response document.
*
* @param handler
* the content handler to send sax events to.
*
* @return a new <code>DescribeLayerTranslator</code>
*/
public Translator createTranslator(ContentHandler handler) {
return new DescribeLayerTranslator(handler);
}
/**
* Gets the <code>Transformer</code> created by the overriden method in the superclass and adds
* it the DOCTYPE token pointing to the DescribeLayer DTD on this server instance.
*
* <p>
* The DTD is set at the fixed location given by the <code>schemaBaseUrl</code> passed to the
* constructor <code>+ "wms/1.1.1/WMS_DescribeLayerResponse.dtd</code>.
* </p>
*
* @return a Transformer propoerly configured to produce DescribeLayer responses.
*
* @throws TransformerException
* if it is thrown by <code>super.createTransformer()</code>
*/
public Transformer createTransformer() throws TransformerException {
Transformer transformer = super.createTransformer();
String dtdUrl = buildSchemaURL(baseURL, "wms/1.1.1/WMS_DescribeLayerResponse.dtd");
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, dtdUrl);
return transformer;
}
/**
* Sends SAX events to produce a DescribeLayer response document.
*
* @author Gabriel Roldan
* @version $Id$
*/
private class DescribeLayerTranslator extends TranslatorSupport {
/**
* Creates a new DescribeLayerTranslator object.
*/
public DescribeLayerTranslator(ContentHandler handler) {
super(handler, null, null);
}
/**
* Encode the object.
*
* @param o
* The {@link DescribeLayerRequest} to encode a DescribeLayer response for
*
* @throws IllegalArgumentException
* if the Object is not encodeable.
*/
public void encode(Object o) throws IllegalArgumentException {
if (!(o instanceof DescribeLayerRequest)) {
throw new IllegalArgumentException();
}
DescribeLayerRequest req = (DescribeLayerRequest) o;
AttributesImpl versionAtt = new AttributesImpl();
final String requestVersion = req.getVersion();
if (requestVersion == null) {
throw new NullPointerException("requestVersion");
}
versionAtt.addAttribute("", "version", "version", "", requestVersion);
start("WMS_DescribeLayerResponse", versionAtt);
handleLayers(req);
end("WMS_DescribeLayerResponse");
}
/**
* As currently GeoServer does not have support for nested layers, this method declares a
* <code>LayerDescription</code> element for each featuretype requested.
*
* @param req
*/
private void handleLayers(DescribeLayerRequest req) {
MapLayerInfo layer;
final List layers = req.getLayers();
AttributesImpl queryAtts = new AttributesImpl();
queryAtts.addAttribute("", "typeName", "typeName", "", "");
for (Iterator it = layers.iterator(); it.hasNext();) {
layer = (MapLayerInfo) it.next();
AttributesImpl layerAtts = new AttributesImpl();
layerAtts.addAttribute("", "name", "name", "", "");
String owsUrl;
String owsType;
if (MapLayerInfo.TYPE_VECTOR == layer.getType()) {
owsUrl = buildURL(baseURL, "wfs", null, URLType.SERVICE);
owsUrl = appendQueryString(owsUrl, "");
owsType = "WFS";
layerAtts.addAttribute("", "wfs", "wfs", "", owsUrl);
} else if (MapLayerInfo.TYPE_RASTER == layer.getType()) {
owsUrl = buildURL(baseURL, "wcs", null, URLType.SERVICE);
owsUrl = appendQueryString(owsUrl, "");
owsType = "WCS";
} else {
// non vector nor raster layer, LayerDescription will not contain these
// attributes
owsUrl = owsType = null;
}
if (owsType != null && owsUrl != null) {
// the layer is describable only if its vector or raster based
// in our case that meand directly associated to a resourceInfo (ie, no base
// map)
layerAtts.addAttribute("", "owsURL", "owsURL", "", owsUrl);
layerAtts.addAttribute("", "owsType", "owsType", "", owsType);
}
layerAtts.setAttribute(0, "", "name", "name", "", layer.getLayerInfo().prefixedName());
start("LayerDescription", layerAtts);
queryAtts.setAttribute(0, "", "typeName", "typeName", "", layer.getName());
element("Query", null, queryAtts);
end("LayerDescription");
}
}
}
}