org.opengis.cite.iso19142.joins.SpatialJoinTests Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ets-wfs20 Show documentation
Show all versions of ets-wfs20 Show documentation
Checks WFS 2.0 implementations for conformance to ISO 19142:2010.
package org.opengis.cite.iso19142.joins;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPathExpressionException;
import org.apache.xerces.xs.XSElementDeclaration;
import org.apache.xerces.xs.XSTypeDefinition;
import org.opengis.cite.geomatics.SpatialOperator;
import org.opengis.cite.iso19142.ConformanceClass;
import org.opengis.cite.iso19142.ErrorMessage;
import org.opengis.cite.iso19142.ErrorMessageKeys;
import org.opengis.cite.iso19142.Namespaces;
import org.opengis.cite.iso19142.ProtocolBinding;
import org.opengis.cite.iso19142.SuiteAttribute;
import org.opengis.cite.iso19142.basic.filter.QueryFilterFixture;
import org.opengis.cite.iso19142.util.AppSchemaUtils;
import org.opengis.cite.iso19142.util.FeatureProperty;
import org.opengis.cite.iso19142.util.ServiceMetadataUtils;
import org.opengis.cite.iso19142.util.XMLUtils;
import org.testng.Assert;
import org.testng.ITestContext;
import org.testng.SkipException;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import com.sun.jersey.api.client.ClientResponse;
/**
* A spatial join includes a spatial predicate. One or more of the following
* spatial predicates must be supported:
*
* - Equals
* - Disjoint
* - Intersects
* - Touches
* - Crosses
* - Within
* - Contains
* - Overlaps
* - Beyond
* - DWithin
*
*
*
* A sample GetFeature request entity is shown below, where the "Intersects"
* predicate refers to the geometry properties of two different feature types.
*
*
*
* <wfs:GetFeature version="2.0.0" service="WFS"
* xmlns:tns="http://example.org/ns1"
* xmlns:wfs="http://www.opengis.net/wfs/2.0"
* xmlns:fes="http://www.opengis.net/fes/2.0">
* <wfs:Query typeNames="tns:Parks tns:Lakes">
* <fes:Filter>
* <fes:Intersects>
* <fes:ValueReference>tns:Parks/tns:geometry</fes:ValueReference>
* <fes:ValueReference>tns:Lakes/tns:geometry</fes:ValueReference>
* </fes:Intersects>
* </fes:Filter>
* </wfs:Query>
* </wfs:GetFeature>
*
*
*
* Sources
*
*
* - OGC 09-025r2, 7.9.2.5.3: Join processing
* - OGC 09-025r2, A.1.12: Spatial joins
* - OGC 09-026r2, A.8: Test cases for spatial filter
*
*/
public class SpatialJoinTests extends QueryFilterFixture {
public final static String IMPL_SPATIAL_JOINS = "ImplementsSpatialJoins";
private static final Logger LOGR = Logger.getLogger(SpatialJoinTests.class.getPackage().getName());
private Map> surfaceProps;
private Map> curveProps;
private Map> pointProps;
private Map> spatialCapabilities;
/**
* Searches the application schema for geometry properties where the value
* is an instance of the given type.
*
* @param gmlTypeName
* The name of a GML geometry type (may be abstract).
* @return A Map containing, for each feature type name (key), a list of
* matching geometry properties (value).
*/
Map> findGeometryProperties(String gmlTypeName) {
Map> geomProps = new HashMap>();
XSTypeDefinition gmlGeomBaseType = getModel().getTypeDefinition(gmlTypeName, Namespaces.GML);
for (QName featureType : this.featureTypes) {
List geomPropsList = AppSchemaUtils.getFeaturePropertiesByType(getModel(), featureType,
gmlGeomBaseType);
if (!geomPropsList.isEmpty()) {
geomProps.put(featureType, geomPropsList);
}
}
return geomProps;
}
/**
* Checks the value of the service constraint {@value #IMPL_SPATIAL_JOINS}
* in the capabilities document. All tests are skipped if this is not
* "TRUE".
*
* @param testContext
* Information about the test run environment.
*/
@BeforeTest
public void implementsSpatialJoins(ITestContext testContext) {
this.wfsMetadata = (Document) testContext.getSuite().getAttribute(SuiteAttribute.TEST_SUBJECT.getName());
String xpath = String.format("//ows:Constraint[@name='%s' and (ows:DefaultValue = 'TRUE')]",
IMPL_SPATIAL_JOINS);
NodeList result;
try {
result = XMLUtils.evaluateXPath(this.wfsMetadata, xpath, null);
} catch (XPathExpressionException e) {
throw new AssertionError(e.getMessage());
}
if (result.getLength() == 0) {
throw new SkipException(ErrorMessage.format(ErrorMessageKeys.NOT_IMPLEMENTED,
ConformanceClass.SPATIAL_JOINS.getConstraintName()));
}
}
/**
* Initializes the test class fixture. Finds surface, curve, and point
* properties defined in the application schema. Properties that use
* primitive types are preferred, but if none are defined then aggregate
* geometry types (Multi*) will be used instead.
*/
@BeforeClass
public void initFixture() {
this.spatialCapabilities = ServiceMetadataUtils.getSpatialCapabilities(this.wfsMetadata);
this.surfaceProps = findGeometryProperties("AbstractSurfaceType");
if (this.surfaceProps.isEmpty()) {
this.surfaceProps = findGeometryProperties("MultiSurfaceType");
}
LOGR.info(this.surfaceProps.toString());
this.curveProps = findGeometryProperties("AbstractCurveType");
if (this.curveProps.isEmpty()) {
this.curveProps = findGeometryProperties("MultiCurveType");
}
LOGR.info(this.curveProps.toString());
this.pointProps = findGeometryProperties("PointType");
if (this.pointProps.isEmpty()) {
this.pointProps = findGeometryProperties("MultiPointType");
}
LOGR.info(this.pointProps.toString());
}
/**
* [{@code Test}] Submits a basic join query that includes the
* Intersects
operator. A projection clause (wfs:PropertyName)
* is omitted, so the response entity is expected to contain instances of
* both feature types.
*/
@Test(description = "See OGC 09-025r2: 7.9.2.5.3, A.1.12")
public void joinWithIntersects() {
if (!this.spatialCapabilities.keySet().contains(SpatialOperator.INTERSECTS)) {
throw new SkipException(ErrorMessage.format(ErrorMessageKeys.NOT_IMPLEMENTED, SpatialOperator.INTERSECTS));
}
List joinProperties = new ArrayList();
if (this.surfaceProps.size() > 1) {
Iterator>> itr = this.surfaceProps.entrySet().iterator();
Entry> entry = itr.next();
joinProperties.add(new FeatureProperty(entry.getKey(), entry.getValue().get(0)));
entry = itr.next();
joinProperties.add(new FeatureProperty(entry.getKey(), entry.getValue().get(0)));
} else if (!this.surfaceProps.isEmpty() && !this.curveProps.isEmpty()) {
// surface property
Iterator>> itrSurfaceProps = this.surfaceProps.entrySet().iterator();
Entry> entrySurfaceProps = itrSurfaceProps.next();
joinProperties.add(new FeatureProperty(entrySurfaceProps.getKey(), entrySurfaceProps.getValue().get(0)));
// curve property
Iterator>> itrCurveProps = this.curveProps.entrySet().iterator();
Entry> entryCurveProps = itrCurveProps.next();
joinProperties.add(new FeatureProperty(entryCurveProps.getKey(), entryCurveProps.getValue().get(0)));
} else if (!this.surfaceProps.isEmpty() && !this.pointProps.isEmpty()) {
// surface property
Iterator>> itrSurfaceProps = this.surfaceProps.entrySet().iterator();
Entry> entrySurfaceProps = itrSurfaceProps.next();
joinProperties.add(new FeatureProperty(entrySurfaceProps.getKey(), entrySurfaceProps.getValue().get(0)));
// point property
Iterator>> itrPointProps = this.pointProps.entrySet().iterator();
Entry> entryPointProps = itrPointProps.next();
joinProperties.add(new FeatureProperty(entryPointProps.getKey(), entryPointProps.getValue().get(0)));
} else if (!this.curveProps.isEmpty() && !this.pointProps.isEmpty()) {
// curve property
Iterator>> itrCurveProps = this.curveProps.entrySet().iterator();
Entry> entryCurveProps = itrCurveProps.next();
joinProperties.add(new FeatureProperty(entryCurveProps.getKey(), entryCurveProps.getValue().get(0)));
// point property
Iterator>> itrPointProps = this.pointProps.entrySet().iterator();
Entry> entryPointProps = itrPointProps.next();
joinProperties.add(new FeatureProperty(entryPointProps.getKey(), entryPointProps.getValue().get(0)));
}
else{
throw new SkipException("This test has triggered an unexpected Spatial Join condition. The Spatial Join test will need to be applied manually.");
}
JoinQueryUtils.appendSpatialJoinQuery(this.reqEntity, "Intersects", joinProperties);
ClientResponse rsp = wfsClient.submitRequest(this.reqEntity, ProtocolBinding.ANY);
this.rspEntity = extractBodyAsDocument(rsp);
Assert.assertEquals(rsp.getStatus(), ClientResponse.Status.OK.getStatusCode(),
ErrorMessage.get(ErrorMessageKeys.UNEXPECTED_STATUS));
// TODO check entity body: F1 intersects F2
}
// self-join T1 BBOX T1 (gml:boundedBy)??
// self-join T1 INTERSECTS T1
// self-join T1 BEFORE T1
// join T1 BBOX T2 (gml;boundedBy) ??
// join T1 AFTER T2
// join T1 BEFORE T2
public void selfJoinWithIntersects() {
if (!ServiceMetadataUtils.implementsSpatialOperator(this.wfsMetadata, "Intersects")) {
throw new SkipException(ErrorMessage.format(ErrorMessageKeys.NOT_IMPLEMENTED, "Intersects operator"));
}
if (!this.surfaceProps.isEmpty()) {
// TODO
}
if (!this.curveProps.isEmpty()) {
// TODO
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy