/* (c) 2014 - 2016 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.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.geotools.data.DataUtilities;
import org.geotools.geometry.jts.JTS;
import org.geotools.image.test.ImageAssert;
import org.geotools.referencing.CRS;
import org.junit.Test;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.springframework.mock.web.MockHttpServletResponse;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
/**
* Test paging with app-schema.
*
* @author Rini Angreani, CSIRO Mineral Resources Flagship
*/
public class PagingTest extends AbstractAppSchemaTestSupport {
@Override
protected FeatureGML32MockData createTestData() {
FeatureGML32MockData mockData = new FeatureGML32MockData();
mockData.addStyle("namefilter", "styles/mappedfeaturebyname.sld");
return mockData;
}
private void checkMf1Values(Document doc) {
assertXpathEvaluatesTo("GUNTHORPE FORMATION", "//gsml:MappedFeature[@gml:id='mf1']/gml:name", doc);
assertXpathEvaluatesTo("urn:ogc:def:crs:EPSG::4326", "//gsml:MappedFeature[@gml:id='mf1']/gsml:shape/gml:Polygon/@srsName", doc);
assertXpathEvaluatesTo("52.5 -1.2 52.6 -1.2 52.6 -1.1 52.5 -1.1 52.5 -1.2", "//gsml:MappedFeature[@gml:id='mf1']/gsml:shape//gml:posList", doc);
assertXpathEvaluatesTo("urn:cgi:feature:CGI:EarthNaturalSurface", "//gsml:MappedFeature[@gml:id=\"mf1\"]/gsml:samplingFrame/@xlink:href", doc);
// specification gu.25699
assertXpathCount(1, "//gsml:MappedFeature[@gml:id='mf1']/gsml:specification/gsml:GeologicUnit", doc);
assertXpathEvaluatesTo("gu.25699", "//gsml:MappedFeature[@gml:id='mf1']/gsml:specification/gsml:GeologicUnit/@gml:id", doc);
// description
assertXpathEvaluatesTo("Olivine basalt, tuff, microgabbro, minor sedimentary rocks",
"//gsml:MappedFeature[@gml:id='mf1']/gsml:specification"
+ "/gsml:GeologicUnit/gml:description", doc);
// name
assertXpathCount(2, "//gsml:MappedFeature[@gml:id='mf1']/gsml:specification"
+ "/gsml:GeologicUnit/gml:name", doc);
assertXpathEvaluatesTo("Yaugher Volcanic Group", "//gsml:MappedFeature[@gml:id='mf1']/gsml:specification"
+ "/gsml:GeologicUnit/gml:name[@codeSpace='urn:ietf:rfc:2141']", doc);
// multi-valued leaf attributes that are feature chained come in random order
// when joining is used
List<String> names = new ArrayList<String>();
names.add("Yaugher Volcanic Group");
names.add("-Py");
String name = evaluate("//gsml:MappedFeature[@gml:id='mf1']/gsml:specification/gsml:GeologicUnit/gml:name[1]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:MappedFeature[@gml:id='mf1']/gsml:specification/gsml:GeologicUnit/gml:name[2]", doc);
assertTrue(names.contains(name));
names.remove(name);
assertTrue(names.isEmpty());
assertXpathEvaluatesTo("instance", "//gsml:MappedFeature[@gml:id='mf1']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:purpose", doc);
assertXpathEvaluatesTo("urn:ogc:def:nil:OGC::unknown", "//gsml:MappedFeature[@gml:id='mf1']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:geologicUnitType/@xlink:href", doc);
// occurrence
assertXpathCount(1, "//gsml:MappedFeature[@gml:id='mf1']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("", "//gsml:MappedFeature[@gml:id='mf1']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf1",
"//gsml:MappedFeature[@gml:id='mf1']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence/@xlink:href", doc);
}
private void checkMf2Values(Document doc) {
assertXpathEvaluatesTo("MERCIA MUDSTONE GROUP", "//gsml:MappedFeature[@gml:id='mf2']/gml:name", doc);
assertXpathEvaluatesTo("urn:ogc:def:crs:EPSG::4326", "//gsml:MappedFeature[@gml:id='mf2']/gsml:shape/gml:Polygon/@srsName", doc);
assertXpathEvaluatesTo("52.5 -1.3 52.6 -1.3 52.6 -1.2 52.5 -1.2 52.5 -1.3", "//gsml:MappedFeature[@gml:id='mf2']/gsml:shape//gml:posList", doc);
assertXpathEvaluatesTo("urn:cgi:feature:CGI:EarthNaturalSurface", "//gsml:MappedFeature[@gml:id=\"mf2\"]/gsml:samplingFrame/@xlink:href", doc);
// specification gu.25678
assertXpathCount(1, "//gsml:MappedFeature[@gml:id='mf2']/gsml:specification/gsml:GeologicUnit", doc);
assertXpathEvaluatesTo("gu.25678", "//gsml:MappedFeature[@gml:id='mf2']/gsml:specification/gsml:GeologicUnit/@gml:id", doc);
// description
assertXpathEvaluatesTo("Olivine basalt, tuff, microgabbro, minor sedimentary rocks",
"//gsml:MappedFeature[@gml:id='mf2']/gsml:specification"
+ "/gsml:GeologicUnit/gml:description", doc);
// name
assertXpathCount(3, "//gsml:MappedFeature[@gml:id='mf2']/gsml:specification"
+ "/gsml:GeologicUnit/gml:name", doc);
// multi-valued leaf attributes that are feature chained come in random order
// when joining is used
List<String> names = new ArrayList<String>();
names.add("Yaugher Volcanic Group 1");
names.add("Yaugher Volcanic Group 2");
names.add("-Py");
String name = evaluate("//gsml:MappedFeature[@gml:id='mf2']/gsml:specification/gsml:GeologicUnit/gml:name[1]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:MappedFeature[@gml:id='mf2']/gsml:specification/gsml:GeologicUnit/gml:name[2]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:MappedFeature[@gml:id='mf2']/gsml:specification/gsml:GeologicUnit/gml:name[3]", doc);
assertTrue(names.contains(name));
names.remove(name);
assertTrue(names.isEmpty());
assertXpathEvaluatesTo("instance", "//gsml:MappedFeature[@gml:id='mf2']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:purpose", doc);
assertXpathEvaluatesTo("urn:ogc:def:nil:OGC::unknown", "//gsml:MappedFeature[@gml:id='mf2']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:geologicUnitType/@xlink:href", doc);
// occurrence
assertXpathCount(2, "//gsml:MappedFeature[@gml:id='mf2']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("", "//gsml:MappedFeature[@gml:id='mf2']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf2",
"//gsml:MappedFeature[@gml:id='mf2']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence[1]/@xlink:href", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf3",
"//gsml:MappedFeature[@gml:id='mf2']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence[2]/@xlink:href", doc);
}
private void checkMf3Values(Document doc) {
assertXpathEvaluatesTo("CLIFTON FORMATION", "//gsml:MappedFeature[@gml:id='mf3']/gml:name", doc);
assertXpathEvaluatesTo("urn:ogc:def:crs:EPSG::4326", "//gsml:MappedFeature[@gml:id='mf3']/gsml:shape/gml:Polygon/@srsName", doc);
assertXpathEvaluatesTo("52.5 -1.2 52.6 -1.2 52.6 -1.1 52.5 -1.1 52.5 -1.2", "//gsml:MappedFeature[@gml:id='mf3']/gsml:shape//gml:posList", doc);
assertXpathEvaluatesTo("urn:cgi:feature:CGI:EarthNaturalSurface", "//gsml:MappedFeature[@gml:id=\"mf3\"]/gsml:samplingFrame/@xlink:href", doc);
// specification gu.25678
assertXpathCount(1, "//gsml:MappedFeature[@gml:id='mf3']/gsml:specification/gsml:GeologicUnit", doc);
assertXpathEvaluatesTo("gu.25678", "//gsml:MappedFeature[@gml:id='mf3']/gsml:specification/gsml:GeologicUnit/@gml:id", doc);
// description
assertXpathEvaluatesTo("Olivine basalt, tuff, microgabbro, minor sedimentary rocks",
"//gsml:MappedFeature[@gml:id='mf3']/gsml:specification"
+ "/gsml:GeologicUnit/gml:description", doc);
// name
assertXpathCount(3, "//gsml:MappedFeature[@gml:id='mf3']/gsml:specification"
+ "/gsml:GeologicUnit/gml:name", doc);
// multi-valued leaf attributes that are feature chained come in random order
// when joining is used
List<String> names = new ArrayList<String>();
names.add("Yaugher Volcanic Group 1");
names.add("Yaugher Volcanic Group 2");
names.add("-Py");
String name = evaluate("//gsml:MappedFeature[@gml:id='mf3']/gsml:specification/gsml:GeologicUnit/gml:name[1]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:MappedFeature[@gml:id='mf3']/gsml:specification/gsml:GeologicUnit/gml:name[2]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:MappedFeature[@gml:id='mf3']/gsml:specification/gsml:GeologicUnit/gml:name[3]", doc);
assertTrue(names.contains(name));
names.remove(name);
assertTrue(names.isEmpty());
assertXpathEvaluatesTo("instance", "//gsml:MappedFeature[@gml:id='mf3']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:purpose", doc);
assertXpathEvaluatesTo("urn:ogc:def:nil:OGC::unknown", "//gsml:MappedFeature[@gml:id='mf3']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:geologicUnitType/@xlink:href", doc);
// occurrence
assertXpathCount(2, "//gsml:MappedFeature[@gml:id='mf3']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("", "//gsml:MappedFeature[@gml:id='mf3']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf2",
"//gsml:MappedFeature[@gml:id='mf3']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence[1]/@xlink:href", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf3",
"//gsml:MappedFeature[@gml:id='mf3']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence[2]/@xlink:href", doc);
}
private void checkMf4Values(Document doc, String epsgId) throws NoSuchAuthorityCodeException, FactoryException, MismatchedDimensionException, TransformException {
assertXpathEvaluatesTo("MURRADUC BASALT", "//gsml:MappedFeature[@gml:id='mf4']/gml:name", doc);
String srsName = "urn:ogc:def:crs:EPSG::" + (epsgId == null ? "4326" : epsgId);
assertXpathEvaluatesTo(srsName, "//gsml:MappedFeature[@gml:id='mf4']/gsml:shape/gml:Polygon/@srsName", doc);
if (epsgId == null) {
assertXpathEvaluatesTo("52.5 -1.3 52.6 -1.3 52.6 -1.2 52.5 -1.2 52.5 -1.3", "//gsml:MappedFeature[@gml:id='mf4']/gsml:shape//gml:posList", doc);
} else {
// I can't get exact transformation figures to compare with.. not important to test anyway
}
assertXpathEvaluatesTo("urn:cgi:feature:CGI:EarthNaturalSurface", "//gsml:MappedFeature[@gml:id=\"mf4\"]/gsml:samplingFrame/@xlink:href", doc);
// specification gu.25682
assertXpathCount(1, "//gsml:MappedFeature[@gml:id='mf4']/gsml:specification/gsml:GeologicUnit", doc);
assertXpathEvaluatesTo("gu.25682", "//gsml:MappedFeature[@gml:id='mf4']/gsml:specification/gsml:GeologicUnit/@gml:id", doc);
// description
assertXpathEvaluatesTo("Olivine basalt",
"//gsml:MappedFeature[@gml:id='mf4']/gsml:specification"
+ "/gsml:GeologicUnit/gml:description", doc);
// name
assertXpathCount(2, "//gsml:MappedFeature[@gml:id='mf4']/gsml:specification"
+ "/gsml:GeologicUnit/gml:name", doc);
assertXpathEvaluatesTo("New Group", "//gsml:MappedFeature[@gml:id='mf4']/gsml:specification"
+ "/gsml:GeologicUnit/gml:name[@codeSpace='urn:ietf:rfc:2141']", doc);
// multi-valued leaf attributes that are feature chained come in random order
// when joining is used
List<String> names = new ArrayList<String>();
names.add("New Group");
names.add("-Xy");
String name = evaluate("//gsml:MappedFeature[@gml:id='mf4']/gsml:specification/gsml:GeologicUnit/gml:name[1]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:MappedFeature[@gml:id='mf4']/gsml:specification/gsml:GeologicUnit/gml:name[2]", doc);
assertTrue(names.contains(name));
names.remove(name);
assertTrue(names.isEmpty());
assertXpathEvaluatesTo("instance", "//gsml:MappedFeature[@gml:id='mf4']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:purpose", doc);
assertXpathEvaluatesTo("urn:ogc:def:nil:OGC::unknown", "//gsml:MappedFeature[@gml:id='mf4']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:geologicUnitType/@xlink:href", doc);
// occurrence
assertXpathCount(1, "//gsml:MappedFeature[@gml:id='mf4']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("", "//gsml:MappedFeature[@gml:id='mf4']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf4",
"//gsml:MappedFeature[@gml:id='mf4']/gsml:specification"
+ "/gsml:GeologicUnit/gsml:occurrence/@xlink:href", doc);
}
@Test
public void testWfs110GetFeature() throws MismatchedDimensionException, NoSuchAuthorityCodeException, FactoryException, TransformException {
Document doc = getAsDOM("wfs?request=GetFeature&version=1.1.0&typename=gsml:MappedFeature&outputFormat=gml32&maxFeatures=2&startIndex=2");
LOGGER.info("WFS GetFeature&typename=gsml:MappedFeature response:\n" + prettyString(doc));
// expecting mf3 and mf4
assertXpathCount(2, "//gsml:MappedFeature", doc);
// ensure order is correct too
Node firstNode = doc.getElementsByTagName("gsml:MappedFeature").item(0);
assertEquals("mf3", firstNode.getAttributes().getNamedItem("gml:id").getNodeValue());
checkMf3Values(doc);
Node secondNode = doc.getElementsByTagName("gsml:MappedFeature").item(1);
assertEquals("mf4", secondNode.getAttributes().getNamedItem("gml:id").getNodeValue());
checkMf4Values(doc, null);
}
@Test
public void testWfs200GetFeature() {
Document doc = getAsDOM("wfs?request=GetFeature&version=2.0.0&typeNames=gsml:MappedFeature&count=1&startIndex=1");
LOGGER.info("WFS GetFeature&typeNames=gsml:MappedFeature response:\n" + prettyString(doc));
// expecting mf2
assertXpathCount(1, "//gsml:MappedFeature", doc);
assertXpathEvaluatesTo("mf2", "//gsml:MappedFeature/@gml:id", doc);
checkMf2Values(doc);
}
@Test
public void testGetFeatureDenormalised() {
Document doc = getAsDOM("wfs?request=GetFeature&version=2.0.0&typeNames=gsml:GeologicUnit&count=1&startIndex=1");
LOGGER.info("WFS GetFeature&typeNames=gsml:GeologicUnit response:\n" + prettyString(doc));
// expecting gu.25682
assertXpathCount(1, "//gsml:GeologicUnit", doc);
assertXpathEvaluatesTo("gu.25682", "//gsml:GeologicUnit/@gml:id", doc);
// description
assertXpathEvaluatesTo("Olivine basalt", "//gsml:GeologicUnit/gml:description", doc);
// name
assertXpathCount(2, "//gsml:GeologicUnit/gml:name", doc);
assertXpathEvaluatesTo("New Group", "//gsml:GeologicUnit/gml:name[@codeSpace='urn:ietf:rfc:2141']", doc);
// multi-valued leaf attributes that are feature chained come in random order
// when joining is used
List<String> names = new ArrayList<String>();
names.add("New Group");
names.add("-Xy");
String name = evaluate("//gsml:GeologicUnit/gml:name[1]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:GeologicUnit/gml:name[2]", doc);
assertTrue(names.contains(name));
names.remove(name);
assertTrue(names.isEmpty());
assertXpathEvaluatesTo("instance", "//gsml:GeologicUnit/gsml:purpose", doc);
assertXpathEvaluatesTo("urn:ogc:def:nil:OGC::unknown", "//gsml:GeologicUnit/gsml:geologicUnitType/@xlink:href", doc);
// occurrence
assertXpathCount(1, "//gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("", "//gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf4",
"//gsml:GeologicUnit/gsml:occurrence/@xlink:href", doc);
}
@Test
public void testGetFeatureSortBy() throws MismatchedDimensionException, NoSuchAuthorityCodeException, FactoryException, TransformException {
Document doc = getAsDOM("wfs?request=GetFeature&version=1.1.0&typename=gsml:MappedFeature&outputFormat=gml32&maxFeatures=2&startIndex=2&sortBy=gsml:specification");
LOGGER.info("WFS GetFeature&typename=gsml:MappedFeature response:\n" + prettyString(doc));
assertXpathCount(2, "//gsml:MappedFeature", doc);
// ensure order is correct too
Node firstNode = doc.getElementsByTagName("gsml:MappedFeature").item(0);
assertEquals("mf4", firstNode.getAttributes().getNamedItem("gml:id").getNodeValue());
checkMf4Values(doc, null);
Node secondNode = doc.getElementsByTagName("gsml:MappedFeature").item(1);
assertEquals("mf1", secondNode.getAttributes().getNamedItem("gml:id").getNodeValue());
checkMf1Values(doc);
}
@Test
public void testGetFeatureSortByDenormalised() {
Document doc = getAsDOM("wfs?request=GetFeature&version=1.1.0&typename=gsml:GeologicUnit&outputFormat=gml32&maxFeatures=2&startIndex=0&sortBy=gml:name");
LOGGER.info("WFS GetFeature&typename=gsml:GeologicUnit response:\n" + prettyString(doc));
assertXpathCount(2, "//gsml:GeologicUnit", doc);
// ensure order is correct too
Node firstNode = doc.getElementsByTagName("gsml:GeologicUnit").item(0);
assertEquals("gu.25682", firstNode.getAttributes().getNamedItem("gml:id").getNodeValue());
// description
assertXpathEvaluatesTo("Olivine basalt", "//gsml:GeologicUnit[@gml:id='gu.25682']/gml:description", doc);
// name
assertXpathCount(2, "//gsml:GeologicUnit[@gml:id='gu.25682']/gml:name", doc);
assertXpathEvaluatesTo("New Group", "//gsml:GeologicUnit[@gml:id='gu.25682']/gml:name[@codeSpace='urn:ietf:rfc:2141']", doc);
// multi-valued leaf attributes that are feature chained come in random order
// when joining is used
List<String> names = new ArrayList<String>();
names.add("New Group");
names.add("-Xy");
String name = evaluate("//gsml:GeologicUnit[@gml:id='gu.25682']/gml:name[1]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:GeologicUnit[@gml:id='gu.25682']/gml:name[2]", doc);
assertTrue(names.contains(name));
names.remove(name);
assertTrue(names.isEmpty());
assertXpathEvaluatesTo("instance", "//gsml:GeologicUnit[@gml:id='gu.25682']/gsml:purpose", doc);
assertXpathEvaluatesTo("urn:ogc:def:nil:OGC::unknown", "//gsml:GeologicUnit[@gml:id='gu.25682']/gsml:geologicUnitType/@xlink:href", doc);
// occurrence
assertXpathCount(1, "//gsml:GeologicUnit[@gml:id='gu.25682']/gsml:occurrence", doc);
assertXpathEvaluatesTo("", "//gsml:GeologicUnit[@gml:id='gu.25682']/gsml:occurrence", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf4",
"//gsml:GeologicUnit[@gml:id='gu.25682']/gsml:occurrence/@xlink:href", doc);
Node secondNode = doc.getElementsByTagName("gsml:GeologicUnit").item(1);
assertEquals("gu.25699", secondNode.getAttributes().getNamedItem("gml:id").getNodeValue());
// description
assertXpathEvaluatesTo("Olivine basalt, tuff, microgabbro, minor sedimentary rocks",
"//gsml:GeologicUnit[@gml:id='gu.25699']/gml:description", doc);
// name
assertXpathCount(2, "//gsml:GeologicUnit[@gml:id='gu.25699']/gml:name", doc);
assertXpathEvaluatesTo("Yaugher Volcanic Group", "//gsml:GeologicUnit[@gml:id='gu.25699']/gml:name[@codeSpace='urn:ietf:rfc:2141']", doc);
// multi-valued leaf attributes that are feature chained come in random order
// when joining is used
names.add("Yaugher Volcanic Group");
names.add("-Py");
name = evaluate("//gsml:GeologicUnit[@gml:id='gu.25699']/gml:name[1]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:GeologicUnit[@gml:id='gu.25699']/gml:name[2]", doc);
assertTrue(names.contains(name));
names.remove(name);
assertTrue(names.isEmpty());
assertXpathEvaluatesTo("instance", "//gsml:GeologicUnit[@gml:id='gu.25699']/gsml:purpose", doc);
assertXpathEvaluatesTo("urn:ogc:def:nil:OGC::unknown", "//gsml:GeologicUnit[@gml:id='gu.25699']/gsml:geologicUnitType/@xlink:href", doc);
// occurrence
assertXpathCount(1, "//gsml:GeologicUnit[@gml:id='gu.25699']/gsml:occurrence", doc);
assertXpathEvaluatesTo("", "//gsml:GeologicUnit[@gml:id='gu.25699']/gsml:occurrence", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf1",
"//gsml:GeologicUnit[@gml:id='gu.25699']/gsml:occurrence/@xlink:href", doc);
}
@Test
public void testGetFeatureReproject() throws MismatchedDimensionException, NoSuchAuthorityCodeException, FactoryException, TransformException {
Document doc = null;
doc = getAsDOM("wfs?request=GetFeature&version=1.1.0&typename=gsml:MappedFeature&outputFormat=gml32&srsName=urn:ogc:def:crs:EPSG::4283&bbox=52.5,-1.3,52.51,-1.29&startIndex=1");
LOGGER.info("WFS GetFeature&typename=gsml:MappedFeature response:\n" + prettyString(doc));
assertXpathCount(1, "//gsml:MappedFeature", doc);
assertXpathEvaluatesTo("mf4", "//gsml:MappedFeature/@gml:id", doc);
checkMf4Values(doc, "4283");
}
@Test
public void testGetFeatureWithFilter() throws MismatchedDimensionException, NoSuchAuthorityCodeException, FactoryException, TransformException {
String xml = //
"<wfs:GetFeature "
+ "service=\"WFS\" " //
+ "version=\"1.1.0\" " //
+ "xmlns:ogc=\"http://www.opengis.net/ogc\" " //
+ "xmlns:wfs=\"http://www.opengis.net/wfs\" " //
+ "xmlns:gml=\"http://www.opengis.net/gml/3.2\" " //
+ "xmlns:gsml=\"urn:cgi:xmlns:CGI:GeoSciML-Core:3.0.0\" " //
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " //
+ "xsi:schemaLocation=\"" //
+ "http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd " //
+ AbstractAppSchemaMockData.GSML_URI
+ " "
+ AbstractAppSchemaMockData.GSML_SCHEMA_LOCATION_URL //
+ "\" "
+ "outputFormat=\"gml32\" "
+ "startIndex=\"1\" "
+ ">"
+ " <wfs:Query typeName=\"gsml:MappedFeature\">"
+ " <ogc:Filter>"
+ " <ogc:PropertyIsLike wildCard=\"*\" singleChar=\"#\" escapeChar=\"!\">"
+ " <ogc:Literal>M*</ogc:Literal>"
+ " <ogc:PropertyName>gml:name</ogc:PropertyName>"
+ " </ogc:PropertyIsLike>" + " </ogc:Filter>"
+ " </wfs:Query> " + "</wfs:GetFeature>";
Document doc = postAsDOM("wfs", xml);
LOGGER.info("WFS filter GetFeature response:\n" + prettyString(doc));
assertXpathCount(1, "//gsml:MappedFeature", doc);
assertXpathEvaluatesTo("mf4", "//gsml:MappedFeature/@gml:id", doc);
checkMf4Values(doc, null);
xml = //
"<wfs:GetFeature "
+ "service=\"WFS\" " //
+ "version=\"2.0.0\" " //
+ "xmlns:fes=\"http://www.opengis.net/fes/2.0\" " //
+ "xmlns:wfs=\"http://www.opengis.net/wfs/2.0\" " //
+ "xmlns:gml=\"http://www.opengis.net/gml/3.2\" " //
+ "xmlns:gsml=\"urn:cgi:xmlns:CGI:GeoSciML-Core:3.0.0\" " //
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " //
+ "xsi:schemaLocation=\"" //
+ "http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd " //
+ AbstractAppSchemaMockData.GSML_URI
+ " "
+ AbstractAppSchemaMockData.GSML_SCHEMA_LOCATION_URL //
+ "\" " + "startIndex=\"0\" count=\"1\" " + ">"
+ " <wfs:Query typeNames=\"gsml:GeologicUnit\">" + " <fes:Filter>"
+ " <fes:PropertyIsEqualTo>"
+ " <fes:Literal>-Py</fes:Literal>"
+ " <fes:ValueReference>gml:name</fes:ValueReference>"
+ " </fes:PropertyIsEqualTo>" + " </fes:Filter>"
+ " </wfs:Query> " + "</wfs:GetFeature>";
validate(xml);
doc = postAsDOM("wfs", xml);
LOGGER.info("WFS filter GetFeature response:\n" + prettyString(doc));
assertXpathCount(1, "//gsml:GeologicUnit", doc);
assertXpathEvaluatesTo("gu.25678", "//gsml:GeologicUnit/@gml:id", doc);
// description
assertXpathEvaluatesTo("Olivine basalt, tuff, microgabbro, minor sedimentary rocks",
"//gsml:GeologicUnit/gml:description", doc);
// name
assertXpathCount(3, "//gsml:GeologicUnit/gml:name", doc);
// multi-valued leaf attributes that are feature chained come in random order
// when joining is used
List<String> names = new ArrayList<String>();
names.add("Yaugher Volcanic Group 1");
names.add("Yaugher Volcanic Group 2");
names.add("-Py");
String name = evaluate("//gsml:GeologicUnit/gml:name[1]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:GeologicUnit/gml:name[2]", doc);
assertTrue(names.contains(name));
names.remove(name);
name = evaluate("//gsml:GeologicUnit/gml:name[3]", doc);
assertTrue(names.contains(name));
names.remove(name);
assertTrue(names.isEmpty());
assertXpathEvaluatesTo("instance", "//gsml:GeologicUnit/gsml:purpose", doc);
assertXpathEvaluatesTo("urn:ogc:def:nil:OGC::unknown", "//gsml:GeologicUnit/gsml:geologicUnitType/@xlink:href", doc);
// occurrence
assertXpathCount(2, "//gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("", "//gsml:GeologicUnit/gsml:occurrence", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf2",
"//gsml:GeologicUnit/gsml:occurrence[1]/@xlink:href", doc);
assertXpathEvaluatesTo("urn:cgi:feature:MappedFeature:mf3",
"//gsml:GeologicUnit/gsml:occurrence[2]/@xlink:href", doc);
}
@Test
public void testGetFeatureWithNestedFilter() {
String xml = //
"<wfs:GetFeature "
+ "service=\"WFS\" " //
+ "version=\"1.1.0\" " //
+ "xmlns:ogc=\"http://www.opengis.net/ogc\" " //
+ "xmlns:wfs=\"http://www.opengis.net/wfs\" " //
+ "xmlns:gml=\"http://www.opengis.net/gml/3.2\" " //
+ "xmlns:gsml=\"urn:cgi:xmlns:CGI:GeoSciML-Core:3.0.0\" " //
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " //
+ "xsi:schemaLocation=\"" //
+ "http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd " //
+ AbstractAppSchemaMockData.GSML_URI
+ " "
+ AbstractAppSchemaMockData.GSML_SCHEMA_LOCATION_URL //
+ "\" "
+ "outputFormat=\"gml32\" "
+ "startIndex=\"1\" "
+ ">"
+ " <wfs:Query typeName=\"gsml:MappedFeature\">"
+ " <ogc:Filter>"
+ " <ogc:PropertyIsEqualTo>"
+ " <ogc:Literal>Yaugher Volcanic Group 2</ogc:Literal>"
+ " <ogc:PropertyName>gsml:specification/gsml:GeologicUnit/gml:name</ogc:PropertyName>"
+ " </ogc:PropertyIsEqualTo>" + " </ogc:Filter>"
+ " </wfs:Query> " + "</wfs:GetFeature>";
Document doc = postAsDOM("wfs", xml);
LOGGER.info("WFS filter GetFeature response:\n" + prettyString(doc));
assertXpathCount(1, "//gsml:MappedFeature", doc);
assertXpathEvaluatesTo("mf3", "//gsml:MappedFeature/@gml:id", doc);
checkMf3Values(doc);
// test WFS 2.0
xml = //
"<wfs:GetFeature "
+ "service=\"WFS\" " //
+ "version=\"2.0.0\" " //
+ "xmlns:fes=\"http://www.opengis.net/fes/2.0\" " //
+ "xmlns:wfs=\"http://www.opengis.net/wfs/2.0\" " //
+ "xmlns:gml=\"http://www.opengis.net/gml/3.2\" " //
+ "xmlns:gsml=\"urn:cgi:xmlns:CGI:GeoSciML-Core:3.0.0\" " //
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " //
+ "xsi:schemaLocation=\"" //
+ "http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd " //
+ AbstractAppSchemaMockData.GSML_URI
+ " "
+ AbstractAppSchemaMockData.GSML_SCHEMA_LOCATION_URL //
+ "\" "
+ "startIndex=\"0\" count=\"1\" "
+ ">"
+ " <wfs:Query typeNames=\"gsml:MappedFeature\">"
+ " <fes:Filter>"
+ " <fes:PropertyIsEqualTo>"
+ " <fes:Literal>Yaugher Volcanic Group 2</fes:Literal>"
+ " <fes:ValueReference>gsml:specification/gsml:GeologicUnit/gml:name</fes:ValueReference>"
+ " </fes:PropertyIsEqualTo>" + " </fes:Filter>"
+ " </wfs:Query> " + "</wfs:GetFeature>";
validate(xml);
doc = postAsDOM("wfs", xml);
LOGGER.info("WFS filter GetFeature response:\n" + prettyString(doc));
assertXpathCount(1, "//gsml:MappedFeature", doc);
assertXpathEvaluatesTo("mf2", "//gsml:MappedFeature/@gml:id", doc);
checkMf2Values(doc);
// test xlink:href and post filtering (using functions)
xml = //
"<wfs:GetFeature "
+ "service=\"WFS\" " //
+ "version=\"2.0.0\" " //
+ "xmlns:fes=\"http://www.opengis.net/fes/2.0\" " //
+ "xmlns:wfs=\"http://www.opengis.net/wfs/2.0\" " //
+ "xmlns:gml=\"http://www.opengis.net/gml/3.2\" " //
+ "xmlns:gsml=\"urn:cgi:xmlns:CGI:GeoSciML-Core:3.0.0\" " //
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " //
+ "xsi:schemaLocation=\"" //
+ "http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd " //
+ AbstractAppSchemaMockData.GSML_URI
+ " "
+ AbstractAppSchemaMockData.GSML_SCHEMA_LOCATION_URL //
+ "\" "
+ ">"
+ " <wfs:Query typeNames=\"gsml:MappedFeature\">"
+ " <fes:Filter>"
+ " <fes:PropertyIsEqualTo>"
+ " <fes:Literal>urn:cgi:feature:MappedFeature:mf3</fes:Literal>"
+ " <fes:ValueReference>gsml:specification/gsml:GeologicUnit/gsml:occurrence/@xlink:href</fes:ValueReference>"
+ " </fes:PropertyIsEqualTo>" + " </fes:Filter>"
+ " </wfs:Query> " + "</wfs:GetFeature>";
validate(xml);
doc = postAsDOM("wfs", xml);
LOGGER.info("WFS filter GetFeature response:\n" + prettyString(doc));
assertXpathCount(2, "//gsml:MappedFeature", doc);
Node firstNode = doc.getElementsByTagName("gsml:MappedFeature").item(0);
assertEquals("mf2", firstNode.getAttributes().getNamedItem("gml:id").getNodeValue());
checkMf2Values(doc);
Node secondNode = doc.getElementsByTagName("gsml:MappedFeature").item(1);
assertEquals("mf3", secondNode.getAttributes().getNamedItem("gml:id").getNodeValue());
assertXpathEvaluatesTo("CLIFTON FORMATION", "//gsml:MappedFeature[@gml:id='mf3']/gml:name", doc);
assertXpathEvaluatesTo("urn:ogc:def:crs:EPSG::4326", "//gsml:MappedFeature[@gml:id='mf3']/gsml:shape/gml:Polygon/@srsName", doc);
assertXpathEvaluatesTo("52.5 -1.2 52.6 -1.2 52.6 -1.1 52.5 -1.1 52.5 -1.2", "//gsml:MappedFeature[@gml:id='mf3']/gsml:shape//gml:posList", doc);
assertXpathEvaluatesTo("urn:cgi:feature:CGI:EarthNaturalSurface", "//gsml:MappedFeature[@gml:id=\"mf3\"]/gsml:samplingFrame/@xlink:href", doc);
// specification gu.25678
assertXpathCount(1, "//gsml:MappedFeature[@gml:id='mf3']/gsml:specification", doc);
assertXpathCount(0, "//gsml:MappedFeature[@gml:id='mf3']/gsml:specification/gsml:GeologicUnit", doc);
assertXpathEvaluatesTo("#gu.25678", "//gsml:MappedFeature[@gml:id='mf3']/gsml:specification/@xlink:href", doc);
// test xlink:href and post filtering (using functions)
xml = //
"<wfs:GetFeature "
+ "service=\"WFS\" " //
+ "version=\"2.0.0\" " //
+ "xmlns:fes=\"http://www.opengis.net/fes/2.0\" " //
+ "xmlns:wfs=\"http://www.opengis.net/wfs/2.0\" " //
+ "xmlns:gml=\"http://www.opengis.net/gml/3.2\" " //
+ "xmlns:gsml=\"urn:cgi:xmlns:CGI:GeoSciML-Core:3.0.0\" " //
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " //
+ "xsi:schemaLocation=\"" //
+ "http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd " //
+ AbstractAppSchemaMockData.GSML_URI
+ " "
+ AbstractAppSchemaMockData.GSML_SCHEMA_LOCATION_URL //
+ "\" "
+ "startIndex=\"1\" count=\"1\" "
+ ">"
+ " <wfs:Query typeNames=\"gsml:MappedFeature\">"
+ " <fes:Filter>"
+ " <fes:PropertyIsEqualTo>"
+ " <fes:Literal>urn:cgi:feature:MappedFeature:mf3</fes:Literal>"
+ " <fes:ValueReference>gsml:specification/gsml:GeologicUnit/gsml:occurrence/@xlink:href</fes:ValueReference>"
+ " </fes:PropertyIsEqualTo>" + " </fes:Filter>"
+ " </wfs:Query> " + "</wfs:GetFeature>";
validate(xml);
doc = postAsDOM("wfs", xml);
LOGGER.info("WFS filter GetFeature response:\n" + prettyString(doc));
assertXpathCount(1, "//gsml:MappedFeature", doc);
assertXpathEvaluatesTo("mf3", "//gsml:MappedFeature/@gml:id", doc);
checkMf3Values(doc);
}
@Test
public void testGetFeatureWithCSVFormat() throws Exception {
MockHttpServletResponse resp = getAsServletResponse("wfs?request=GetFeature&version=2.0.0&typeNames=gsml:MappedFeature&count=1&startIndex=1&outputFormat=csv");
// check the mime type
assertEquals("text/csv", resp.getContentType());
// check the content disposition
assertEquals("attachment; filename=MappedFeature.csv",
resp.getHeader("Content-Disposition"));
// read the response back with a parser that can handle escaping, newlines and what not
List<String[]> lines = CSVOutputFormatTest.readLines(resp.getContentAsString());
// we should have one header line and then all the features in that feature type
assertEquals(2, lines.size());
assertEquals("mf2", lines.get(1)[0]);
}
@Test
public void testGetMap() throws IOException {
InputStream is = getBinary("wms?request=GetMap&SRS=EPSG:4326&layers=gsml:MappedFeature&styles=namefilter&BBOX=-2,52,0,54&X=0&Y=0&width=20&height=20&FORMAT=image/png&startIndex=1");
BufferedImage imageBuffer = ImageIO.read(is);
assertNotBlank("app-schema test getmap", imageBuffer, Color.WHITE);
ImageAssert
.assertEquals(
DataUtilities.urlToFile(getClass().getResource(
"/test-data/img/mappedfeature.png")), imageBuffer, 10);
}
}