Skip to content

Commit

Permalink
[GEOS-8994] Complex features nested attributes not correctly detected (
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuno Oliveira committed Nov 2, 2018
1 parent fa19ec7 commit c3b1c03
Show file tree
Hide file tree
Showing 12 changed files with 387 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.custommonkey.xmlunit.XpathEngine;
import org.custommonkey.xmlunit.exceptions.XpathException;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.util.IOUtils;
import org.geoserver.wfs.WFSInfo;
import org.geotools.appschema.jdbc.NestedFilterToSQL;
import org.geotools.appschema.resolver.xml.AppSchemaValidator;
Expand Down Expand Up @@ -621,4 +622,19 @@ protected String toString(Document document) throws TransformerException {
transformer.transform(new DOMSource(document), new StreamResult(writer));
return writer.getBuffer().toString();
}

/**
* Helper method that reads a resource from the class path converting it to text.
*
* @param resourcePath non relative path to the class path resource
* @return the content of the resource as text
*/
protected String readResource(String resourcePath) {
try (InputStream input =
NormalizedMultiValuesTest.class.getResourceAsStream(resourcePath)) {
return IOUtils.toString(input);
} catch (Exception exception) {
throw new RuntimeException(String.format("Error reading resource '%s'.", resourcePath));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* (c) 2018 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.test;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import java.util.Collections;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletResponse;

/**
* Validates the encoding of filters on nested properties with some advanced mappings and xpaths.
*/
public final class NestedElementsFilteringTest extends AbstractAppSchemaTestSupport {

private static final String STATIONS_PREFIX = "st";
private static final String STATIONS_URI = "http://www.stations.org/1.0";

@Override
protected StationsMockData createTestData() {
// instantiate our custom complex types
return new MockData();
}

/** Helper class that will setup custom complex feature types using the stations data set. */
private static final class MockData extends StationsMockData {

@Override
public void addContent() {
// add stations namespaces
putNamespace(STATIONS_PREFIX, STATIONS_URI);
// add stations feature types
addAppSchemaFeatureType(
STATIONS_PREFIX,
null,
"Station",
"/test-data/stations/nestedElements/stations.xml",
Collections.emptyMap(),
"/test-data/stations/nestedElements/stations.xsd",
"/test-data/stations/nestedElements/institutes.xml",
"/test-data/stations/nestedElements/persons.xml",
"/test-data/stations/nestedElements/stations.properties",
"/test-data/stations/nestedElements/institutes.properties",
"/test-data/stations/nestedElements/persons.properties");
}
}

@Test
public void testWfsGetFeatureWithAdvancedNestedFilter() throws Exception {
// execute the WFS 2.0 request
MockHttpServletResponse response =
postAsServletResponse(
"wfs",
readResource(
"/test-data/stations/nestedElements/requests/wfs_get_feature_1.xml"));
// check that station 1 was returned
String content = response.getContentAsString();
assertThat(content, containsString("gml:id=\"ins.1\""));
assertThat(StringUtils.countMatches(content, "<wfs:member>"), is(1));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.custommonkey.xmlunit.XpathEngine;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.util.IOUtils;
import org.geotools.data.DataAccess;
import org.geotools.data.FeatureSource;
import org.geotools.data.complex.AppSchemaDataAccess;
Expand Down Expand Up @@ -420,19 +418,4 @@ private boolean notJdbcBased() throws Exception {
FeatureSource featureSource = appSchemaDataAccess.getMappingByName(name).getSource();
return !(featureSource instanceof JDBCFeatureStore);
}

/**
* Helper method that reads a resource from the class path converting it to text.
*
* @param resourcePath non relative path to the class path resource
* @return the content of the resource as text
*/
private String readResource(String resourcePath) {
try (InputStream input =
NormalizedMultiValuesTest.class.getResourceAsStream(resourcePath)) {
return IOUtils.toString(input);
} catch (Exception exception) {
throw new RuntimeException(String.format("Error reading resource '%s'.", resourcePath));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ protected void addStationFeatureType(

/**
* Helper method that will add the desired App-Schema defined feature type customizing it for
* the desired GML version.
* the desired GML version. If the provided GML prefix is NULL or empty it will be ignored.
*/
protected void addAppSchemaFeatureType(
String namespacePrefix,
Expand Down Expand Up @@ -374,6 +374,10 @@ private File getTargetFile(String resource, String gmlPrefix, File gmlDirectory)
}
String extension = name.substring(index);
name = name.substring(0, index);
if (gmlPrefix == null || gmlPrefix.isEmpty()) {
// no gml prefix to add
return new File(gmlDirectory, name + extension);
}
return new File(gmlDirectory, name + "_" + gmlPrefix + extension);
}

Expand All @@ -386,6 +390,10 @@ protected synchronized File getDirectoryForGmlPrefix(String gmlPrefix) {
// init the test directory
testRootDirectory = createTestRootDirectory();
}
if (gmlPrefix == null || gmlPrefix.isEmpty()) {
// no GML prefix, let's just use the root directory
return testRootDirectory;
}
return new File(testRootDirectory, gmlPrefix);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
_=ID:String,NAME:String,ADDRESS:String,STATION:String
ins.1=ins.1|ins1|europe|st.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<as:AppSchemaDataAccess xmlns:as="http://www.geotools.org/app-schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.geotools.org/app-schema AppSchemaDataAccess.xsd">
<namespaces>
<Namespace>
<prefix>st</prefix>
<uri>http://www.stations.org/1.0</uri>
</Namespace>
<Namespace>
<prefix>xlink</prefix>
<uri>http://www.w3.org/1999/xlink</uri>
</Namespace>
</namespaces>
<sourceDataStores>
<DataStore>
<id>institutes</id>
<parameters>
<Parameter>
<name>directory</name>
<value>file:./</value>
</Parameter>
</parameters>
</DataStore>
</sourceDataStores>
<targetTypes>
<FeatureType>
<schemaUri>stations.xsd</schemaUri>
</FeatureType>
</targetTypes>
<typeMappings>
<FeatureTypeMapping>
<sourceDataStore>institutes</sourceDataStore>
<sourceType>institutes</sourceType>
<targetElement>st:Institute</targetElement>
<attributeMappings>
<AttributeMapping>
<targetAttribute>st:Institute</targetAttribute>
<idExpression>
<OCQL>ID</OCQL>
</idExpression>
</AttributeMapping>
<AttributeMapping>
<targetAttribute>st:Institute/st:name</targetAttribute>
<sourceExpression>
<OCQL>NAME</OCQL>
</sourceExpression>
</AttributeMapping>
<AttributeMapping>
<targetAttribute>st:Institute/st:contact/st:identification/st:address</targetAttribute>
<sourceExpression>
<OCQL>ADDRESS</OCQL>
</sourceExpression>
</AttributeMapping>
<AttributeMapping>
<targetAttribute>FEATURE_LINK[1]</targetAttribute>
<sourceExpression>
<OCQL>STATION</OCQL>
</sourceExpression>
</AttributeMapping>
<AttributeMapping>
<targetAttribute>st:Institute/st:contact/st:persons</targetAttribute>
<sourceExpression>
<OCQL>ID</OCQL>
<linkElement>st:Person</linkElement>
<linkField>FEATURE_LINK[2]</linkField>
</sourceExpression>
</AttributeMapping>
</attributeMappings>
</FeatureTypeMapping>
</typeMappings>
</as:AppSchemaDataAccess>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
_=ID:String,NAME:String,MAIL:String,INSTITUTE:String
ps.1=ps.1|ps1|ps1@stations.org|ins.1
ps.2=ps.2|ps2|ps1@stations.org|ins.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<as:AppSchemaDataAccess xmlns:as="http://www.geotools.org/app-schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.geotools.org/app-schema AppSchemaDataAccess.xsd">
<namespaces>
<Namespace>
<prefix>st</prefix>
<uri>http://www.stations.org/1.0</uri>
</Namespace>
<Namespace>
<prefix>xlink</prefix>
<uri>http://www.w3.org/1999/xlink</uri>
</Namespace>
</namespaces>
<sourceDataStores>
<DataStore>
<id>persons</id>
<parameters>
<Parameter>
<name>directory</name>
<value>file:./</value>
</Parameter>
</parameters>
</DataStore>
</sourceDataStores>
<targetTypes>
<FeatureType>
<schemaUri>stations.xsd</schemaUri>
</FeatureType>
</targetTypes>
<typeMappings>
<FeatureTypeMapping>
<sourceDataStore>persons</sourceDataStore>
<sourceType>persons</sourceType>
<targetElement>st:Person</targetElement>
<attributeMappings>
<AttributeMapping>
<targetAttribute>st:Person</targetAttribute>
<idExpression>
<OCQL>ID</OCQL>
</idExpression>
</AttributeMapping>
<AttributeMapping>
<targetAttribute>st:Person/st:name</targetAttribute>
<sourceExpression>
<OCQL>NAME</OCQL>
</sourceExpression>
</AttributeMapping>
<AttributeMapping>
<targetAttribute>st:Person/st:mail</targetAttribute>
<sourceExpression>
<OCQL>MAIL</OCQL>
</sourceExpression>
</AttributeMapping>
<AttributeMapping>
<targetAttribute>FEATURE_LINK[2]</targetAttribute>
<sourceExpression>
<OCQL>INSTITUTE</OCQL>
</sourceExpression>
</AttributeMapping>
</attributeMappings>
</FeatureTypeMapping>
</typeMappings>
</as:AppSchemaDataAccess>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<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">
<wfs:Query typeNames="st:Station">
<fes:Filter>
<fes:And>
<fes:PropertyIsEqualTo>
<fes:ValueReference>
st:Station/st:meta/st:institutes/st:Institute/st:contact/st:identification/st:address
</fes:ValueReference>
<fes:Literal>europe</fes:Literal>
</fes:PropertyIsEqualTo>
</fes:And>
</fes:Filter>
</wfs:Query>
</wfs:GetFeature>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
_=ID:String,NAME:String,LOCATION:Geometry:srid=4326
st.1=st.1|station1|POINT(-1 1)
st.2=st.2|station2|POINT(-2 -3)

0 comments on commit c3b1c03

Please sign in to comment.