Skip to content

Commit

Permalink
Adding multi-valued property support, with atmosferic data layer prop…
Browse files Browse the repository at this point in the history
…erties as an example
  • Loading branch information
aaime committed Jul 31, 2018
1 parent 36397d2 commit 97ab230
Show file tree
Hide file tree
Showing 20 changed files with 725 additions and 142 deletions.
14 changes: 14 additions & 0 deletions src/community/oseo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
The tests in these modules are of the "online" kind, they need to connect to an empty
PosgreSQL database with PostGIS support enabled.

The tests will be skipped unless the $HOME/.geoserver/oseo-postgis.properties file is found
and contains information needed to connect to the database, here is an example (replace
all values with your own):

```
user=theUser
port=5432
passwd=thePassword
host=localhost
database=oseo-tests
```
10 changes: 10 additions & 0 deletions src/community/oseo/oseo-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-sample-data</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.geotools.jdbc</groupId>
<artifactId>gt-jdbc-postgis</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymockclassextension</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public Service serviceDispatched(Request request, Service service) throws Servic
// (clients following the template to the letter will create keys with empty value)
for (String key : new HashSet<String>(request.getRawKvp().keySet())) {
Object value = rawKvp.get(key);
if (!(value instanceof String) || StringUtils.isEmpty((String) value)) {
if ((!(value instanceof String) || StringUtils.isEmpty((String) value))
&& !(value instanceof String[])) {
rawKvp.remove(key);
kvp.remove(key);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public SearchRequestKvpReader(GeoServer gs, OpenSearchEoService service) {
super(SearchRequest.class);
this.oseo = service;
this.gs = gs;
setRepeatedParameters(true);
}

@Override
Expand Down Expand Up @@ -551,9 +552,28 @@ private Filter buildEoFilter(Parameter<?> parameter, Object value) {
OpenSearchParameters.getFilterPropertyFor(
gs.getService(OSEOInfo.class), FF, parameter);

if (value instanceof String[]) {
String[] values = (String[]) value;
List<Filter> filters = new ArrayList<>();
for (String v : values) {
Filter filter = buildEOFilterForSingleValue(parameter, v, type, pn);
filters.add(filter);
}
return FF.and(filters);
} else {
return buildEOFilterForSingleValue(parameter, (String) value, type, pn);
}
}

private Filter buildEOFilterForSingleValue(
Parameter<?> parameter, String value, Class<?> type, PropertyName pn) {
// for numeric and range parameters check the range syntax
String input = (String) value;
if (Date.class.isAssignableFrom(type) || Number.class.isAssignableFrom(type)) {
String input = value;
Class target = type;
if (type != null && type.isArray()) {
target = target.getComponentType();
}
if (Date.class.isAssignableFrom(target) || Number.class.isAssignableFrom(target)) {
Matcher matcher;
if ((matcher = FULL_RANGE_PATTERN.matcher(input)).matches()) {
String opening = matcher.group(1);
Expand All @@ -565,21 +585,27 @@ private Filter buildEoFilter(Parameter<?> parameter, Object value) {
Object v1 = parseParameter(parameter, s1);
Object v2 = parseParameter(parameter, s2);

Filter f1, f2;
Literal l1 = FF.literal(v1);
Literal l2 = FF.literal(v2);
if ("[".equals(opening)) {
f1 = FF.greaterOrEqual(pn, l1);
} else {
f1 = FF.greater(pn, l1);
}
if ("]".equals(closing)) {
f2 = FF.lessOrEqual(pn, l2);
if (type.isArray()) {
// cannot express that the same element in the array must be
// at the same time greater than and lower than, fall back on using
// a between filter
return FF.between(pn, FF.literal(v1), FF.literal(v2), MatchAction.ANY);
} else {
f2 = FF.less(pn, l2);
Filter f1, f2;
Literal l1 = FF.literal(v1);
Literal l2 = FF.literal(v2);
if ("[".equals(opening)) {
f1 = FF.greaterOrEqual(pn, l1);
} else {
f1 = FF.greater(pn, l1);
}
if ("]".equals(closing)) {
f2 = FF.lessOrEqual(pn, l2);
} else {
f2 = FF.less(pn, l2);
}
return FF.and(f1, f2);
}

return FF.and(f1, f2);
} else if ((matcher = LEFT_RANGE_PATTERN.matcher(input)).matches()) {
String opening = matcher.group(1);
String s1 = matcher.group(2);
Expand Down Expand Up @@ -633,7 +659,12 @@ private Filter buildEqualityFilter(Parameter<?> parameter, PropertyName pn, Stri
}

private Object parseParameter(Parameter<?> parameter, String value) {
Object converted = Converters.convert(value, parameter.getType(), SAFE_CONVERSION_HINTS);
Class target = parameter.getType();
// for searches on array types
if (target != null && target.isArray()) {
target = target.getComponentType();
}
Object converted = Converters.convert(value, target, SAFE_CONVERSION_HINTS);
if (converted == null) {
throw new OWS20Exception(
"Value '"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -800,9 +800,12 @@ public void modifyFeatures(Name[] attributeNames, Object[] attributeValues, Filt
SimpleFeature sf = (SimpleFeature) f;
for (AttributeDescriptor ad :
linksStore.getSchema().getAttributeDescriptors()) {
fb.set(
ad.getLocalName(),
sf.getAttribute(ad.getLocalName()));
if (sf.getFeatureType().getDescriptor(ad.getLocalName())
!= null) {
fb.set(
ad.getLocalName(),
sf.getAttribute(ad.getLocalName()));
}
}
fb.set(getLinkForeignKey(), id);
SimpleFeature mappedLink = fb.buildFeature(null);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* (c) 2014 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.opensearch.eo;

import java.io.File;
import java.util.Properties;
import junit.framework.TestCase;
import org.geotools.test.FixtureUtilities;

/**
* Static methods to support the implementation of tests that use fixture configuration files. See
* {@link OnlineTestCase} and {@link OnlineTestSupport} for details. This slightly differ from
* org.geotools.test.FixtureUtilities as it points to a different directory. This utilities delegate
* most of its method call to FixtureUtilities except where directory location is concerned. Note:
* Static method cannot be overridden hence this implementation.
*
* @author Victor Tey, CSIRO Earth Science and Resource Engineering
*/
public class GSFixtureUtilitiesDelegate {

/** Load {@link Properties} from a {@link File}. */
public static Properties loadProperties(File file) {
return FixtureUtilities.loadProperties(file);
}

/**
* Return the directory containing GeoServer test fixture configuration files. This is
* ".geoserver" in the user home directory.
*/
public static File getFixtureDirectory() {
return new File(System.getProperty("user.home") + File.separator + ".geoserver");
}

/**
* Return the file that should contain the fixture configuration properties. It is not
* guaranteed to exist.
*
* <p>
*
* Dots "." in the fixture id represent a subdirectory path under the GeoTools configuration
* file directory. For example, an id <code>a.b.foo</code> would be resolved to
* <code>.geotools/a/b/foo.properties<code>.
*
* @param fixtureDirectory
* the base fixture configuration file directory, typically ".geotools" in the user
* home directory.
* @param fixtureId
* the fixture id
*/
public static File getFixtureFile(File fixtureDirectory, String fixtureId) {
return FixtureUtilities.getFixtureFile(fixtureDirectory, fixtureId);
}

/**
* Print a notice that tests are being skipped, identifying the property file whose absence is
* responsible.
*
* @param fixtureId the fixture id
* @param fixtureFile the missing fixture configuration file
*/
public static void printSkipNotice(String fixtureId, File fixtureFile) {
FixtureUtilities.printSkipNotice(fixtureId, fixtureFile);
}

/**
* Return Properties loaded from a fixture configuration file, or null if not found.
*
* <p>If a fixture configuration file is not found, a notice is printed to standard output
* stating that tests for this fixture id are skipped.
*
* <p>This method allows tests that cannot extend {@link OnlineTestCase} or {@link
* OnlineTestSupport} because they already extend another class (for example, a non-online test
* framework) to access fixture configuration files in the same way that those classes do. Only
* basic fixture configuration loading is supported. This method does not support the extra
* services such as fixture caching and connection testing provided by {@link OnlineTestCase}
* and {@link OnlineTestSupport}.
*
* <p>A JUnit 4 test fixture can readily be disabled in the absence of a fixture configuration
* file by placing <code>Assume.assumeNotNull(FixtureUtilities.loadFixture(fixtureId))</code> or
* similar in its <code>@BeforeClass</code> method. JUnit 3 tests must provide their own logic,
* typically overriding {@link TestCase#run()} or {@link TestCase#runTest()}, or providing a
* suite.
*
* @param fixtureId the fixture id, where dots "." are converted to subdirectories.
* @return the fixture Properties or null
* @see OnlineTestCase
* @see OnlineTestSupport
*/
public static Properties loadFixture(String fixtureId) {
File fixtureFile = getFixtureFile(getFixtureDirectory(), fixtureId);
if (fixtureFile.exists()) {
return loadProperties(fixtureFile);
} else {
printSkipNotice(fixtureId, fixtureFile);
return null;
}
}
}

0 comments on commit 97ab230

Please sign in to comment.