This is an automated email from the ASF dual-hosted git repository.
afs pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/main by this push:
new a4ed0f9fb9 Organise GeoSPARQL function tests by function
a4ed0f9fb9 is described below
commit a4ed0f9fb9389e9298d6d131c33bb1c7d21719ef
Author: Edmond Chuc <[email protected]>
AuthorDate: Mon Sep 28 00:41:19 2026 +1000
Organise GeoSPARQL function tests by function
* Split GeoSPARQL geometry metadata function tests
* Split GeoSPARQL coordinate extrema function tests
* Refine GeoSPARQL centroid function tests
* Move GeometryTransformIndexTest alongside other index tests
---
.../filter_functions/CentroidFFTest.java | 25 +-
.../GeometryCoordinateExtremaFFTest.java | 284 ---------------------
.../GeometryMetadataErrorsTest.java | 147 -----------
.../geometry_property/GeometryMetadataFFTest.java | 145 -----------
.../GeometryPropertyFFTestSupport.java | 64 +++++
.../geometry_property/Is3DFFTest.java | 102 ++++++++
.../geometry_property/IsEmptyFFTest.java | 12 +
.../geometry_property/IsMeasuredFFTest.java | 102 ++++++++
.../geometry_property/MaxXFFTest.java | 136 ++++++++++
.../geometry_property/MaxYFFTest.java | 136 ++++++++++
.../geometry_property/MaxZFFTest.java | 130 ++++++++++
.../geometry_property/MinXFFTest.java | 136 ++++++++++
.../geometry_property/MinYFFTest.java | 136 ++++++++++
.../geometry_property/MinZFFTest.java | 130 ++++++++++
.../geometry_property/NumGeometriesFFTest.java | 86 +++++++
.../{ => index}/GeometryTransformIndexTest.java | 4 +-
16 files changed, 1185 insertions(+), 590 deletions(-)
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/nontopological/filter_functions/CentroidFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/nontopological/filter_functions/CentroidFFTest.java
index 685bc33cbc..5274baf007 100644
---
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/nontopological/filter_functions/CentroidFFTest.java
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/nontopological/filter_functions/CentroidFFTest.java
@@ -23,7 +23,6 @@ package
org.apache.jena.geosparql.geof.nontopological.filter_functions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
@@ -34,7 +33,6 @@ import
org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
import
org.apache.jena.geosparql.implementation.jts.CoordinateSequenceDimensions;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
-import org.apache.jena.query.QueryBuildException;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
@@ -114,6 +112,19 @@ public class CentroidFFTest {
assertEquals(300, result.getXYGeometry().getCoordinate().getY(), 0);
}
+ @Test
+ public void directExecutionAcceptsExplicitWktCrs() {
+ NodeValue input = NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/27700> LINESTRING (100
200, 300 400)", WKTDatatype.INSTANCE);
+ NodeValue output = new CentroidFF().exec(input);
+ assertEquals(WKTDatatype.URI, output.asNode().getLiteralDatatypeURI());
+ GeometryWrapper result = GeometryWrapper.extract(output.asNode());
+ assertPointMetadata(result);
+ assertEquals("http://www.opengis.net/def/crs/EPSG/0/27700",
result.getSrsURI());
+ assertEquals(200, result.getXYGeometry().getCoordinate().getX(), 0);
+ assertEquals(300, result.getXYGeometry().getCoordinate().getY(), 0);
+ }
+
@Test
public void geographicCentroidIsPlanar() {
assertCentroid("MULTIPOINT ((170 10), (-170 10))", 0, 10);
@@ -194,16 +205,6 @@ public class CentroidFFTest {
NodeValue.makeNode(NodeFactory.createURI("urn:geometry")),
NodeValue.makeNode("invalid", WKTDatatype.INSTANCE) }) {
assertThrows(ExprEvalException.class, () -> function.exec(value));
}
- for (String value : new String[] { "42", "'POINT (1 2)'",
"<urn:geometry>", "'invalid'^^geo:wktLiteral", "?missing" }) {
- assertNull(evaluate("geof:centroid(" + value + ")"));
- }
- }
-
- @Test
- public void wrongArityIsRejectedAtQueryBuild() {
- assertThrows(QueryBuildException.class, () ->
evaluate("geof:centroid()"));
- assertThrows(QueryBuildException.class,
- () -> evaluate("geof:centroid('POINT
EMPTY'^^geo:wktLiteral, 1)"));
}
private static void assertCentroid(String wkt, double x, double y) {
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryCoordinateExtremaFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryCoordinateExtremaFFTest.java
deleted file mode 100644
index 418893b171..0000000000
---
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryCoordinateExtremaFFTest.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assume.assumeFalse;
-
-import java.util.List;
-
-import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
-import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
-import org.apache.jena.graph.Node;
-import org.apache.jena.graph.NodeFactory;
-import org.apache.jena.query.QueryBuildException;
-import org.apache.jena.query.QueryExecution;
-import org.apache.jena.query.QuerySolution;
-import org.apache.jena.query.ResultSet;
-import org.apache.jena.rdf.model.ModelFactory;
-import org.apache.jena.sparql.expr.ExprEvalException;
-import org.apache.jena.sparql.expr.NodeValue;
-import org.apache.jena.sparql.function.FunctionBase1;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-@RunWith(Parameterized.class)
-public class GeometryCoordinateExtremaFFTest {
- @Parameterized.Parameters(name = "function: {0}")
- public static List<Object[]> functions() {
- return List.of(
- new Object[] { "minX", new MinXFF() },
- new Object[] { "minY", new MinYFF() },
- new Object[] { "minZ", new MinZFF() },
- new Object[] { "maxX", new MaxXFF() },
- new Object[] { "maxY", new MaxYFF() },
- new Object[] { "maxZ", new MaxZFF() }
- );
- }
-
- private final String name;
- private final FunctionBase1 function;
-
- public GeometryCoordinateExtremaFFTest(String name, FunctionBase1
function) {
- this.name = name;
- this.function = function;
- }
-
- @BeforeClass
- public static void setup() {
- GeoSPARQLConfig.setupNoIndex();
- }
-
- @Test
- public void iriArgumentRaisesExpressionError() {
- assertThrows(ExprEvalException.class, () ->
function.exec(NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal"))));
- }
-
- @Test
- public void numericArgumentRaisesExpressionError() {
- assertThrows(ExprEvalException.class, () ->
function.exec(NodeValue.makeInteger(42)));
- }
-
- @Test
- public void stringWithoutGeometryDatatypeRaisesExpressionError() {
- assertThrows(ExprEvalException.class, () ->
function.exec(NodeValue.makeString("POINT (1 2)")));
- }
-
- @Test
- public void malformedWktRaisesExpressionError() {
- NodeValue malformed = NodeValue.makeNode("invalid",
WKTDatatype.INSTANCE);
- assertThrows(ExprEvalException.class, () -> function.exec(malformed));
- }
-
- @Test
- public void iriArgumentLeavesBindUnbound() {
- assertUnbound("<urn:not-a-literal>");
- }
-
- @Test
- public void numericArgumentLeavesBindUnbound() {
- assertUnbound("42");
- }
-
- @Test
- public void stringWithoutGeometryDatatypeLeavesBindUnbound() {
- assertUnbound("'POINT (1 2)'");
- }
-
- @Test
- public void malformedWktLeavesBindUnbound() {
- assertUnbound("'invalid'^^geo:wktLiteral");
- }
-
- @Test
- public void unboundArgumentLeavesBindUnbound() {
- assertUnbound("?missing");
- }
-
- @Test
- public void missingArgumentIsRejectedAtQueryBuild() {
- assertThrows(QueryBuildException.class, () -> evaluate("geof:" + name
+ "()"));
- }
-
- @Test
- public void extraArgumentIsRejectedAtQueryBuild() {
- assertThrows(QueryBuildException.class,
- () -> evaluate("geof:" + name + "('POINT
EMPTY'^^geo:wktLiteral, 1)"));
- }
-
- @Test
- public void extremaReturnDoubleLiterals() {
- double expected = switch (name) {
- case "minX" -> -9;
- case "maxX" -> -2;
- case "minY" -> 3;
- case "maxY" -> 8;
- case "minZ" -> -7;
- case "maxZ" -> -1;
- default -> throw new AssertionError(name);
- };
- assertEquals(NodeValue.makeDouble(expected).asNode(),
- evaluate("geof:" + name + "('LINESTRING ZM (-9 8 -7 100,
-2 3 -1 -100)'^^geo:wktLiteral)"));
- }
-
- @Test
- public void epsg4326LineStringExtremaFollowSrsDimensionOrder() {
- String argument = "'<http://www.opengis.net/def/crs/EPSG/0/4326> "
- + "LINESTRING (10 100, 20 120)'^^geo:wktLiteral";
- if (name.endsWith("Z")) {
- assertUnbound(argument);
- } else {
- double expected = switch (name) {
- case "minX" -> 10;
- case "maxX" -> 20;
- case "minY" -> 100;
- case "maxY" -> 120;
- default -> throw new AssertionError(name);
- };
- assertEquals(NodeValue.makeDouble(expected).asNode(),
- evaluate("geof:" + name + "(" + argument + ")"));
- }
- }
-
- @Test
- public void infiniteOrdinateRaisesExpressionErrorAndLeavesBindUnbound() {
- for (String infinity : new String[] { "Infinity", "-Infinity" }) {
- String coordinate = switch (name.charAt(name.length() - 1)) {
- case 'X' -> infinity + " 1 1";
- case 'Y' -> "1 " + infinity + " 1";
- case 'Z' -> "1 1 " + infinity;
- default -> throw new AssertionError(name);
- };
- String wkt = "LINESTRING Z (-4 -4 -4, " + coordinate + ", 9 9 9)";
- assertThrows(wkt, ExprEvalException.class,
- () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
- assertUnbound("'" + wkt + "'^^geo:wktLiteral");
- }
- }
-
- @Test
- public void nanXYOrdinateRaisesExpressionErrorAndLeavesBindUnbound() {
- assumeFalse("Only X/Y extrema are covered by this test",
name.endsWith("Z"));
- String coordinate = name.endsWith("Y") ? "2 NaN" : "NaN 2";
- String wkt = "LINESTRING (1 1, " + coordinate + ", 3 3)";
- assertThrows(wkt, ExprEvalException.class,
- () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
- assertUnbound("'" + wkt + "'^^geo:wktLiteral");
- }
-
- @Test
- public void emptyGeometryRaisesExpressionErrorAndLeavesBindUnbound() {
- assertThrows(ExprEvalException.class,
- () -> function.exec(NodeValue.makeNode("POINT Z EMPTY",
WKTDatatype.INSTANCE)));
- assertUnbound("'POINT Z EMPTY'^^geo:wktLiteral");
- }
-
- @Test
- public void layoutsWithoutZStillHaveXYExtrema() {
- for (String wkt : new String[] { "POINT (1 2)", "POINT M (1 2 99)" }) {
- if (name.endsWith("Z")) {
- assertThrows(wkt, ExprEvalException.class,
- () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
- assertUnbound("'" + wkt + "'^^geo:wktLiteral");
- } else {
- double expected = name.endsWith("X") ? 1 : 2;
- assertEquals(wkt, NodeValue.makeDouble(expected).asNode(),
- evaluate("geof:" + name + "('" + wkt +
"'^^geo:wktLiteral)"));
- }
- }
- }
-
- @Test
- public void multiPointExtremaDistinguishZFromMeasures() {
- for (boolean hasZ : new boolean[] { false, true }) {
- String wkt = hasZ ? "MULTIPOINT ZM ((1 2 -4 10), (3 4 9 20))"
- : "MULTIPOINT M ((1 2 10), (3 4 20))";
- if (name.endsWith("Z") && !hasZ) {
- assertThrows(ExprEvalException.class,
- () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
- assertUnbound("'" + wkt + "'^^geo:wktLiteral");
- } else {
- double value = switch (name) {
- case "minX" -> 1;
- case "maxX" -> 3;
- case "minY" -> 2;
- case "maxY" -> 4;
- case "minZ" -> -4;
- case "maxZ" -> 9;
- default -> throw new AssertionError(name);
- };
- NodeValue expected = NodeValue.makeDouble(value);
- assertEquals(expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
- assertEquals(expected.asNode(), evaluate("geof:" + name + "('"
+ wkt + "'^^geo:wktLiteral)"));
- }
- }
- }
-
- @Test
- public void mixedCollectionExtremaDoNotDependOnMemberOrder() {
- for (String wkt : new String[] {
- "GEOMETRYCOLLECTION (POINT Z (1 2 3))",
- "GEOMETRYCOLLECTION (POINT (1 2), POINT M (1 2 999), POINT Z
(1 2 3))",
- "GEOMETRYCOLLECTION (POINT Z (1 2 3), POINT M (1 2 999), POINT
(1 2))" }) {
- NodeValue expected = NodeValue.makeDouble(name.endsWith("X") ? 1 :
name.endsWith("Y") ? 2 : 3);
- assertEquals(expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
- assertEquals(expected.asNode(), evaluate("geof:" + name + "('" +
wkt + "'^^geo:wktLiteral)"));
- }
- }
-
- @Test
- public void gmlExtremaFollowSrsDimensionOrder() {
- String point = """
- '<gml:Point xmlns:gml="http://www.opengis.net/gml/3.2"
- srsName="http://www.opengis.net/def/crs/EPSG/0/4979">
- <gml:pos srsDimension="3">10 100 -4</gml:pos>
- </gml:Point>'^^geo:gmlLiteral
- """.replace("\n", " ");
- double expected = name.endsWith("X") ? 10 : name.endsWith("Y") ? 100 :
-4;
- assertEquals(NodeValue.makeDouble(expected).asNode(), evaluate("geof:"
+ name + "(" + point + ")"));
- }
-
- private static Node evaluate(String expression) {
- String query = """
- PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
- PREFIX geo: <http://www.opengis.net/ont/geosparql#>
- SELECT ?result WHERE { BIND(%s AS ?result) }
- """.formatted(expression);
- try (QueryExecution execution = QueryExecution.create(query,
ModelFactory.createDefaultModel())) {
- ResultSet results = execution.execSelect();
- assertTrue("Expected one solution for " + expression,
results.hasNext());
- QuerySolution solution = results.next();
- assertFalse("Expected only one solution for " + expression,
results.hasNext());
- return solution.contains("result") ?
solution.get("result").asNode() : null;
- }
- }
-
- private void assertUnbound(String argument) {
- String expression = "geof:" + name + "(" + argument + ")";
- assertNull(expression, evaluate(expression));
- }
-}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryMetadataErrorsTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryMetadataErrorsTest.java
deleted file mode 100644
index f4f78eb726..0000000000
---
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryMetadataErrorsTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-
-import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
-import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
-import org.apache.jena.graph.Node;
-import org.apache.jena.graph.NodeFactory;
-import org.apache.jena.query.QueryBuildException;
-import org.apache.jena.query.QueryExecution;
-import org.apache.jena.query.QuerySolution;
-import org.apache.jena.query.ResultSet;
-import org.apache.jena.rdf.model.ModelFactory;
-import org.apache.jena.sparql.expr.ExprEvalException;
-import org.apache.jena.sparql.expr.NodeValue;
-import org.apache.jena.sparql.function.FunctionBase1;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-@RunWith(Parameterized.class)
-public class GeometryMetadataErrorsTest {
- @Parameterized.Parameters(name = "function: {0}")
- public static List<Object[]> functions() {
- return List.of(
- new Object[] { "is3D", new Is3DFF() },
- new Object[] { "isMeasured", new IsMeasuredFF() },
- new Object[] { "numGeometries", new NumGeometriesFF() }
- );
- }
-
- private final String name;
- private final FunctionBase1 function;
-
- public GeometryMetadataErrorsTest(String name, FunctionBase1 function) {
- this.name = name;
- this.function = function;
- }
-
- @BeforeClass
- public static void setup() {
- GeoSPARQLConfig.setupNoIndex();
- }
-
- @Test
- public void iriArgumentRaisesExpressionError() {
- assertThrows(ExprEvalException.class, () ->
function.exec(NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal"))));
- }
-
- @Test
- public void numericArgumentRaisesExpressionError() {
- assertThrows(ExprEvalException.class, () ->
function.exec(NodeValue.makeInteger(42)));
- }
-
- @Test
- public void stringWithoutGeometryDatatypeRaisesExpressionError() {
- assertThrows(ExprEvalException.class, () ->
function.exec(NodeValue.makeString("POINT (1 2)")));
- }
-
- @Test
- public void malformedWktRaisesExpressionError() {
- NodeValue malformed = NodeValue.makeNode("invalid",
WKTDatatype.INSTANCE);
- assertThrows(ExprEvalException.class, () -> function.exec(malformed));
- }
-
- @Test
- public void iriArgumentLeavesBindUnbound() {
- assertUnbound("<urn:not-a-literal>");
- }
-
- @Test
- public void numericArgumentLeavesBindUnbound() {
- assertUnbound("42");
- }
-
- @Test
- public void stringWithoutGeometryDatatypeLeavesBindUnbound() {
- assertUnbound("'POINT (1 2)'");
- }
-
- @Test
- public void malformedWktLeavesBindUnbound() {
- assertUnbound("'invalid'^^geo:wktLiteral");
- }
-
- @Test
- public void unboundArgumentLeavesBindUnbound() {
- assertUnbound("?missing");
- }
-
- @Test
- public void missingArgumentIsRejectedAtQueryBuild() {
- assertThrows(QueryBuildException.class, () -> evaluate("geof:" + name
+ "()"));
- }
-
- @Test
- public void extraArgumentIsRejectedAtQueryBuild() {
- assertThrows(QueryBuildException.class,
- () -> evaluate("geof:" + name + "('POINT
EMPTY'^^geo:wktLiteral, 1)"));
- }
-
- private static Node evaluate(String expression) {
- String query = """
- PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
- PREFIX geo: <http://www.opengis.net/ont/geosparql#>
- SELECT ?result WHERE { BIND(%s AS ?result) }
- """.formatted(expression);
- try (QueryExecution execution = QueryExecution.create(query,
ModelFactory.createDefaultModel())) {
- ResultSet results = execution.execSelect();
- assertTrue("Expected one solution for " + expression,
results.hasNext());
- QuerySolution solution = results.next();
- assertFalse("Expected only one solution for " + expression,
results.hasNext());
- return solution.contains("result") ?
solution.get("result").asNode() : null;
- }
- }
-
- private void assertUnbound(String argument) {
- String expression = "geof:" + name + "(" + argument + ")";
- assertNull(expression, evaluate(expression));
- }
-}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryMetadataFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryMetadataFFTest.java
deleted file mode 100644
index e5c3b7d548..0000000000
---
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryMetadataFFTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import org.apache.jena.datatypes.xsd.XSDDatatype;
-import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
-import org.apache.jena.graph.Node;
-import org.apache.jena.graph.NodeFactory;
-import org.apache.jena.query.QueryExecution;
-import org.apache.jena.query.QuerySolution;
-import org.apache.jena.query.ResultSet;
-import org.apache.jena.rdf.model.ModelFactory;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class GeometryMetadataFFTest {
- private static final String PREFIXES = """
- PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
- PREFIX geo: <http://www.opengis.net/ont/geosparql#>
- """;
-
- @BeforeClass
- public static void setup() {
- GeoSPARQLConfig.setupNoIndex();
- }
-
- @Test
- public void is3DDistinguishesZFromM() {
- assertResult("geof:is3D('POINT Z (1 2 3)'^^geo:wktLiteral)", "true",
XSDDatatype.XSDboolean);
- assertResult("geof:is3D('POINT M (1 2 3)'^^geo:wktLiteral)", "false",
XSDDatatype.XSDboolean);
- }
-
- @Test
- public void isMeasuredDistinguishesMFromZ() {
- assertResult("geof:isMeasured('POINT M (1 2 3)'^^geo:wktLiteral)",
"true", XSDDatatype.XSDboolean);
- assertResult("geof:isMeasured('POINT Z (1 2 3)'^^geo:wktLiteral)",
"false", XSDDatatype.XSDboolean);
- }
-
- @Test
- public void emptyPointsRetainZAndMFlags() {
- assertFlags("POINT EMPTY", false, false);
- assertFlags("POINT Z EMPTY", true, false);
- assertFlags("POINT M EMPTY", false, true);
- assertFlags("POINT ZM EMPTY", true, true);
- }
-
- @Test
- public void emptyCollectionsRetainDeclaredZAndMFlags() {
- assertFlags("GEOMETRYCOLLECTION EMPTY", false, false);
- assertFlags("GEOMETRYCOLLECTION Z EMPTY", true, false);
- assertFlags("GEOMETRYCOLLECTION M EMPTY", false, true);
- assertFlags("GEOMETRYCOLLECTION ZM EMPTY", true, true);
- }
-
- @Test
- public void permissiveWktCollectionLayoutDoesNotAggregateMemberLayouts() {
- // Mixed member layouts are a Jena WKT extension, not an SFA
conformance case.
- assertFlags("GEOMETRYCOLLECTION (POINT Z (1 2 3), POINT M (4 5 6))",
false, false);
- }
-
- @Test
- public void numGeometriesCountsMembersAsAnInteger() {
- assertResult("geof:numGeometries('MULTIPOINT ((1 2), (3
4))'^^geo:wktLiteral)",
- "2", XSDDatatype.XSDinteger);
- }
-
- @Test
- public void numGeometriesDistinguishesEmptyAtomsFromCollections() {
- assertResult("geof:numGeometries('POINT EMPTY'^^geo:wktLiteral)", "1",
XSDDatatype.XSDinteger);
- assertResult("geof:numGeometries('GEOMETRYCOLLECTION
EMPTY'^^geo:wktLiteral)", "0", XSDDatatype.XSDinteger);
- assertResult("geof:numGeometries('MULTIPOINT EMPTY'^^geo:wktLiteral)",
"0", XSDDatatype.XSDinteger);
- assertResult("geof:numGeometries('GEOMETRYCOLLECTION (POINT
EMPTY)'^^geo:wktLiteral)",
- "1", XSDDatatype.XSDinteger);
- }
-
- @Test
- public void gmlPointUsesMetadataFunctions() {
- String point = """
- '<gml:Point xmlns:gml="http://www.opengis.net/gml/3.2"
- srsName="http://www.opengis.net/def/crs/OGC/1.3/CRS84">
- <gml:pos>1 2</gml:pos>
- </gml:Point>'^^geo:gmlLiteral
- """.replace("\n", " ");
- assertResult("geof:numGeometries(" + point + ")", "1",
XSDDatatype.XSDinteger);
- assertResult("geof:is3D(" + point + ")", "false",
XSDDatatype.XSDboolean);
- assertResult("geof:isMeasured(" + point + ")", "false",
XSDDatatype.XSDboolean);
- assertResult("geof:isEmpty(" + point + ")", "false",
XSDDatatype.XSDboolean);
- }
-
- @Test
- public void threeDimensionalGmlPointHasZButNoMeasure() {
- String point = """
- '<gml:Point xmlns:gml="http://www.opengis.net/gml/3.2"
- srsName="http://www.opengis.net/def/crs/EPSG/0/4979">
- <gml:pos srsDimension="3">2 1 3</gml:pos>
- </gml:Point>'^^geo:gmlLiteral
- """.replace("\n", " ");
- assertResult("geof:is3D(" + point + ")", "true",
XSDDatatype.XSDboolean);
- assertResult("geof:isMeasured(" + point + ")", "false",
XSDDatatype.XSDboolean);
- assertResult("geof:isEmpty(" + point + ")", "false",
XSDDatatype.XSDboolean);
- }
-
- private static void assertFlags(String wkt, boolean hasZ, boolean hasM) {
- assertResult("geof:is3D('" + wkt + "'^^geo:wktLiteral)",
Boolean.toString(hasZ), XSDDatatype.XSDboolean);
- assertResult("geof:isMeasured('" + wkt + "'^^geo:wktLiteral)",
Boolean.toString(hasM), XSDDatatype.XSDboolean);
- }
-
- private static void assertResult(String expression, String lexicalForm,
XSDDatatype datatype) {
- Node expected = NodeFactory.createLiteralDT(lexicalForm, datatype);
- assertEquals(expression, expected, evaluate(expression));
- }
-
- private static Node evaluate(String expression) {
- String query = PREFIXES + "SELECT ?result WHERE { BIND(" + expression
+ " AS ?result) }";
- try (QueryExecution execution = QueryExecution.create(query,
ModelFactory.createDefaultModel())) {
- ResultSet results = execution.execSelect();
- assertTrue("Expected one solution for " + expression,
results.hasNext());
- QuerySolution solution = results.next();
- assertFalse("Expected only one solution for " + expression,
results.hasNext());
- return solution.contains("result") ?
solution.get("result").asNode() : null;
- }
- }
-}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryPropertyFFTestSupport.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryPropertyFFTestSupport.java
new file mode 100644
index 0000000000..e8346cb140
--- /dev/null
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/GeometryPropertyFFTestSupport.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+
+import org.apache.jena.graph.Node;
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.rdf.model.ModelFactory;
+
+final class GeometryPropertyFFTestSupport {
+ static final String GML_2D_POINT = """
+ '<gml:Point xmlns:gml="http://www.opengis.net/gml/3.2"
+ srsName="http://www.opengis.net/def/crs/OGC/1.3/CRS84">
+ <gml:pos>1 2</gml:pos>
+ </gml:Point>'^^geo:gmlLiteral
+ """.replace("\n", " ");
+
+ static final String GML_3D_POINT = """
+ '<gml:Point xmlns:gml="http://www.opengis.net/gml/3.2"
+ srsName="http://www.opengis.net/def/crs/EPSG/0/4979">
+ <gml:pos srsDimension="3">2 1 3</gml:pos>
+ </gml:Point>'^^geo:gmlLiteral
+ """.replace("\n", " ");
+
+ private GeometryPropertyFFTestSupport() {}
+
+ static String wktArgument(String wkt) {
+ return "'" + wkt + "'^^geo:wktLiteral";
+ }
+
+ static Node evaluate(String expression) {
+ String query = """
+ PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
+ PREFIX geo: <http://www.opengis.net/ont/geosparql#>
+ SELECT ?result WHERE { BIND(%s AS ?result) }
+ """.formatted(expression);
+ try (QueryExecution execution = QueryExecution.create(query,
ModelFactory.createDefaultModel())) {
+ ResultSet results = execution.execSelect();
+ QuerySolution solution = results.next();
+ if (results.hasNext())
+ throw new IllegalStateException("Expected one solution for " +
expression);
+ return solution.contains("result") ?
solution.get("result").asNode() : null;
+ }
+ }
+}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/Is3DFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/Is3DFFTest.java
new file mode 100644
index 0000000000..b4f302f83d
--- /dev/null
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/Is3DFFTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_2D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_3D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.evaluate;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.wktArgument;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
+import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.sparql.expr.ExprEvalException;
+import org.apache.jena.sparql.expr.NodeValue;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class Is3DFFTest {
+ private final Is3DFF function = new Is3DFF();
+
+ @BeforeClass
+ public static void setup() {
+ GeoSPARQLConfig.setupNoIndex();
+ }
+
+ @Test
+ public void directExecutionAcceptsExplicitWktCrs() {
+ NodeValue geometry = NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/27700> POINT Z (1 2 3)",
WKTDatatype.INSTANCE);
+ assertEquals(NodeValue.makeBoolean(true), function.exec(geometry));
+ }
+
+ @Test
+ public void distinguishesZFromM() {
+ assertResult("POINT Z (1 2 3)", true);
+ assertResult("POINT M (1 2 3)", false);
+ }
+
+ @Test
+ public void emptyPointsRetainDeclaredLayout() {
+ assertResult("POINT EMPTY", false);
+ assertResult("POINT Z EMPTY", true);
+ assertResult("POINT M EMPTY", false);
+ assertResult("POINT ZM EMPTY", true);
+ }
+
+ @Test
+ public void emptyCollectionsRetainDeclaredLayout() {
+ assertResult("GEOMETRYCOLLECTION EMPTY", false);
+ assertResult("GEOMETRYCOLLECTION Z EMPTY", true);
+ assertResult("GEOMETRYCOLLECTION M EMPTY", false);
+ assertResult("GEOMETRYCOLLECTION ZM EMPTY", true);
+ }
+
+ @Test
+ public void permissiveWktCollectionDoesNotAggregateMemberLayouts() {
+ // Mixed member layouts are a Jena WKT extension, not an SFA
conformance case.
+ assertResult("GEOMETRYCOLLECTION (POINT Z (1 2 3), POINT M (4 5 6))",
false);
+ }
+
+ @Test
+ public void gmlPointsReportTheirZLayout() {
+ assertEquals(NodeValue.makeBoolean(false).asNode(),
evaluate("geof:is3D(" + GML_2D_POINT + ")"));
+ assertEquals(NodeValue.makeBoolean(true).asNode(),
evaluate("geof:is3D(" + GML_3D_POINT + ")"));
+ }
+
+ @Test
+ public void invalidArgumentsRaiseExpressionErrors() {
+ for (NodeValue value : new NodeValue[] {
+ NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal")),
+ NodeValue.makeInteger(42),
+ NodeValue.makeString("POINT (1 2)"),
+ NodeValue.makeNode("invalid", WKTDatatype.INSTANCE) }) {
+ assertThrows(ExprEvalException.class, () -> function.exec(value));
+ }
+ }
+
+ private static void assertResult(String wkt, boolean expected) {
+ assertEquals(wkt, NodeValue.makeBoolean(expected).asNode(),
+ evaluate("geof:is3D(" + wktArgument(wkt) + ")"));
+ }
+}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/IsEmptyFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/IsEmptyFFTest.java
index fbd7e715f5..817129e8b4 100644
---
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/IsEmptyFFTest.java
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/IsEmptyFFTest.java
@@ -20,6 +20,11 @@
*/
package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_2D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_3D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.evaluate;
+
+import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
import org.apache.jena.sparql.expr.NodeValue;
import org.junit.After;
@@ -40,6 +45,7 @@ public class IsEmptyFFTest {
@BeforeClass
public static void setUpClass() {
+ GeoSPARQLConfig.setupNoIndex();
}
@AfterClass
@@ -80,4 +86,10 @@ public class IsEmptyFFTest {
assertEquals(expResult, result);
}
+ @Test
+ public void gmlPointsAreNotEmpty() {
+ assertEquals(NodeValue.makeBoolean(false).asNode(),
evaluate("geof:isEmpty(" + GML_2D_POINT + ")"));
+ assertEquals(NodeValue.makeBoolean(false).asNode(),
evaluate("geof:isEmpty(" + GML_3D_POINT + ")"));
+ }
+
}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/IsMeasuredFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/IsMeasuredFFTest.java
new file mode 100644
index 0000000000..fe776c0c4c
--- /dev/null
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/IsMeasuredFFTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_2D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_3D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.evaluate;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.wktArgument;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
+import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.sparql.expr.ExprEvalException;
+import org.apache.jena.sparql.expr.NodeValue;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class IsMeasuredFFTest {
+ private final IsMeasuredFF function = new IsMeasuredFF();
+
+ @BeforeClass
+ public static void setup() {
+ GeoSPARQLConfig.setupNoIndex();
+ }
+
+ @Test
+ public void directExecutionAcceptsExplicitWktCrs() {
+ NodeValue geometry = NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/27700> POINT M (1 2 3)",
WKTDatatype.INSTANCE);
+ assertEquals(NodeValue.makeBoolean(true), function.exec(geometry));
+ }
+
+ @Test
+ public void distinguishesMFromZ() {
+ assertResult("POINT M (1 2 3)", true);
+ assertResult("POINT Z (1 2 3)", false);
+ }
+
+ @Test
+ public void emptyPointsRetainDeclaredLayout() {
+ assertResult("POINT EMPTY", false);
+ assertResult("POINT Z EMPTY", false);
+ assertResult("POINT M EMPTY", true);
+ assertResult("POINT ZM EMPTY", true);
+ }
+
+ @Test
+ public void emptyCollectionsRetainDeclaredLayout() {
+ assertResult("GEOMETRYCOLLECTION EMPTY", false);
+ assertResult("GEOMETRYCOLLECTION Z EMPTY", false);
+ assertResult("GEOMETRYCOLLECTION M EMPTY", true);
+ assertResult("GEOMETRYCOLLECTION ZM EMPTY", true);
+ }
+
+ @Test
+ public void permissiveWktCollectionDoesNotAggregateMemberLayouts() {
+ // Mixed member layouts are a Jena WKT extension, not an SFA
conformance case.
+ assertResult("GEOMETRYCOLLECTION (POINT Z (1 2 3), POINT M (4 5 6))",
false);
+ }
+
+ @Test
+ public void gmlPointsAreNotMeasured() {
+ assertEquals(NodeValue.makeBoolean(false).asNode(),
evaluate("geof:isMeasured(" + GML_2D_POINT + ")"));
+ assertEquals(NodeValue.makeBoolean(false).asNode(),
evaluate("geof:isMeasured(" + GML_3D_POINT + ")"));
+ }
+
+ @Test
+ public void invalidArgumentsRaiseExpressionErrors() {
+ for (NodeValue value : new NodeValue[] {
+ NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal")),
+ NodeValue.makeInteger(42),
+ NodeValue.makeString("POINT (1 2)"),
+ NodeValue.makeNode("invalid", WKTDatatype.INSTANCE) }) {
+ assertThrows(ExprEvalException.class, () -> function.exec(value));
+ }
+ }
+
+ private static void assertResult(String wkt, boolean expected) {
+ assertEquals(wkt, NodeValue.makeBoolean(expected).asNode(),
+ evaluate("geof:isMeasured(" + wktArgument(wkt) + ")"));
+ }
+}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MaxXFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MaxXFFTest.java
new file mode 100644
index 0000000000..2596d771a4
--- /dev/null
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MaxXFFTest.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_3D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.evaluate;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.wktArgument;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
+import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.sparql.expr.ExprEvalException;
+import org.apache.jena.sparql.expr.NodeValue;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class MaxXFFTest {
+ private final MaxXFF function = new MaxXFF();
+
+ @BeforeClass
+ public static void setup() {
+ GeoSPARQLConfig.setupNoIndex();
+ }
+
+ @Test
+ public void directExecutionAcceptsExplicitWktCrs() {
+ NodeValue geometry = NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/27700> LINESTRING ZM (-9 8
-7 100, -2 3 -1 -100)",
+ WKTDatatype.INSTANCE);
+ assertEquals(NodeValue.makeDouble(-2), function.exec(geometry));
+ }
+
+ @Test
+ public void returnsDoubleLiteralThroughSparql() {
+ String wkt = "LINESTRING ZM (-9 8 -7 100, -2 3 -1 -100)";
+ assertEquals(NodeValue.makeDouble(-2).asNode(),
+ evaluate("geof:maxX(" + wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void followsSrsDimensionOrder() {
+ String wkt = "<http://www.opengis.net/def/crs/EPSG/0/4326> LINESTRING
(10 100, 20 120)";
+ assertEquals(NodeValue.makeDouble(20).asNode(),
+ evaluate("geof:maxX(" + wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void infiniteOrdinateRaisesExpressionError() {
+ for (String infinity : new String[] { "Infinity", "-Infinity" }) {
+ String wkt = "LINESTRING Z (-4 -4 -4, " + infinity + " 1 1, 9 9
9)";
+ assertThrows(wkt, ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void nanOrdinateRaisesExpressionError() {
+ String wkt = "LINESTRING (1 1, NaN 2, 3 3)";
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void emptyGeometryRaisesExpressionError() {
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode("POINT Z EMPTY",
WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void layoutsWithoutZHaveTheExpectedResult() {
+ for (String wkt : new String[] { "POINT (1 2)", "POINT M (1 2 99)" }) {
+ assertEquals(wkt, NodeValue.makeDouble(1),
+ function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void multiPointExtremaDistinguishZFromMeasures() {
+ for (String wkt : new String[] {
+ "MULTIPOINT M ((1 2 10), (3 4 20))",
+ "MULTIPOINT ZM ((1 2 -4 10), (3 4 9 20))" }) {
+ NodeValue expected = NodeValue.makeDouble(3);
+ assertEquals(wkt, expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(wkt, expected.asNode(), evaluate("geof:maxX(" +
wktArgument(wkt) + ")"));
+ }
+ }
+
+ @Test
+ public void mixedCollectionExtremaDoNotDependOnMemberOrder() {
+ for (String wkt : new String[] {
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3))",
+ "GEOMETRYCOLLECTION (POINT (1 2), POINT M (1 2 999), POINT Z
(1 2 3))",
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3), POINT M (1 2 999), POINT
(1 2))" }) {
+ NodeValue expected = NodeValue.makeDouble(1);
+ assertEquals(wkt, expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(wkt, expected.asNode(), evaluate("geof:maxX(" +
wktArgument(wkt) + ")"));
+ }
+ }
+
+ @Test
+ public void gmlExtremaFollowSrsDimensionOrder() {
+ assertEquals(NodeValue.makeDouble(2).asNode(),
+ evaluate("geof:maxX(" + GML_3D_POINT + ")"));
+ }
+
+ @Test
+ public void invalidArgumentsRaiseExpressionErrors() {
+ for (NodeValue value : new NodeValue[] {
+ NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal")),
+ NodeValue.makeInteger(42),
+ NodeValue.makeString("POINT (1 2)"),
+ NodeValue.makeNode("invalid", WKTDatatype.INSTANCE) }) {
+ assertThrows(ExprEvalException.class, () -> function.exec(value));
+ }
+ }
+}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MaxYFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MaxYFFTest.java
new file mode 100644
index 0000000000..dc7f204efd
--- /dev/null
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MaxYFFTest.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_3D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.evaluate;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.wktArgument;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
+import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.sparql.expr.ExprEvalException;
+import org.apache.jena.sparql.expr.NodeValue;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class MaxYFFTest {
+ private final MaxYFF function = new MaxYFF();
+
+ @BeforeClass
+ public static void setup() {
+ GeoSPARQLConfig.setupNoIndex();
+ }
+
+ @Test
+ public void directExecutionAcceptsExplicitWktCrs() {
+ NodeValue geometry = NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/27700> LINESTRING ZM (-9 8
-7 100, -2 3 -1 -100)",
+ WKTDatatype.INSTANCE);
+ assertEquals(NodeValue.makeDouble(8), function.exec(geometry));
+ }
+
+ @Test
+ public void returnsDoubleLiteralThroughSparql() {
+ String wkt = "LINESTRING ZM (-9 8 -7 100, -2 3 -1 -100)";
+ assertEquals(NodeValue.makeDouble(8).asNode(),
+ evaluate("geof:maxY(" + wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void followsSrsDimensionOrder() {
+ String wkt = "<http://www.opengis.net/def/crs/EPSG/0/4326> LINESTRING
(10 100, 20 120)";
+ assertEquals(NodeValue.makeDouble(120).asNode(),
+ evaluate("geof:maxY(" + wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void infiniteOrdinateRaisesExpressionError() {
+ for (String infinity : new String[] { "Infinity", "-Infinity" }) {
+ String wkt = "LINESTRING Z (-4 -4 -4, " + "1 " + infinity + " 1, 9
9 9)";
+ assertThrows(wkt, ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void nanOrdinateRaisesExpressionError() {
+ String wkt = "LINESTRING (1 1, 2 NaN, 3 3)";
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void emptyGeometryRaisesExpressionError() {
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode("POINT Z EMPTY",
WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void layoutsWithoutZHaveTheExpectedResult() {
+ for (String wkt : new String[] { "POINT (1 2)", "POINT M (1 2 99)" }) {
+ assertEquals(wkt, NodeValue.makeDouble(2),
+ function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void multiPointExtremaDistinguishZFromMeasures() {
+ for (String wkt : new String[] {
+ "MULTIPOINT M ((1 2 10), (3 4 20))",
+ "MULTIPOINT ZM ((1 2 -4 10), (3 4 9 20))" }) {
+ NodeValue expected = NodeValue.makeDouble(4);
+ assertEquals(wkt, expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(wkt, expected.asNode(), evaluate("geof:maxY(" +
wktArgument(wkt) + ")"));
+ }
+ }
+
+ @Test
+ public void mixedCollectionExtremaDoNotDependOnMemberOrder() {
+ for (String wkt : new String[] {
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3))",
+ "GEOMETRYCOLLECTION (POINT (1 2), POINT M (1 2 999), POINT Z
(1 2 3))",
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3), POINT M (1 2 999), POINT
(1 2))" }) {
+ NodeValue expected = NodeValue.makeDouble(2);
+ assertEquals(wkt, expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(wkt, expected.asNode(), evaluate("geof:maxY(" +
wktArgument(wkt) + ")"));
+ }
+ }
+
+ @Test
+ public void gmlExtremaFollowSrsDimensionOrder() {
+ assertEquals(NodeValue.makeDouble(1).asNode(),
+ evaluate("geof:maxY(" + GML_3D_POINT + ")"));
+ }
+
+ @Test
+ public void invalidArgumentsRaiseExpressionErrors() {
+ for (NodeValue value : new NodeValue[] {
+ NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal")),
+ NodeValue.makeInteger(42),
+ NodeValue.makeString("POINT (1 2)"),
+ NodeValue.makeNode("invalid", WKTDatatype.INSTANCE) }) {
+ assertThrows(ExprEvalException.class, () -> function.exec(value));
+ }
+ }
+}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MaxZFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MaxZFFTest.java
new file mode 100644
index 0000000000..8a8162726b
--- /dev/null
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MaxZFFTest.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_3D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.evaluate;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.wktArgument;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
+import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.sparql.expr.ExprEvalException;
+import org.apache.jena.sparql.expr.NodeValue;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class MaxZFFTest {
+ private final MaxZFF function = new MaxZFF();
+
+ @BeforeClass
+ public static void setup() {
+ GeoSPARQLConfig.setupNoIndex();
+ }
+
+ @Test
+ public void directExecutionAcceptsExplicitWktCrs() {
+ NodeValue geometry = NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/27700> LINESTRING ZM (-9 8
-7 100, -2 3 -1 -100)",
+ WKTDatatype.INSTANCE);
+ assertEquals(NodeValue.makeDouble(-1), function.exec(geometry));
+ }
+
+ @Test
+ public void returnsDoubleLiteralThroughSparql() {
+ String wkt = "LINESTRING ZM (-9 8 -7 100, -2 3 -1 -100)";
+ assertEquals(NodeValue.makeDouble(-1).asNode(),
+ evaluate("geof:maxZ(" + wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void followsSrsDimensionOrder() {
+ String wkt = "<http://www.opengis.net/def/crs/EPSG/0/4979> LINESTRING
Z (10 100 -4, 20 120 9)";
+ assertEquals(NodeValue.makeDouble(9).asNode(),
+ evaluate("geof:maxZ(" + wktArgument(wkt) + ")"));
+ assertThrows(ExprEvalException.class, () ->
function.exec(NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/4326> LINESTRING (10 100,
20 120)", WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void infiniteOrdinateRaisesExpressionError() {
+ for (String infinity : new String[] { "Infinity", "-Infinity" }) {
+ String wkt = "LINESTRING Z (-4 -4 -4, " + "1 1 " + infinity + ", 9
9 9)";
+ assertThrows(wkt, ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void emptyGeometryRaisesExpressionError() {
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode("POINT Z EMPTY",
WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void layoutsWithoutZHaveTheExpectedResult() {
+ for (String wkt : new String[] { "POINT (1 2)", "POINT M (1 2 99)" }) {
+ assertThrows(wkt, ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void multiPointExtremaDistinguishZFromMeasures() {
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode("MULTIPOINT M ((1
2 10), (3 4 20))", WKTDatatype.INSTANCE)));
+ String wkt = "MULTIPOINT ZM ((1 2 -4 10), (3 4 9 20))";
+ NodeValue expected = NodeValue.makeDouble(9);
+ assertEquals(expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(expected.asNode(), evaluate("geof:maxZ(" +
wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void mixedCollectionExtremaDoNotDependOnMemberOrder() {
+ for (String wkt : new String[] {
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3))",
+ "GEOMETRYCOLLECTION (POINT (1 2), POINT M (1 2 999), POINT Z
(1 2 3))",
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3), POINT M (1 2 999), POINT
(1 2))" }) {
+ NodeValue expected = NodeValue.makeDouble(3);
+ assertEquals(wkt, expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(wkt, expected.asNode(), evaluate("geof:maxZ(" +
wktArgument(wkt) + ")"));
+ }
+ }
+
+ @Test
+ public void gmlExtremaFollowSrsDimensionOrder() {
+ assertEquals(NodeValue.makeDouble(3).asNode(),
+ evaluate("geof:maxZ(" + GML_3D_POINT + ")"));
+ }
+
+ @Test
+ public void invalidArgumentsRaiseExpressionErrors() {
+ for (NodeValue value : new NodeValue[] {
+ NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal")),
+ NodeValue.makeInteger(42),
+ NodeValue.makeString("POINT (1 2)"),
+ NodeValue.makeNode("invalid", WKTDatatype.INSTANCE) }) {
+ assertThrows(ExprEvalException.class, () -> function.exec(value));
+ }
+ }
+}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MinXFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MinXFFTest.java
new file mode 100644
index 0000000000..1ee4ce8481
--- /dev/null
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MinXFFTest.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_3D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.evaluate;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.wktArgument;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
+import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.sparql.expr.ExprEvalException;
+import org.apache.jena.sparql.expr.NodeValue;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class MinXFFTest {
+ private final MinXFF function = new MinXFF();
+
+ @BeforeClass
+ public static void setup() {
+ GeoSPARQLConfig.setupNoIndex();
+ }
+
+ @Test
+ public void directExecutionAcceptsExplicitWktCrs() {
+ NodeValue geometry = NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/27700> LINESTRING ZM (-9 8
-7 100, -2 3 -1 -100)",
+ WKTDatatype.INSTANCE);
+ assertEquals(NodeValue.makeDouble(-9), function.exec(geometry));
+ }
+
+ @Test
+ public void returnsDoubleLiteralThroughSparql() {
+ String wkt = "LINESTRING ZM (-9 8 -7 100, -2 3 -1 -100)";
+ assertEquals(NodeValue.makeDouble(-9).asNode(),
+ evaluate("geof:minX(" + wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void followsSrsDimensionOrder() {
+ String wkt = "<http://www.opengis.net/def/crs/EPSG/0/4326> LINESTRING
(10 100, 20 120)";
+ assertEquals(NodeValue.makeDouble(10).asNode(),
+ evaluate("geof:minX(" + wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void infiniteOrdinateRaisesExpressionError() {
+ for (String infinity : new String[] { "Infinity", "-Infinity" }) {
+ String wkt = "LINESTRING Z (-4 -4 -4, " + infinity + " 1 1, 9 9
9)";
+ assertThrows(wkt, ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void nanOrdinateRaisesExpressionError() {
+ String wkt = "LINESTRING (1 1, NaN 2, 3 3)";
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void emptyGeometryRaisesExpressionError() {
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode("POINT Z EMPTY",
WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void layoutsWithoutZHaveTheExpectedResult() {
+ for (String wkt : new String[] { "POINT (1 2)", "POINT M (1 2 99)" }) {
+ assertEquals(wkt, NodeValue.makeDouble(1),
+ function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void multiPointExtremaDistinguishZFromMeasures() {
+ for (String wkt : new String[] {
+ "MULTIPOINT M ((1 2 10), (3 4 20))",
+ "MULTIPOINT ZM ((1 2 -4 10), (3 4 9 20))" }) {
+ NodeValue expected = NodeValue.makeDouble(1);
+ assertEquals(wkt, expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(wkt, expected.asNode(), evaluate("geof:minX(" +
wktArgument(wkt) + ")"));
+ }
+ }
+
+ @Test
+ public void mixedCollectionExtremaDoNotDependOnMemberOrder() {
+ for (String wkt : new String[] {
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3))",
+ "GEOMETRYCOLLECTION (POINT (1 2), POINT M (1 2 999), POINT Z
(1 2 3))",
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3), POINT M (1 2 999), POINT
(1 2))" }) {
+ NodeValue expected = NodeValue.makeDouble(1);
+ assertEquals(wkt, expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(wkt, expected.asNode(), evaluate("geof:minX(" +
wktArgument(wkt) + ")"));
+ }
+ }
+
+ @Test
+ public void gmlExtremaFollowSrsDimensionOrder() {
+ assertEquals(NodeValue.makeDouble(2).asNode(),
+ evaluate("geof:minX(" + GML_3D_POINT + ")"));
+ }
+
+ @Test
+ public void invalidArgumentsRaiseExpressionErrors() {
+ for (NodeValue value : new NodeValue[] {
+ NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal")),
+ NodeValue.makeInteger(42),
+ NodeValue.makeString("POINT (1 2)"),
+ NodeValue.makeNode("invalid", WKTDatatype.INSTANCE) }) {
+ assertThrows(ExprEvalException.class, () -> function.exec(value));
+ }
+ }
+}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MinYFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MinYFFTest.java
new file mode 100644
index 0000000000..1842420c7c
--- /dev/null
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MinYFFTest.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_3D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.evaluate;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.wktArgument;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
+import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.sparql.expr.ExprEvalException;
+import org.apache.jena.sparql.expr.NodeValue;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class MinYFFTest {
+ private final MinYFF function = new MinYFF();
+
+ @BeforeClass
+ public static void setup() {
+ GeoSPARQLConfig.setupNoIndex();
+ }
+
+ @Test
+ public void directExecutionAcceptsExplicitWktCrs() {
+ NodeValue geometry = NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/27700> LINESTRING ZM (-9 8
-7 100, -2 3 -1 -100)",
+ WKTDatatype.INSTANCE);
+ assertEquals(NodeValue.makeDouble(3), function.exec(geometry));
+ }
+
+ @Test
+ public void returnsDoubleLiteralThroughSparql() {
+ String wkt = "LINESTRING ZM (-9 8 -7 100, -2 3 -1 -100)";
+ assertEquals(NodeValue.makeDouble(3).asNode(),
+ evaluate("geof:minY(" + wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void followsSrsDimensionOrder() {
+ String wkt = "<http://www.opengis.net/def/crs/EPSG/0/4326> LINESTRING
(10 100, 20 120)";
+ assertEquals(NodeValue.makeDouble(100).asNode(),
+ evaluate("geof:minY(" + wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void infiniteOrdinateRaisesExpressionError() {
+ for (String infinity : new String[] { "Infinity", "-Infinity" }) {
+ String wkt = "LINESTRING Z (-4 -4 -4, " + "1 " + infinity + " 1, 9
9 9)";
+ assertThrows(wkt, ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void nanOrdinateRaisesExpressionError() {
+ String wkt = "LINESTRING (1 1, 2 NaN, 3 3)";
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void emptyGeometryRaisesExpressionError() {
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode("POINT Z EMPTY",
WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void layoutsWithoutZHaveTheExpectedResult() {
+ for (String wkt : new String[] { "POINT (1 2)", "POINT M (1 2 99)" }) {
+ assertEquals(wkt, NodeValue.makeDouble(2),
+ function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void multiPointExtremaDistinguishZFromMeasures() {
+ for (String wkt : new String[] {
+ "MULTIPOINT M ((1 2 10), (3 4 20))",
+ "MULTIPOINT ZM ((1 2 -4 10), (3 4 9 20))" }) {
+ NodeValue expected = NodeValue.makeDouble(2);
+ assertEquals(wkt, expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(wkt, expected.asNode(), evaluate("geof:minY(" +
wktArgument(wkt) + ")"));
+ }
+ }
+
+ @Test
+ public void mixedCollectionExtremaDoNotDependOnMemberOrder() {
+ for (String wkt : new String[] {
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3))",
+ "GEOMETRYCOLLECTION (POINT (1 2), POINT M (1 2 999), POINT Z
(1 2 3))",
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3), POINT M (1 2 999), POINT
(1 2))" }) {
+ NodeValue expected = NodeValue.makeDouble(2);
+ assertEquals(wkt, expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(wkt, expected.asNode(), evaluate("geof:minY(" +
wktArgument(wkt) + ")"));
+ }
+ }
+
+ @Test
+ public void gmlExtremaFollowSrsDimensionOrder() {
+ assertEquals(NodeValue.makeDouble(1).asNode(),
+ evaluate("geof:minY(" + GML_3D_POINT + ")"));
+ }
+
+ @Test
+ public void invalidArgumentsRaiseExpressionErrors() {
+ for (NodeValue value : new NodeValue[] {
+ NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal")),
+ NodeValue.makeInteger(42),
+ NodeValue.makeString("POINT (1 2)"),
+ NodeValue.makeNode("invalid", WKTDatatype.INSTANCE) }) {
+ assertThrows(ExprEvalException.class, () -> function.exec(value));
+ }
+ }
+}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MinZFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MinZFFTest.java
new file mode 100644
index 0000000000..600a86bf31
--- /dev/null
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/MinZFFTest.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_3D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.evaluate;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.wktArgument;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
+import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.sparql.expr.ExprEvalException;
+import org.apache.jena.sparql.expr.NodeValue;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class MinZFFTest {
+ private final MinZFF function = new MinZFF();
+
+ @BeforeClass
+ public static void setup() {
+ GeoSPARQLConfig.setupNoIndex();
+ }
+
+ @Test
+ public void directExecutionAcceptsExplicitWktCrs() {
+ NodeValue geometry = NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/27700> LINESTRING ZM (-9 8
-7 100, -2 3 -1 -100)",
+ WKTDatatype.INSTANCE);
+ assertEquals(NodeValue.makeDouble(-7), function.exec(geometry));
+ }
+
+ @Test
+ public void returnsDoubleLiteralThroughSparql() {
+ String wkt = "LINESTRING ZM (-9 8 -7 100, -2 3 -1 -100)";
+ assertEquals(NodeValue.makeDouble(-7).asNode(),
+ evaluate("geof:minZ(" + wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void followsSrsDimensionOrder() {
+ String wkt = "<http://www.opengis.net/def/crs/EPSG/0/4979> LINESTRING
Z (10 100 -4, 20 120 9)";
+ assertEquals(NodeValue.makeDouble(-4).asNode(),
+ evaluate("geof:minZ(" + wktArgument(wkt) + ")"));
+ assertThrows(ExprEvalException.class, () ->
function.exec(NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/4326> LINESTRING (10 100,
20 120)", WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void infiniteOrdinateRaisesExpressionError() {
+ for (String infinity : new String[] { "Infinity", "-Infinity" }) {
+ String wkt = "LINESTRING Z (-4 -4 -4, " + "1 1 " + infinity + ", 9
9 9)";
+ assertThrows(wkt, ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void emptyGeometryRaisesExpressionError() {
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode("POINT Z EMPTY",
WKTDatatype.INSTANCE)));
+ }
+
+ @Test
+ public void layoutsWithoutZHaveTheExpectedResult() {
+ for (String wkt : new String[] { "POINT (1 2)", "POINT M (1 2 99)" }) {
+ assertThrows(wkt, ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ }
+ }
+
+ @Test
+ public void multiPointExtremaDistinguishZFromMeasures() {
+ assertThrows(ExprEvalException.class,
+ () -> function.exec(NodeValue.makeNode("MULTIPOINT M ((1
2 10), (3 4 20))", WKTDatatype.INSTANCE)));
+ String wkt = "MULTIPOINT ZM ((1 2 -4 10), (3 4 9 20))";
+ NodeValue expected = NodeValue.makeDouble(-4);
+ assertEquals(expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(expected.asNode(), evaluate("geof:minZ(" +
wktArgument(wkt) + ")"));
+ }
+
+ @Test
+ public void mixedCollectionExtremaDoNotDependOnMemberOrder() {
+ for (String wkt : new String[] {
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3))",
+ "GEOMETRYCOLLECTION (POINT (1 2), POINT M (1 2 999), POINT Z
(1 2 3))",
+ "GEOMETRYCOLLECTION (POINT Z (1 2 3), POINT M (1 2 999), POINT
(1 2))" }) {
+ NodeValue expected = NodeValue.makeDouble(3);
+ assertEquals(wkt, expected, function.exec(NodeValue.makeNode(wkt,
WKTDatatype.INSTANCE)));
+ assertEquals(wkt, expected.asNode(), evaluate("geof:minZ(" +
wktArgument(wkt) + ")"));
+ }
+ }
+
+ @Test
+ public void gmlExtremaFollowSrsDimensionOrder() {
+ assertEquals(NodeValue.makeDouble(3).asNode(),
+ evaluate("geof:minZ(" + GML_3D_POINT + ")"));
+ }
+
+ @Test
+ public void invalidArgumentsRaiseExpressionErrors() {
+ for (NodeValue value : new NodeValue[] {
+ NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal")),
+ NodeValue.makeInteger(42),
+ NodeValue.makeString("POINT (1 2)"),
+ NodeValue.makeNode("invalid", WKTDatatype.INSTANCE) }) {
+ assertThrows(ExprEvalException.class, () -> function.exec(value));
+ }
+ }
+}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/NumGeometriesFFTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/NumGeometriesFFTest.java
new file mode 100644
index 0000000000..1d20c45714
--- /dev/null
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/geof/topological/filter_functions/geometry_property/NumGeometriesFFTest.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property;
+
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.GML_2D_POINT;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.evaluate;
+import static
org.apache.jena.geosparql.geof.topological.filter_functions.geometry_property.GeometryPropertyFFTestSupport.wktArgument;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
+import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.sparql.expr.ExprEvalException;
+import org.apache.jena.sparql.expr.NodeValue;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class NumGeometriesFFTest {
+ private final NumGeometriesFF function = new NumGeometriesFF();
+
+ @BeforeClass
+ public static void setup() {
+ GeoSPARQLConfig.setupNoIndex();
+ }
+
+ @Test
+ public void directExecutionAcceptsExplicitWktCrs() {
+ NodeValue geometry = NodeValue.makeNode(
+ "<http://www.opengis.net/def/crs/EPSG/0/27700> POINT (1 2)",
WKTDatatype.INSTANCE);
+ assertEquals(NodeValue.makeInteger(1), function.exec(geometry));
+ }
+
+ @Test
+ public void countsMembersAsAnInteger() {
+ assertResult("MULTIPOINT ((1 2), (3 4))", 2);
+ }
+
+ @Test
+ public void distinguishesAtomsFromCollections() {
+ assertResult("POINT (1 2)", 1);
+ assertResult("POINT EMPTY", 1);
+ assertResult("GEOMETRYCOLLECTION EMPTY", 0);
+ assertResult("MULTIPOINT EMPTY", 0);
+ assertResult("GEOMETRYCOLLECTION (POINT EMPTY)", 1);
+ }
+
+ @Test
+ public void gmlPointCountsAsOne() {
+ assertEquals(NodeValue.makeInteger(1).asNode(),
evaluate("geof:numGeometries(" + GML_2D_POINT + ")"));
+ }
+
+ @Test
+ public void invalidArgumentsRaiseExpressionErrors() {
+ for (NodeValue value : new NodeValue[] {
+ NodeValue.makeNode(NodeFactory.createURI("urn:not-a-literal")),
+ NodeValue.makeInteger(42),
+ NodeValue.makeString("POINT (1 2)"),
+ NodeValue.makeNode("invalid", WKTDatatype.INSTANCE) }) {
+ assertThrows(ExprEvalException.class, () -> function.exec(value));
+ }
+ }
+
+ private static void assertResult(String wkt, int expected) {
+ assertEquals(wkt, NodeValue.makeInteger(expected).asNode(),
+ evaluate("geof:numGeometries(" + wktArgument(wkt) + ")"));
+ }
+}
diff --git
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/GeometryTransformIndexTest.java
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/index/GeometryTransformIndexTest.java
similarity index 95%
rename from
jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/GeometryTransformIndexTest.java
rename to
jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/index/GeometryTransformIndexTest.java
index 434f2711dc..6ff237bd42 100644
---
a/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/GeometryTransformIndexTest.java
+++
b/jena-geosparql/src/test/java/org/apache/jena/geosparql/implementation/index/GeometryTransformIndexTest.java
@@ -18,14 +18,14 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
-package org.apache.jena.geosparql.implementation;
+package org.apache.jena.geosparql.implementation.index;
import static org.junit.Assert.assertEquals;
import org.apache.jena.geosparql.configuration.GeoSPARQLConfig;
+import org.apache.jena.geosparql.implementation.GeometryWrapper;
import org.apache.jena.geosparql.implementation.datatype.GMLDatatype;
import org.apache.jena.geosparql.implementation.datatype.WKTDatatype;
-import org.apache.jena.geosparql.implementation.index.GeometryTransformIndex;
import org.junit.Test;
public class GeometryTransformIndexTest {