/**
* Copyright (c) Codice Foundation
*
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*
**/
package org.codice.ddf.spatial.ogc.wfs.v2_0_0.catalog.source;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.lang.StringUtils;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.codice.ddf.spatial.ogc.catalog.common.AvailabilityTask;
import org.codice.ddf.spatial.ogc.wfs.catalog.common.WfsException;
import org.codice.ddf.spatial.ogc.wfs.catalog.mapper.MetacardMapper;
import org.codice.ddf.spatial.ogc.wfs.catalog.source.WfsUriResolver;
import org.codice.ddf.spatial.ogc.wfs.v2_0_0.catalog.common.DescribeFeatureTypeRequest;
import org.codice.ddf.spatial.ogc.wfs.v2_0_0.catalog.common.GetCapabilitiesRequest;
import org.codice.ddf.spatial.ogc.wfs.v2_0_0.catalog.common.Wfs20Constants;
import org.codice.ddf.spatial.ogc.wfs.v2_0_0.catalog.common.Wfs20FeatureCollection;
import org.codice.ddf.spatial.ogc.wfs.v2_0_0.catalog.source.reader.FeatureCollectionMessageBodyReaderWfs20;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.opengis.filter.Filter;
import org.opengis.filter.sort.SortBy;
import org.opengis.filter.sort.SortOrder;
import org.osgi.framework.BundleContext;
import ddf.catalog.data.ContentType;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.Result;
import ddf.catalog.data.impl.MetacardImpl;
import ddf.catalog.filter.impl.SortByImpl;
import ddf.catalog.filter.proxy.adapter.GeotoolsFilterAdapterImpl;
import ddf.catalog.filter.proxy.builder.GeotoolsFilterBuilder;
import ddf.catalog.operation.Query;
import ddf.catalog.operation.SourceResponse;
import ddf.catalog.operation.impl.QueryImpl;
import ddf.catalog.operation.impl.QueryRequestImpl;
import ddf.catalog.source.UnsupportedQueryException;
import net.opengis.filter.v_2_0_0.ConformanceType;
import net.opengis.filter.v_2_0_0.FilterCapabilities;
import net.opengis.filter.v_2_0_0.SortByType;
import net.opengis.filter.v_2_0_0.SortOrderType;
import net.opengis.ows.v_1_1_0.DomainType;
import net.opengis.ows.v_1_1_0.ValueType;
import net.opengis.wfs.v_2_0_0.FeatureTypeListType;
import net.opengis.wfs.v_2_0_0.FeatureTypeType;
import net.opengis.wfs.v_2_0_0.GetFeatureType;
import net.opengis.wfs.v_2_0_0.QueryType;
import net.opengis.wfs.v_2_0_0.WFSCapabilitiesType;
public class TestWfsSource {
private static final String ONE_TEXT_PROPERTY_SCHEMA =
"<?xml version=\"1.0\"?>" + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
+ "<xs:element name=\"shiporder\">" + "<xs:complexType>" + "<xs:sequence>"
+ "<xs:element name=\"title\" type=\"xs:string\"/>" + "</xs:sequence>"
+ "</xs:complexType>" + "</xs:element>" + "</xs:schema>";
private static final String SAMPLE_FEATURE_NAME = "SampleFeature";
private static final Integer MAX_FEATURES = 10;
private static final Integer NULL_NUM_RETURNED = 9889;
private static final String LITERAL = "literal";
private final GeotoolsFilterBuilder builder = new GeotoolsFilterBuilder();
private RemoteWfs mockWfs = mock(RemoteWfs.class);
private WFSCapabilitiesType mockCapabilites = new WFSCapabilitiesType();
private BundleContext mockContext = mock(BundleContext.class);
private AvailabilityTask mockAvailabilityTask = mock(AvailabilityTask.class);
private FeatureCollectionMessageBodyReaderWfs20 mockReader = mock(
FeatureCollectionMessageBodyReaderWfs20.class);
private Wfs20FeatureCollection mockFeatureCollection = mock(Wfs20FeatureCollection.class);
public WfsSource getWfsSource(final String schema, final FilterCapabilities filterCapabilities,
final String srsName, final int numFeatures) throws WfsException {
return getWfsSource(schema, filterCapabilities, srsName, numFeatures, false);
}
public WfsSource getWfsSource(final String schema, final FilterCapabilities filterCapabilities,
final String srsName, final int numFeatures,
final boolean throwExceptionOnDescribeFeatureType) throws WfsException {
// GetCapabilities Response
when(mockWfs.getCapabilities(any(GetCapabilitiesRequest.class)))
.thenReturn(mockCapabilites);
mockCapabilites.setFilterCapabilities(filterCapabilities);
when(mockAvailabilityTask.isAvailable()).thenReturn(true);
mockCapabilites.setFeatureTypeList(new FeatureTypeListType());
for (int ii = 0; ii < numFeatures; ii++) {
FeatureTypeType feature = new FeatureTypeType();
QName qName;
if (ii == 0) {
qName = new QName(SAMPLE_FEATURE_NAME + ii);
} else {
qName = new QName("http://example.com", SAMPLE_FEATURE_NAME + ii, "Prefix" + ii);
}
feature.setName(qName);
feature.setDefaultCRS(Wfs20Constants.EPSG_4326_URN);
mockCapabilites.getFeatureTypeList().getFeatureType().add(feature);
}
XmlSchema xmlSchema = null;
if (StringUtils.isNotBlank(schema)) {
XmlSchemaCollection schemaCollection = new XmlSchemaCollection();
WfsUriResolver wfsUriResolver = new WfsUriResolver();
wfsUriResolver.setGmlNamespace(Wfs20Constants.GML_3_2_NAMESPACE);
wfsUriResolver.setWfsNamespace(Wfs20Constants.WFS_2_0_NAMESPACE);
schemaCollection.setSchemaResolver(wfsUriResolver);
xmlSchema = schemaCollection
.read(new StreamSource(new ByteArrayInputStream(schema.getBytes())));
}
if (throwExceptionOnDescribeFeatureType) {
when(mockWfs.describeFeatureType(any(DescribeFeatureTypeRequest.class)))
.thenThrow(new WfsException(""));
} else {
when(mockWfs.describeFeatureType(any(DescribeFeatureTypeRequest.class)))
.thenReturn(xmlSchema);
}
when(mockWfs.getFeatureCollectionReader()).thenReturn(mockReader);
// GetFeature Response
when(mockWfs.getFeature(any(GetFeatureType.class))).thenReturn(mockFeatureCollection);
when(mockFeatureCollection.getNumberReturned()).thenReturn(BigInteger.valueOf(numFeatures));
when(mockFeatureCollection.getMembers()).thenAnswer(new Answer<List<Metacard>>() {
@Override
public List<Metacard> answer(InvocationOnMock invocation) {
// Create as many metacards as there are features
List<Metacard> metacards = new ArrayList<Metacard>(numFeatures);
for (int i = 0; i < numFeatures; i++) {
MetacardImpl mc = new MetacardImpl();
mc.setId("ID_" + String.valueOf(i + 1));
metacards.add(mc);
}
return metacards;
}
});
MetacardMapper mockMapper = mock(MetacardMapper.class);
List<MetacardMapper> mappers = new ArrayList<MetacardMapper>(1);
mappers.add(mockMapper);
WfsSource source = new WfsSource(mockWfs, new GeotoolsFilterAdapterImpl(), mockContext,
mockAvailabilityTask);
source.setMetacardToFeatureMapper(mappers);
return source;
}
public WfsSource getWfsSource(final String schema, final FilterCapabilities filterCapabilities,
final String srsName, final int numFeatures,
final boolean throwExceptionOnDescribeFeatureType, boolean prefix,
int numReturned) throws WfsException {
// GetCapabilities Response
when(mockWfs.getCapabilities(any(GetCapabilitiesRequest.class)))
.thenReturn(mockCapabilites);
when(mockFeatureCollection.getMembers()).thenAnswer(new Answer<List<Metacard>>() {
@Override
public List<Metacard> answer(InvocationOnMock invocation) {
// Create as many metacards as there are features
List<Metacard> metacards = new ArrayList<Metacard>(numFeatures);
for (int i = 0; i < numFeatures; i++) {
MetacardImpl mc = new MetacardImpl();
mc.setId("ID_" + String.valueOf(i + 1));
metacards.add(mc);
}
return metacards;
}
});
if (numReturned != NULL_NUM_RETURNED) {
when(mockFeatureCollection.getNumberReturned())
.thenReturn(BigInteger.valueOf(numReturned));
} else {
when(mockFeatureCollection.getNumberReturned()).thenReturn(null);
}
when(mockWfs.getFeature(any(GetFeatureType.class))).thenReturn(mockFeatureCollection);
mockCapabilites.setFilterCapabilities(filterCapabilities);
when(mockAvailabilityTask.isAvailable()).thenReturn(true);
mockCapabilites.setFeatureTypeList(new FeatureTypeListType());
for (int ii = 0; ii < numFeatures; ii++) {
FeatureTypeType feature = new FeatureTypeType();
QName qName;
if (prefix) {
qName = new QName("http://example.com", SAMPLE_FEATURE_NAME + ii, "Prefix" + ii);
} else {
qName = new QName("http://example.com", SAMPLE_FEATURE_NAME + ii);
}
feature.setName(qName);
feature.setDefaultCRS(Wfs20Constants.EPSG_4326_URN);
mockCapabilites.getFeatureTypeList().getFeatureType().add(feature);
}
XmlSchema xmlSchema = null;
if (StringUtils.isNotBlank(schema)) {
XmlSchemaCollection schemaCollection = new XmlSchemaCollection();
WfsUriResolver wfsUriResolver = new WfsUriResolver();
wfsUriResolver.setGmlNamespace(Wfs20Constants.GML_3_2_NAMESPACE);
wfsUriResolver.setWfsNamespace(Wfs20Constants.WFS_2_0_NAMESPACE);
schemaCollection.setSchemaResolver(wfsUriResolver);
xmlSchema = schemaCollection
.read(new StreamSource(new ByteArrayInputStream(schema.getBytes())));
}
if (throwExceptionOnDescribeFeatureType) {
when(mockWfs.describeFeatureType(any(DescribeFeatureTypeRequest.class)))
.thenThrow(new WfsException(""));
} else {
when(mockWfs.describeFeatureType(any(DescribeFeatureTypeRequest.class)))
.thenReturn(xmlSchema);
}
when(mockWfs.getFeatureCollectionReader()).thenReturn(mockReader);
return new WfsSource(mockWfs, new GeotoolsFilterAdapterImpl(), mockContext,
mockAvailabilityTask);
}
@Test
public void testAvailability() throws WfsException {
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 1);
assertTrue(source.isAvailable());
}
@Test
public void testParseCapabilities() throws WfsException {
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 1);
assertTrue(source.isAvailable());
assertThat(source.featureTypeFilters.size(), is(1));
WfsFilterDelegate delegate = source.featureTypeFilters
.get(new QName(SAMPLE_FEATURE_NAME + "0"));
assertThat(delegate, notNullValue());
}
@Test
public void testParseCapabilitiesNoFeatures() throws WfsException {
WfsSource source = getWfsSource("", MockWfsServer.getFilterCapabilities(),
Wfs20Constants.EPSG_4326_URN, 0);
assertTrue(source.isAvailable());
assertThat(source.featureTypeFilters.size(), is(0));
}
@Test
public void testParseCapabilitiesNoFilterCapabilities() throws WfsException {
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA, null,
Wfs20Constants.EPSG_4326_URN, 1);
assertTrue(source.isAvailable());
assertThat(source.featureTypeFilters.size(), is(0));
}
@Test
public void testConfigureFeatureTypes() throws WfsException {
ArgumentCaptor<DescribeFeatureTypeRequest> captor = ArgumentCaptor
.forClass(DescribeFeatureTypeRequest.class);
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 1);
final String SAMPLE_FEATURE_NAME0 = SAMPLE_FEATURE_NAME + "0";
verify(mockWfs).describeFeatureType(captor.capture());
DescribeFeatureTypeRequest describeFeatureType = captor.getValue();
// sample feature 0 does not have a prefix
assertThat(SAMPLE_FEATURE_NAME0, equalTo(describeFeatureType.getTypeName()));
assertTrue(source.isAvailable());
assertThat(source.featureTypeFilters.size(), is(1));
WfsFilterDelegate delegate = source.featureTypeFilters.get(new QName(SAMPLE_FEATURE_NAME0));
assertThat(delegate, notNullValue());
assertThat(source.getContentTypes().size(), is(1));
List<ContentType> types = new ArrayList<ContentType>();
types.addAll(source.getContentTypes());
assertTrue(SAMPLE_FEATURE_NAME0.equals(types.get(0).getName()));
}
@Test
public void testConfigureFeatureTypesDescribeFeatureException() throws WfsException {
ArgumentCaptor<DescribeFeatureTypeRequest> captor = ArgumentCaptor
.forClass(DescribeFeatureTypeRequest.class);
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 1, true);
final String SAMPLE_FEATURE_NAME0 = SAMPLE_FEATURE_NAME + "0";
verify(mockWfs).describeFeatureType(captor.capture());
DescribeFeatureTypeRequest describeFeatureType = captor.getValue();
// sample feature 0 does not have a prefix
assertThat(SAMPLE_FEATURE_NAME0, equalTo(describeFeatureType.getTypeName()));
assertTrue(source.featureTypeFilters.isEmpty());
assertTrue(source.getContentTypes().isEmpty());
}
@Test
public void testTypeNameHasPrefix() throws WfsException, UnsupportedQueryException {
//Setup
final String TITLE = "title";
final String searchPhrase = "*";
final int pageSize = 1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 3, false, true,
3);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
SortBy sortBy = new SortByImpl(TITLE, SortOrder.DESCENDING);
query.setSortBy(sortBy);
// Perform test
GetFeatureType featureType = source.buildGetFeatureRequest(query);
//Validate
List<JAXBElement<?>> queryList = featureType.getAbstractQueryExpression();
for (JAXBElement<?> queryType : queryList) {
Object val = queryType.getValue();
QueryType queryTypeVal = (QueryType) val;
assertThat(queryTypeVal.getTypeNames().get(0), containsString("Prefix"));
assertThat(queryTypeVal.getTypeNames().get(0), containsString(":"));
assertThat(queryTypeVal.getTypeNames().get(0), containsString("SampleFeature"));
}
}
@Test
public void testTypeNameHasNoPrefix() throws WfsException, UnsupportedQueryException {
//Setup
final String TITLE = "title";
final String searchPhrase = "*";
final int pageSize = 1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 3, false,
false, 3);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
SortBy sortBy = new SortByImpl(TITLE, SortOrder.DESCENDING);
query.setSortBy(sortBy);
// Perform test
GetFeatureType featureType = source.buildGetFeatureRequest(query);
//Validate
List<JAXBElement<?>> queryList = featureType.getAbstractQueryExpression();
for (JAXBElement<?> queryType : queryList) {
Object val = queryType.getValue();
QueryType queryTypeVal = (QueryType) val;
assertThat(queryTypeVal.getTypeNames().get(0), containsString("SampleFeature"));
assertThat(queryTypeVal.getTypeNames().get(0), is(not(containsString("Prefix"))));
assertThat(queryTypeVal.getTypeNames().get(0), is(not(containsString(":"))));
}
}
/**
* Given 10 features (and metacards) exist that match search criteria, since page size=4 and
* startIndex=0, should get 4 results back - metacards 1 thru 4.
*
* @throws WfsException
* @throws TransformerConfigurationException
* @throws UnsupportedQueryException
*/
@Test
public void testPagingStartIndexZero() throws WfsException, TransformerConfigurationException,
UnsupportedQueryException {
//Setup
int pageSize = 4;
int startIndex = 0;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 10, false);
Filter filter = builder.attribute(Metacard.ANY_TEXT).is().like().text(LITERAL);
Query query = new QueryImpl(filter, startIndex, pageSize, null, false, 0);
//Execute
GetFeatureType featureType = source.buildGetFeatureRequest(query);
BigInteger startIndexGetFeature = featureType.getStartIndex();
BigInteger countGetFeature = featureType.getCount();
//Verify
assertThat(countGetFeature.intValue(), is(pageSize));
assertThat(startIndexGetFeature.intValue(), is(startIndex));
}
/**
* Verify that, per DDF Query API Javadoc, if the startIndex is negative, the WfsSource throws
* an UnsupportedQueryException.
*
* @throws WfsException
* @throws TransformerConfigurationException
* @throws UnsupportedQueryException
*/
@Test(expected = UnsupportedQueryException.class)
public void testPagingStartIndexNegative() throws WfsException,
TransformerConfigurationException, UnsupportedQueryException {
//Setup
int pageSize = 4;
int startIndex = -1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 10, false);
Filter filter = builder.attribute(Metacard.ANY_TEXT).is().like().text(LITERAL);
Query query = new QueryImpl(filter, startIndex, pageSize, null, false, 0);
//Execute
GetFeatureType featureType = source.buildGetFeatureRequest(query);
}
/**
* Verify that, per DDF Query API Javadoc, if the startIndex is negative, the WfsSource throws
* an UnsupportedQueryException.
*
* @throws WfsException
* @throws TransformerConfigurationException
* @throws UnsupportedQueryException
*/
@Test(expected = UnsupportedQueryException.class)
public void testPagingPageSizeNegative() throws WfsException, TransformerConfigurationException,
UnsupportedQueryException {
//Setup
int pageSize = -4;
int startIndex = 0;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 10, false);
Filter filter = builder.attribute(Metacard.ANY_TEXT).is().like().text(LITERAL);
Query query = new QueryImpl(filter, startIndex, pageSize, null, false, 0);
//Execute
GetFeatureType featureType = source.buildGetFeatureRequest(query);
}
@Test
public void testResultNumReturnedNegative() throws WfsException,
TransformerConfigurationException, UnsupportedQueryException {
//Setup
final String TITLE = "title";
final String searchPhrase = "*";
final int pageSize = 1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 3, false, true,
-1);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
SortBy sortBy = new SortByImpl(TITLE, SortOrder.DESCENDING);
query.setSortBy(sortBy);
QueryRequestImpl queryReq = new QueryRequestImpl(query);
// Perform test
SourceResponse resp = source.query(queryReq);
}
/**
* If numberReturned is null, then query should return back size equivalent to the number of members in the
* feature collection.
*
* @throws WfsException
* @throws TransformerConfigurationException
* @throws UnsupportedQueryException
*/
@Test
public void testResultNumReturnedIsNull() throws WfsException,
TransformerConfigurationException, UnsupportedQueryException {
//Setup
final String TITLE = "title";
final String searchPhrase = "*";
final int pageSize = 1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 3, false, true,
NULL_NUM_RETURNED);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
SortBy sortBy = new SortByImpl(TITLE, SortOrder.DESCENDING);
query.setSortBy(sortBy);
QueryRequestImpl queryReq = new QueryRequestImpl(query);
// Perform test
SourceResponse resp = source.query(queryReq);
assertEquals(3, resp.getResults().size());
}
/**
* If numberReturned is null, then query should return back size equivalent to the number of members in the
* feature collection.
*
* @throws WfsException
* @throws TransformerConfigurationException
* @throws UnsupportedQueryException
*/
@Test
public void testResultNumReturnedIsWrong() throws WfsException,
TransformerConfigurationException, UnsupportedQueryException {
//Setup
final String TITLE = "title";
final String searchPhrase = "*";
final int pageSize = 1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 3, false, true,
5);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
SortBy sortBy = new SortByImpl(TITLE, SortOrder.DESCENDING);
query.setSortBy(sortBy);
QueryRequestImpl queryReq = new QueryRequestImpl(query);
// Perform test
SourceResponse resp = source.query(queryReq);
assertEquals(3, resp.getResults().size());
}
@Test
public void testResultNumReturnedIsZero() throws WfsException,
TransformerConfigurationException, UnsupportedQueryException {
//Setup
final String TITLE = "title";
final String searchPhrase = "*";
final int pageSize = 1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 3, false, true,
0);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
SortBy sortBy = new SortByImpl(TITLE, SortOrder.DESCENDING);
query.setSortBy(sortBy);
QueryRequestImpl queryReq = new QueryRequestImpl(query);
// Perform test
SourceResponse resp = source.query(queryReq);
assertEquals(3, resp.getResults().size());
}
/**
* Verify that the SortBy is set with the mapped Feature Property and a ASC sort order. In this case, the incoming sort property of TEMPORAL is mapped to
* myTemporalFeatureProperty.
*
* <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
* <ns5:GetFeature startIndex="1" count="1" service="WFS" version="2.0.0" xmlns:ns2="http://www.opengis.net/ows/1.1" xmlns="http://www.opengis.net/fes/2.0" xmlns:ns4="http://www.opengis.net/gml" xmlns:ns3="http://www.w3.org/1999/xlink" xmlns:ns5="http://www.opengis.net/wfs/2.0">
* <ns5:Query typeNames="SampleFeature0" handle="SampleFeature0">
* <Filter>
* <PropertyIsLike wildCard="*" singleChar="?" escapeChar="!">
* <Literal>*</Literal>
* <ValueReference>title</ValueReference>
* </PropertyIsLike>
* </Filter>
* <SortBy>
* <SortProperty>
* <ValueReference>myTemporalFeatureProperty</ValueReference>
* <SortOrder>ASC</SortOrder>
* </SortProperty>
* </SortBy>
* </ns5:Query>
* </ns5:GetFeature>
*/
@Test
public void testSortingAscendingSortingSupported() throws Exception {
// Setup
final String searchPhrase = "*";
final String mockTemporalFeatureProperty = "myTemporalFeatureProperty";
final String mockFeatureType = "{http://example.com}" + SAMPLE_FEATURE_NAME + 0;
final int pageSize = 1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 1, false,
false, 0);
MetacardMapper mockMetacardMapper = mock(MetacardMapper.class);
when(mockMetacardMapper.getFeatureType()).thenReturn(mockFeatureType);
when(mockMetacardMapper.getSortByTemporalFeatureProperty())
.thenReturn(mockTemporalFeatureProperty);
List<MetacardMapper> mappers = new ArrayList<MetacardMapper>(1);
mappers.add(mockMetacardMapper);
source.setMetacardToFeatureMapper(mappers);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
SortBy sortBy = new SortByImpl(Result.TEMPORAL, SortOrder.ASCENDING);
query.setSortBy(sortBy);
// Perform Test
GetFeatureType featureType = source.buildGetFeatureRequest(query);
// Verify
QueryType queryType = (QueryType) featureType.getAbstractQueryExpression().get(0)
.getValue();
JAXBElement<?> abstractSortingClause = queryType.getAbstractSortingClause();
SortByType sortByType = (SortByType) abstractSortingClause.getValue();
assertThat(sortByType.getSortProperty().get(0).getValueReference(),
is(mockTemporalFeatureProperty));
assertThat(sortByType.getSortProperty().get(0).getSortOrder().name(),
is(SortOrderType.ASC.value()));
}
/**
* Verify that the SortBy is NOT set. In this case, sorting is not supported in the capabilities.
*/
@Test
public void testSortingAscendingSortingNotSupported() throws Exception {
// Setup
final String searchPhrase = "*";
final String mockTemporalFeatureProperty = "myTemporalFeatureProperty";
final String mockFeatureType = "{http://example.com}" + SAMPLE_FEATURE_NAME + 0;
final int pageSize = 1;
// Set ImplementsSorting to FALSE (sorting not supported)
FilterCapabilities mockCapabilitiesSortingNotSupported = MockWfsServer
.getFilterCapabilities();
ConformanceType conformance = mockCapabilitiesSortingNotSupported.getConformance();
List<DomainType> domainTypes = conformance.getConstraint();
for (DomainType domainType : domainTypes) {
if (StringUtils.equals(domainType.getName(), "ImplementsSorting")) {
ValueType valueType = new ValueType();
valueType.setValue("FALSE");
domainType.setDefaultValue(valueType);
break;
}
}
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
mockCapabilitiesSortingNotSupported, Wfs20Constants.EPSG_4326_URN, 1, false, false,
0);
MetacardMapper mockMetacardMapper = mock(MetacardMapper.class);
when(mockMetacardMapper.getFeatureType()).thenReturn(mockFeatureType);
when(mockMetacardMapper.getSortByTemporalFeatureProperty())
.thenReturn(mockTemporalFeatureProperty);
List<MetacardMapper> mappers = new ArrayList<MetacardMapper>(1);
mappers.add(mockMetacardMapper);
source.setMetacardToFeatureMapper(mappers);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
SortBy sortBy = new SortByImpl(Result.TEMPORAL, SortOrder.ASCENDING);
query.setSortBy(sortBy);
// Perform Test
GetFeatureType featureType = source.buildGetFeatureRequest(query);
// Verify
QueryType queryType = (QueryType) featureType.getAbstractQueryExpression().get(0)
.getValue();
assertFalse(queryType.isSetAbstractSortingClause());
}
/**
* Verify that the SortBy is NOT set. In this case, there is no mapping for the incoming sort property of TEMPORAL so no SortBy should be set.
*
* <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
* <ns5:GetFeature startIndex="1" count="1" service="WFS" version="2.0.0" xmlns:ns2="http://www.opengis.net/ows/1.1" xmlns="http://www.opengis.net/fes/2.0" xmlns:ns4="http://www.opengis.net/gml" xmlns:ns3="http://www.w3.org/1999/xlink" xmlns:ns5="http://www.opengis.net/wfs/2.0">
* <ns5:Query typeNames="SampleFeature0" handle="SampleFeature0">
* <Filter>
* <PropertyIsLike wildCard="*" singleChar="?" escapeChar="!">
* <Literal>*</Literal>
* <ValueReference>title</ValueReference>
* </PropertyIsLike>
* </Filter>
* </ns5:Query>
* </ns5:GetFeature>
*/
@Test
public void testSortingAscendingNoFeaturePropertyMappingSortingSupported() throws Exception {
// Setup
final String searchPhrase = "*";
final String mockFeatureType = "{http://example.com}" + SAMPLE_FEATURE_NAME + 0;
final int pageSize = 1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 1, false,
false, 0);
MetacardMapper mockMetacardMapper = mock(MetacardMapper.class);
when(mockMetacardMapper.getFeatureType()).thenReturn(mockFeatureType);
List<MetacardMapper> mappers = new ArrayList<MetacardMapper>(1);
mappers.add(mockMetacardMapper);
source.setMetacardToFeatureMapper(mappers);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
SortBy sortBy = new SortByImpl(Result.TEMPORAL, SortOrder.ASCENDING);
query.setSortBy(sortBy);
// Perform Test
GetFeatureType featureType = source.buildGetFeatureRequest(query);
// Verify
QueryType queryType = (QueryType) featureType.getAbstractQueryExpression().get(0)
.getValue();
assertFalse(queryType.isSetAbstractSortingClause());
}
/**
* Verify that the SortBy is set with the mapped Feature Property and a DESC sort order. In this case, the incoming sort property of TEMPORAL is mapped to
* myTemporalFeatureProperty.
*
* <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
* <ns5:GetFeature startIndex="1" count="1" service="WFS" version="2.0.0" xmlns:ns2="http://www.opengis.net/ows/1.1" xmlns="http://www.opengis.net/fes/2.0" xmlns:ns4="http://www.opengis.net/gml" xmlns:ns3="http://www.w3.org/1999/xlink" xmlns:ns5="http://www.opengis.net/wfs/2.0">
* <ns5:Query typeNames="SampleFeature0" handle="SampleFeature0">
* <Filter>
* <PropertyIsLike wildCard="*" singleChar="?" escapeChar="!">
* <Literal>*</Literal>
* <ValueReference>title</ValueReference>
* </PropertyIsLike>
* </Filter>
* <SortBy>
* <SortProperty>
* <ValueReference>myTemporalFeatureProperty</ValueReference>
* <SortOrder>DESC</SortOrder>
* </SortProperty>
* </SortBy>
* </ns5:Query>
* </ns5:GetFeature>
*/
@Test
public void testSortingDescendingSortingSupported() throws Exception {
// Setup
final String searchPhrase = "*";
final String mockTemporalFeatureProperty = "myTemporalFeatureProperty";
final String mockFeatureType = "{http://example.com}" + SAMPLE_FEATURE_NAME + 0;
final int pageSize = 1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 1, false,
false, 0);
MetacardMapper mockMetacardMapper = mock(MetacardMapper.class);
when(mockMetacardMapper.getFeatureType()).thenReturn(mockFeatureType);
when(mockMetacardMapper.getSortByTemporalFeatureProperty())
.thenReturn(mockTemporalFeatureProperty);
List<MetacardMapper> mappers = new ArrayList<MetacardMapper>(1);
mappers.add(mockMetacardMapper);
source.setMetacardToFeatureMapper(mappers);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
SortBy sortBy = new SortByImpl(Result.TEMPORAL, SortOrder.DESCENDING);
query.setSortBy(sortBy);
// Perform Test
GetFeatureType featureType = source.buildGetFeatureRequest(query);
// Verify
QueryType queryType = (QueryType) featureType.getAbstractQueryExpression().get(0)
.getValue();
JAXBElement<?> abstractSortingClause = queryType.getAbstractSortingClause();
SortByType sortByType = (SortByType) abstractSortingClause.getValue();
assertThat(sortByType.getSortProperty().get(0).getValueReference(),
is(mockTemporalFeatureProperty));
assertThat(sortByType.getSortProperty().get(0).getSortOrder().name(),
is(SortOrderType.DESC.value()));
}
@Test
public void testSortingNoSortBySortingSupported() throws Exception {
// Setup
final String searchPhrase = "*";
final int pageSize = 1;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 1, false,
false, 0);
QueryImpl query = new QueryImpl(
builder.attribute(Metacard.ANY_TEXT).is().like().text(searchPhrase));
query.setPageSize(pageSize);
// Perform Test
GetFeatureType featureType = source.buildGetFeatureRequest(query);
// Verify
QueryType queryType = (QueryType) featureType.getAbstractQueryExpression().get(0)
.getValue();
assertFalse(queryType.isSetAbstractSortingClause());
}
@Test
public void testTimeoutConfiguration() throws WfsException {
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 1, false,
false, 0);
source.setConnectionTimeout(10000);
source.setReceiveTimeout(10000);
// Perform test
source.updateTimeouts();
verify(mockWfs, atLeastOnce()).setTimeouts(any(Integer.class), any(Integer.class));
}
@Test
public void testSearchByType() throws Exception {
//Setup
int startIndex = 0;
int pageSize = 10;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 10, false);
Filter filter = builder.attribute(Metacard.CONTENT_TYPE).is().equalTo()
.text(SAMPLE_FEATURE_NAME + "0");
QueryImpl query = new QueryImpl(filter);
query.setPageSize(pageSize);
//Execute
GetFeatureType featureType = source.buildGetFeatureRequest(query);
QueryType queryType = (QueryType) featureType.getAbstractQueryExpression().get(0)
.getValue();
//Validate
assertEquals(SAMPLE_FEATURE_NAME + "0", queryType.getTypeNames().get(0));
}
@Test
public void testSearchByMultipleTypes() throws Exception {
//Setup
int startIndex = 0;
int pageSize = 10;
WfsSource source = getWfsSource(ONE_TEXT_PROPERTY_SCHEMA,
MockWfsServer.getFilterCapabilities(), Wfs20Constants.EPSG_4326_URN, 10, false);
Filter filter0 = builder.attribute(Metacard.CONTENT_TYPE).is().equalTo()
.text(SAMPLE_FEATURE_NAME + "8");
Filter filter1 = builder.attribute(Metacard.CONTENT_TYPE).is().equalTo()
.text(SAMPLE_FEATURE_NAME + "9");
Filter filter2 = builder.attribute(Metacard.ANY_TEXT).is().like().text("*");
Filter typeSearchFilters = builder.anyOf(filter0, filter1);
QueryImpl query = new QueryImpl(builder.allOf(filter2, typeSearchFilters));
query.setPageSize(pageSize);
//Execute
GetFeatureType featureType = source.buildGetFeatureRequest(query);
int numTypes = featureType.getAbstractQueryExpression().size();
//Validate
assertEquals(2, numTypes);
}
}