/* (c) 2014 - 2015 Open Source Geospatial Foundation - all rights reserved
* (c) 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/package org.geoserver.wms.capabilities;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import javax.xml.namespace.QName;
import org.custommonkey.xmlunit.SimpleNamespaceContext;
import org.custommonkey.xmlunit.XMLUnit;
import org.custommonkey.xmlunit.XpathEngine;
import org.custommonkey.xmlunit.exceptions.XpathException;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.MetadataMap;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.LayerGroupInfo.Mode;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.wms.ExtendedCapabilitiesProvider;
import org.geoserver.wms.GetCapabilitiesRequest;
import org.geoserver.wms.WMS;
import org.geoserver.wms.WMSInfo;
import org.geoserver.wms.WMSTestSupport;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.junit.Test;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Test cases for Capabilities' ScaleHint
*
* @author Mauricio Pazos
* @author Niels Charlier
*
*/
public class GetCapabilitiesScaleDenominatorTest extends WMSTestSupport {
private final XpathEngine xpath;
private static final String BASE_URL = "http://localhost/geoserver";
/** Test layers */
public static final QName REGIONATED = new QName(MockData.SF_URI, "Regionated", MockData.SF_PREFIX);
public static final QName ACCIDENT = new QName(MockData.SF_URI, "Accident", MockData.SF_PREFIX);
public static final QName ACCIDENT2 = new QName(MockData.SF_URI, "Accident2", MockData.SF_PREFIX);
public static final QName ACCIDENT3 = new QName(MockData.SF_URI, "Accident3", MockData.SF_PREFIX);
private Catalog catalog;
public GetCapabilitiesScaleDenominatorTest(){
Map<String, String> namespaces = new HashMap<String, String>();
namespaces.put("xlink", "http://www.w3.org/1999/xlink");
namespaces.put("wms", "http://www.opengis.net/wms");
XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(namespaces));
xpath = XMLUnit.newXpathEngine();
}
@Override
protected void setUpTestData(SystemTestData testData) throws Exception {
// all the data we need is registered in this test
testData.setUpSecurity();
}
/**
* Adds required styles to test the selection of maximum and minimum denominator from style's rules.
*/
@Override
protected void onSetUp(SystemTestData testData) throws Exception {
this.catalog = getCatalog();
addLayerAndStyle(testData, REGIONATED);
addLayerAndStyle(testData, ACCIDENT);
addLayerAndStyle(testData, ACCIDENT2);
addLayerAndStyle(testData, ACCIDENT3);
addLayerGroups(testData);
}
void addLayerAndStyle(SystemTestData testData, QName name) throws IOException {
testData.addVectorLayer(name, null, name.getLocalPart() + ".properties", getClass(),
this.catalog);
final String styleName = name.getLocalPart();
testData.addStyle(styleName, getClass(), this.catalog);
StyleInfo defaultStyle = this.catalog.getStyleByName(styleName);
String layerId = getLayerId(name);
LayerInfo layerInfo = this.catalog.getLayerByName(layerId);
layerInfo.setDefaultStyle(defaultStyle);
this.catalog.save(layerInfo);
}
void addLayerGroups(SystemTestData testData) throws Exception {
//setup basic layergroups
testData.addStyle("Accident3_2", getClass(), this.catalog);
CoordinateReferenceSystem nativeCrs = CRS.decode("EPSG:4326", true);
ReferencedEnvelope nativeBounds = new ReferencedEnvelope(-180, 180, -90, 90, nativeCrs);
LayerGroupInfo layerGroup1 = catalog.getFactory().createLayerGroup();
layerGroup1.setName("testLayerGroup1");
layerGroup1.setBounds(nativeBounds);
layerGroup1.setMode(Mode.NAMED);
LayerGroupInfo layerGroup2 = catalog.getFactory().createLayerGroup();
layerGroup2.setName("testLayerGroup2");
layerGroup2.setBounds(nativeBounds);
LayerGroupInfo layerGroup3 = catalog.getFactory().createLayerGroup();
layerGroup3.setName("testLayerGroup3");
layerGroup3.setBounds(nativeBounds);
//add layers & styles
layerGroup1.getLayers().add(catalog.getLayerByName(getLayerId(REGIONATED)));
layerGroup1.getStyles().add(null);
layerGroup1.getLayers().add(catalog.getLayerByName(getLayerId(ACCIDENT3)));
layerGroup1.getStyles().add(catalog.getStyleByName("Accident3_2"));
layerGroup2.getLayers().add(catalog.getLayerByName(getLayerId(REGIONATED)));
layerGroup2.getLayers().add(catalog.getLayerByName(getLayerId(ACCIDENT)));
layerGroup2.getLayers().add(catalog.getLayerByName(getLayerId(ACCIDENT2)));
layerGroup3.getLayers().add(layerGroup2);
layerGroup3.getLayers().add(catalog.getLayerByName(getLayerId(ACCIDENT3)));
catalog.add(layerGroup1);
catalog.add(layerGroup2);
catalog.add(layerGroup3);
}
@Test
public void testLayerGroups()throws Exception{
Document dom = findCapabilities(false);
// print(dom);
checkWms13ValidationErrors(dom);
Element layerElement= searchLayerElement("testLayerGroup1", dom);
NodeList minScaleNode = layerElement.getElementsByTagName("MinScaleDenominator");
Element minScaleElement = (Element)minScaleNode.item(0);
NodeList maxScaleNode = layerElement.getElementsByTagName("MaxScaleDenominator");
Element maxScaleElement = (Element)maxScaleNode.item(0);
assertEquals(Double.valueOf(80000000), Double.valueOf(minScaleElement.getTextContent()));
assertEquals(Double.valueOf(1000000000), Double.valueOf(maxScaleElement.getTextContent()));
layerElement= searchLayerElement("testLayerGroup3", dom);
minScaleNode = layerElement.getElementsByTagName("wms:MinScaleDenominator");
minScaleElement = (Element)minScaleNode.item(0);
maxScaleNode = layerElement.getElementsByTagName("wms:MaxScaleDenominator");
maxScaleElement = (Element)minScaleNode.item(0);
assertNull(minScaleElement);
assertNull(maxScaleElement);
}
/**
* Retrieves the WMS's capabilities document.
*
* @param scaleHintUnitsPerDiaPixel true if the scalehint must be in units per diagonal of a pixel
* @return Capabilities as {@link Document}
*
*/
private Document findCapabilities(Boolean scaleHintUnitsPerDiaPixel) throws Exception{
//set the Scalehint units per diagonal pixel setting.
WMS wms = getWMS();
WMSInfo info=wms.getServiceInfo();
MetadataMap mm= info.getMetadata();
mm.put(WMS.SCALEHINT_MAPUNITS_PIXEL, scaleHintUnitsPerDiaPixel);
info.getGeoServer().save(info);
Capabilities_1_3_0_Transformer tr = new Capabilities_1_3_0_Transformer(wms, BASE_URL,
wms.getAllowedMapFormats(), new HashSet<ExtendedCapabilitiesProvider>());
GetCapabilitiesRequest req = new GetCapabilitiesRequest();
req.setBaseUrl(BASE_URL);
req.setVersion(WMS.VERSION_1_3_0.toString());
Document dom = WMSTestSupport.transform(req, tr);
Element root = dom.getDocumentElement();
assertEquals(WMS.VERSION_1_3_0.toString(), root.getAttribute("version"));
return dom;
}
/**
* Searches the required layer in the capabilities document.
*
* @param layerRequired
* @param capabilities
* @return The layer element or null it the required layer isn't found
* @throws XpathException
*/
private Element searchLayerElement(final String layerRequired, Document capabilities) throws XpathException {
NodeList layersNodes = xpath.getMatchingNodes("//wms:Layer/wms:Name",capabilities);
for (int i = 0; i < layersNodes.getLength(); i++) {
Element e = (Element) layersNodes.item(i);
NodeList childNodes = e.getChildNodes();
for (int j = 0; j < childNodes.getLength(); j++) {
Node item = childNodes.item(j);
String nodeValue = item.getNodeValue();
if(layerRequired.equalsIgnoreCase(nodeValue)){
return (Element) e.getParentNode(); // returns the layer element associated to the required layer name.
}
}
}
return null; // not found
}
}