You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2024/06/01 10:55:16 UTC
(sis) branch main updated (c1009799e7 -> 6e63051a6f)
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/sis.git
from c1009799e7 Merge branch 'geoapi-3.1'. This is mostly about changing the type of `TemporalDatum.origin` to `java.time`, at least internally.
add 8b0191c652 More dynamic and more efficient comparisons of temporal values depending on their type. This is required by the change of period beginning/ending times to `Temporal`. This work duplicates work already done in `ComparisonFilter`, but the latter will need to be refactored in order to delegate to the new temporal filters.
add e7195efe6b Enable temporal tests which were disabled because of the lack of `sis-temporal` module. This change requires more extensive usage of `java.time` objects in metadata fields.
add 8924c14a5c Replace call to `LocalDate.parse(String)` by `LocalDate.of(year, month, day)` in tests.
add 5458f8dedf Merge branch 'geoapi-4.0' into geoapi-3.1. The main work is a generalization from `Instant` to `Temporal`.
add 51124b9153 Change the `serialVersionUID` of `DefaultCitation` because the following properties are of different types: - citedResponsibleParties (Collection<ResponsibleParty> instead of Collection<Responsibility>) - otherCitationDetails (InternationalString instead of Collection<InternationalString>)
new 6e63051a6f Merge branch 'geoapi-3.1'
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../org/apache/sis/filter/ComparisonFilter.java | 4 +
.../apache/sis/filter/DefaultFilterFactory.java | 55 +-
.../main/org/apache/sis/filter/TemporalFilter.java | 811 ++++-----------------
.../org/apache/sis/filter/TemporalOperation.java | 762 +++++++++++++++++++
.../main/org/apache/sis/filter/TimeMethods.java | 393 ++++++++++
.../geoapi/filter/TemporalOperatorName.java | 4 +
.../org/apache/sis/filter/TemporalFilterTest.java | 23 +-
.../org.apache.sis.metadata/main/module-info.java | 1 +
.../sis/metadata/iso/acquisition/DefaultEvent.java | 9 +-
.../iso/acquisition/DefaultRequestedDate.java | 36 +-
.../iso/acquisition/DefaultRequirement.java | 23 +-
.../sis/metadata/iso/citation/DefaultCitation.java | 23 +-
.../metadata/iso/citation/DefaultCitationDate.java | 11 +-
.../distribution/DefaultStandardOrderProcess.java | 20 +-
.../metadata/iso/extent/DefaultTemporalExtent.java | 40 +-
.../apache/sis/metadata/iso/extent/Extents.java | 95 ++-
.../metadata/iso/identification/DefaultUsage.java | 23 +-
.../sis/metadata/privy/ImplementationHelper.java | 23 -
.../apache/sis/pending/temporal/DefaultPeriod.java | 12 +-
.../sis/pending/temporal/TemporalUtilities.java | 39 +-
.../org/apache/sis/xml/bind/gco/GO_DateTime.java | 3 +-
.../org/apache/sis/xml/bind/gml/TM_Primitive.java | 43 +-
.../apache/sis/xml/bind/gml/TemporalAdapter.java | 4 +-
.../org/apache/sis/xml/bind/gml/TimeInstant.java | 20 +-
.../apache/sis/xml/bind/gml/TimePeriodBound.java | 6 +-
.../org/apache/sis/xml/privy/XmlUtilities.java | 52 +-
.../sis/metadata/iso/extent/DefaultExtentTest.java | 15 +-
.../metadata/privy/ImplementationHelperTest.java | 19 -
.../org/apache/sis/metadata/xml/2007/Extent.xml | 2 -
.../org/apache/sis/metadata/xml/2016/Extent.xml | 2 -
.../apache/sis/xml/bind/gml/TimePeriodTest.java | 19 +-
.../org/apache/sis/xml/privy/XmlUtilitiesTest.java | 12 +-
.../test/org/apache/sis/xml/test/TestCase.java | 33 -
.../sis/referencing/gazetteer/LocationFormat.java | 7 +-
.../main/org/apache/sis/io/wkt/Formatter.java | 12 +-
.../apache/sis/io/wkt/GeodeticObjectParser.java | 3 +-
.../sis/referencing/datum/AbstractDatum.java | 3 +-
.../referencing/datum/DefaultGeodeticDatum.java | 4 +-
.../org/apache/sis/referencing/internal/Epoch.java | 6 +-
.../sis/referencing/privy/ExtentSelector.java | 101 +--
.../referencing/AbstractReferenceSystemTest.java | 9 +-
.../datum/DefaultGeodeticDatumTest.java | 3 +-
.../sis/referencing/privy/ExtentSelectorTest.java | 5 +-
.../apache/sis/test/integration/MetadataTest.java | 29 +-
.../sis/test/integration/MetadataVerticalTest.java | 10 +-
.../storage/geotiff/reader/XMLMetadataTest.java | 2 +-
.../apache/sis/storage/base/MetadataBuilder.java | 3 +-
.../apache/sis/pending/geoapi/temporal/Period.java | 6 +-
.../main/org/apache/sis/util/Classes.java | 20 +-
.../org/apache/sis/util/privy/TemporalDate.java | 113 ++-
.../main/org/apache/sis/util/resources/Errors.java | 5 +
.../apache/sis/util/resources/Errors.properties | 1 +
.../apache/sis/util/resources/Errors_fr.properties | 1 +
.../org/apache/sis/measure/RangeFormatTest.java | 8 +-
.../test/org/apache/sis/test/TestUtilities.java | 4 +-
.../sis/gui/metadata/IdentificationInfo.java | 9 +-
56 files changed, 1841 insertions(+), 1160 deletions(-)
create mode 100644 endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalOperation.java
create mode 100644 endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TimeMethods.java
(sis) 01/01: Merge branch 'geoapi-3.1'
Posted by de...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sis.git
commit 6e63051a6fef034289bf1a562837084075d4f802
Merge: c1009799e7 51124b9153
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Sat Jun 1 00:11:11 2024 +0200
Merge branch 'geoapi-3.1'
.../org/apache/sis/filter/ComparisonFilter.java | 4 +
.../apache/sis/filter/DefaultFilterFactory.java | 55 +-
.../main/org/apache/sis/filter/TemporalFilter.java | 811 ++++-----------------
.../org/apache/sis/filter/TemporalOperation.java | 762 +++++++++++++++++++
.../main/org/apache/sis/filter/TimeMethods.java | 393 ++++++++++
.../geoapi/filter/TemporalOperatorName.java | 4 +
.../org/apache/sis/filter/TemporalFilterTest.java | 23 +-
.../org.apache.sis.metadata/main/module-info.java | 1 +
.../sis/metadata/iso/acquisition/DefaultEvent.java | 9 +-
.../iso/acquisition/DefaultRequestedDate.java | 36 +-
.../iso/acquisition/DefaultRequirement.java | 23 +-
.../sis/metadata/iso/citation/DefaultCitation.java | 23 +-
.../metadata/iso/citation/DefaultCitationDate.java | 11 +-
.../distribution/DefaultStandardOrderProcess.java | 20 +-
.../metadata/iso/extent/DefaultTemporalExtent.java | 40 +-
.../apache/sis/metadata/iso/extent/Extents.java | 95 ++-
.../metadata/iso/identification/DefaultUsage.java | 23 +-
.../sis/metadata/privy/ImplementationHelper.java | 23 -
.../apache/sis/pending/temporal/DefaultPeriod.java | 12 +-
.../sis/pending/temporal/TemporalUtilities.java | 39 +-
.../org/apache/sis/xml/bind/gco/GO_DateTime.java | 3 +-
.../org/apache/sis/xml/bind/gml/TM_Primitive.java | 43 +-
.../apache/sis/xml/bind/gml/TemporalAdapter.java | 4 +-
.../org/apache/sis/xml/bind/gml/TimeInstant.java | 20 +-
.../apache/sis/xml/bind/gml/TimePeriodBound.java | 6 +-
.../org/apache/sis/xml/privy/XmlUtilities.java | 52 +-
.../sis/metadata/iso/extent/DefaultExtentTest.java | 15 +-
.../metadata/privy/ImplementationHelperTest.java | 19 -
.../org/apache/sis/metadata/xml/2007/Extent.xml | 2 -
.../org/apache/sis/metadata/xml/2016/Extent.xml | 2 -
.../apache/sis/xml/bind/gml/TimePeriodTest.java | 19 +-
.../org/apache/sis/xml/privy/XmlUtilitiesTest.java | 12 +-
.../test/org/apache/sis/xml/test/TestCase.java | 33 -
.../sis/referencing/gazetteer/LocationFormat.java | 7 +-
.../main/org/apache/sis/io/wkt/Formatter.java | 12 +-
.../apache/sis/io/wkt/GeodeticObjectParser.java | 3 +-
.../sis/referencing/datum/AbstractDatum.java | 3 +-
.../referencing/datum/DefaultGeodeticDatum.java | 4 +-
.../org/apache/sis/referencing/internal/Epoch.java | 6 +-
.../sis/referencing/privy/ExtentSelector.java | 101 +--
.../referencing/AbstractReferenceSystemTest.java | 9 +-
.../datum/DefaultGeodeticDatumTest.java | 3 +-
.../sis/referencing/privy/ExtentSelectorTest.java | 5 +-
.../apache/sis/test/integration/MetadataTest.java | 29 +-
.../sis/test/integration/MetadataVerticalTest.java | 10 +-
.../storage/geotiff/reader/XMLMetadataTest.java | 2 +-
.../apache/sis/storage/base/MetadataBuilder.java | 3 +-
.../apache/sis/pending/geoapi/temporal/Period.java | 6 +-
.../main/org/apache/sis/util/Classes.java | 20 +-
.../org/apache/sis/util/privy/TemporalDate.java | 113 ++-
.../main/org/apache/sis/util/resources/Errors.java | 5 +
.../apache/sis/util/resources/Errors.properties | 1 +
.../apache/sis/util/resources/Errors_fr.properties | 1 +
.../org/apache/sis/measure/RangeFormatTest.java | 8 +-
.../test/org/apache/sis/test/TestUtilities.java | 4 +-
.../sis/gui/metadata/IdentificationInfo.java | 9 +-
56 files changed, 1841 insertions(+), 1160 deletions(-)
diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/DefaultFilterFactory.java
index 80379a395d,c020754996..03264883a2
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/DefaultFilterFactory.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/DefaultFilterFactory.java
@@@ -32,12 -32,16 +32,13 @@@ import org.apache.sis.filter.sqlmm.Regi
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.iso.AbstractFactory;
import org.apache.sis.util.resources.Errors;
+ import org.apache.sis.util.privy.Strings;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import java.util.Iterator;
-import java.time.Instant;
-import org.opengis.filter.*;
-import org.opengis.feature.Feature;
-import org.opengis.filter.capability.AvailableFunction;
-import org.opengis.filter.capability.FilterCapabilities;
-import org.apache.sis.util.privy.AbstractMap;
+// Specific to the main branch:
+import org.apache.sis.feature.AbstractFeature;
+import org.apache.sis.pending.geoapi.filter.MatchAction;
+import org.apache.sis.pending.geoapi.filter.SpatialOperatorName;
+import org.apache.sis.pending.geoapi.filter.DistanceOperatorName;
/**
@@@ -128,14 -128,13 +132,13 @@@ public abstract class DefaultFilterFact
}
/**
- * Returns a factory operating on {@link Feature} instances.
+ * Returns a factory operating on {@link AbstractFeature} instances.
* The {@linkplain GeometryLibrary geometry library} will be the system default.
+ * The temporal objects can be {@link java.util.Date} or implementations of {@link java.time.temporal.Temporal}.
*
- * @return factory operating on {@link Feature} instances.
+ * @return factory operating on {@link AbstractFeature} instances.
- *
- * @todo The type of temporal objects is not yet determined.
*/
- public static FilterFactory<Feature, Object, Object> forFeatures() {
+ public static DefaultFilterFactory<AbstractFeature, Object, Object> forFeatures() {
return Features.DEFAULT;
}
@@@ -643,11 -725,14 +646,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "After" operator between the two temporal values.
- *
- * @see TemporalOperatorName#AFTER
*/
- @Override
- public TemporalOperator<R> after(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> after(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.After<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.After::new, time1, time2);
}
/**
@@@ -656,11 -741,14 +659,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "Before" operator between the two temporal values.
- *
- * @see TemporalOperatorName#BEFORE
*/
- @Override
- public TemporalOperator<R> before(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> before(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.Before<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.Before::new, time1, time2);
}
/**
@@@ -669,11 -757,14 +672,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "Begins" operator between the two temporal values.
- *
- * @see TemporalOperatorName#BEGINS
*/
- @Override
- public TemporalOperator<R> begins(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> begins(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.Begins<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.Begins::new, time1, time2);
}
/**
@@@ -682,11 -773,14 +685,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "BegunBy" operator between the two temporal values.
- *
- * @see TemporalOperatorName#BEGUN_BY
*/
- @Override
- public TemporalOperator<R> begunBy(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> begunBy(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.BegunBy<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.BegunBy::new, time1, time2);
}
/**
@@@ -695,11 -789,14 +698,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "TContains" operator between the two temporal values.
- *
- * @see TemporalOperatorName#CONTAINS
*/
- @Override
- public TemporalOperator<R> tcontains(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> tcontains(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.Contains<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.Contains::new, time1, time2);
}
/**
@@@ -708,11 -805,14 +711,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "During" operator between the two temporal values.
- *
- * @see TemporalOperatorName#DURING
*/
- @Override
- public TemporalOperator<R> during(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> during(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.During<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.During::new, time1, time2);
}
/**
@@@ -721,11 -821,14 +724,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "TEquals" operator between the two temporal values.
- *
- * @see TemporalOperatorName#EQUALS
*/
- @Override
- public TemporalOperator<R> tequals(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> tequals(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.Equals<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.Equals::new, time1, time2);
}
/**
@@@ -734,11 -837,14 +737,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "TOverlaps" operator between the two temporal values.
- *
- * @see TemporalOperatorName#OVERLAPS
*/
- @Override
- public TemporalOperator<R> toverlaps(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> toverlaps(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.Overlaps<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.Overlaps::new, time1, time2);
}
/**
@@@ -747,11 -853,14 +750,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "Meets" operator between the two temporal values.
- *
- * @see TemporalOperatorName#MEETS
*/
- @Override
- public TemporalOperator<R> meets(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> meets(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.Meets<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.Meets::new, time1, time2);
}
/**
@@@ -760,11 -869,14 +763,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "Ends" operator between the two temporal values.
- *
- * @see TemporalOperatorName#ENDS
*/
- @Override
- public TemporalOperator<R> ends(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> ends(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.Ends<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.Ends::new, time1, time2);
}
/**
@@@ -773,11 -885,14 +776,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "OverlappedBy" operator between the two temporal values.
- *
- * @see TemporalOperatorName#OVERLAPPED_BY
*/
- @Override
- public TemporalOperator<R> overlappedBy(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> overlappedBy(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.OverlappedBy<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.OverlappedBy::new, time1, time2);
}
/**
@@@ -786,11 -901,14 +789,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "MetBy" operator between the two temporal values.
- *
- * @see TemporalOperatorName#MET_BY
*/
- @Override
- public TemporalOperator<R> metBy(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> metBy(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.MetBy<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.MetBy::new, time1, time2);
}
/**
@@@ -799,11 -917,14 +802,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "EndedBy" operator between the two temporal values.
- *
- * @see TemporalOperatorName#ENDED_BY
*/
- @Override
- public TemporalOperator<R> endedBy(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> endedBy(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.EndedBy<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.EndedBy::new, time1, time2);
}
/**
@@@ -813,11 -934,14 +816,11 @@@
* @param time1 expression fetching the first temporal value.
* @param time2 expression fetching the second temporal value.
* @return a filter for the "AnyInteracts" operator between the two temporal values.
- *
- * @see TemporalOperatorName#ANY_INTERACTS
*/
- @Override
- public TemporalOperator<R> anyInteracts(final Expression<R, ? extends T> time1,
- final Expression<R, ? extends T> time2)
+ public Filter<R> anyInteracts(final Expression<R, ? extends T> time1,
+ final Expression<R, ? extends T> time2)
{
- return new TemporalFilter.AnyInteracts<>(time1, time2);
+ return TemporalFilter.create(temporal, TemporalOperation.AnyInteracts::new, time1, time2);
}
/**
diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalFilter.java
index ae78bad713,88ebd77415..21629a0fda
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalFilter.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalFilter.java
@@@ -16,11 -16,15 +16,12 @@@
*/
package org.apache.sis.filter;
- import java.time.Instant;
+ import org.apache.sis.util.Classes;
+ import org.apache.sis.feature.privy.FeatureExpression;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.temporal.Period;
-import org.opengis.filter.Filter;
-import org.opengis.filter.Expression;
-import org.opengis.filter.TemporalOperator;
-import org.opengis.filter.TemporalOperatorName;
+// Specific to the main branch:
+import org.apache.sis.pending.geoapi.temporal.Period;
+import org.apache.sis.pending.geoapi.filter.TemporalOperatorName;
/**
@@@ -37,10 -35,11 +32,11 @@@
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
*
- * @param <T> the type of resources (e.g. {@code Feature}) used as inputs.
- * @param <R> the type of resources (e.g. {@link org.opengis.feature.Feature}) used as inputs.
++ * @param <R> the type of resources (e.g. {@code Feature}) used as inputs.
+ * @param <T> the base type of temporal objects, or {@code Object.class} for any type.
*/
- abstract class TemporalFilter<T> extends BinaryFunction<T,Object,Object>
- implements Filter<T>, Optimization.OnFilter<T>
+ class TemporalFilter<R,T> extends BinaryFunction<R,T,T>
- implements TemporalOperator<R>, Optimization.OnFilter<R>
++ implements Filter<R>, Optimization.OnFilter<R>
{
/**
* For cross-version compatibility.
diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalOperation.java
index 0000000000,d826f84485..535990fc99
mode 000000,100644..100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalOperation.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalOperation.java
@@@ -1,0 -1,762 +1,762 @@@
+ /*
+ * 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
+ *
+ * http://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.
+ */
+ package org.apache.sis.filter;
+
+ import java.io.Serializable;
+ import java.time.temporal.Temporal;
+ import org.apache.sis.util.Classes;
+ import org.apache.sis.util.privy.Strings;
+ import org.apache.sis.util.collection.WeakHashSet;
+ import static org.apache.sis.filter.TimeMethods.BEFORE;
+ import static org.apache.sis.filter.TimeMethods.AFTER;
+ import static org.apache.sis.filter.TimeMethods.EQUAL;
+
+ // Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.temporal.Period;
-import org.opengis.filter.TemporalOperatorName;
++import org.apache.sis.pending.geoapi.temporal.Period;
++import org.apache.sis.pending.geoapi.filter.TemporalOperatorName;
+
+
+ /**
+ * Temporal operations between periods and/or instants.
+ * The nature of the operation depends on the subclass.
+ * Subclasses shall override at least one of the following methods:
+ *
+ * <ul>
+ * <li>{@link #evaluate(T, T)}</li>
+ * <li>{@link #evaluate(T, Period)}</li>
+ * <li>{@link #evaluate(Period, T)}</li>
+ * <li>{@link #evaluate(Period, Period)}</li>
+ * </ul>
+ *
+ * Instances of this classes are immutable and thread-safe.
+ * The same instances are shared by many filters.
+ *
+ * @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
+ *
+ * @param <T> the base type of temporal objects, or {@code Object.class} for any type.
+ */
+ abstract class TemporalOperation<T> implements Serializable {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -5304814915639460679L;
+
+ /**
+ * Temporal operations created in the current JVM.
+ */
+ @SuppressWarnings("unchecked")
+ private static final WeakHashSet<TemporalOperation<?>> POOL = new WeakHashSet<>((Class) TemporalOperation.class);
+
+ /**
+ * The set of methods to invoke for performing "is before", "is after" or "is equal" comparisons.
+ */
+ protected final TimeMethods<T> comparators;
+
+ /**
+ * Creates a new temporal operation.
+ *
+ * @param comparators the set of methods to invoke for performing comparisons.
+ */
+ protected TemporalOperation(final TimeMethods<T> comparators) {
+ this.comparators = comparators;
+ }
+
+ /**
+ * Returns a unique, shared instance of this operation.
+ *
+ * @return a unique instance equal to {@code this}.
+ */
+ public final TemporalOperation<T> unique() {
+ return POOL.unique(this);
+ }
+
+ /**
+ * Returns a hash code value for this operation.
+ * Used for {@link #unique()} implementation.
+ */
+ @Override
+ public final int hashCode() {
+ return getClass().hashCode() + 31 * comparators.type.hashCode();
+ }
+
+ /**
+ * Compares the given object with this operation for equality.
+ * Used for {@link #unique()} implementation.
+ */
+ @Override
+ public final boolean equals(final Object other) {
+ return (other != null) && (other.getClass() == getClass()) &&
+ ((TemporalOperation) other).comparators.type == comparators.type;
+ }
+
+ /**
+ * Returns a string representation for debugging purposes.
+ */
+ @Override
+ public final String toString() {
+ return Strings.toString(getClass(),
+ "operator", getOperatorType().identifier(),
+ "type", comparators.type.getSimpleName());
+ }
+
+ /**
+ * Returns an identification of this operation.
+ */
+ public abstract TemporalOperatorName getOperatorType();
+
+ /**
+ * Returns the mathematical symbol for this temporal operation.
+ *
+ * @return the mathematical symbol, or 0 if none.
+ */
+ protected char symbol() {
+ return (char) 0;
+ }
+
+ /**
+ * Evaluates the filter between two temporal objects.
+ * Both arguments given to this method shall be non-null.
+ */
+ protected boolean evaluate(T self, T other) {
+ return false;
+ }
+
+ /**
+ * Evaluates the filter between a temporal object and a period.
+ * Both arguments given to this method shall be non-null, but period begin or end instant may be null.
+ *
+ * <p><b>Note:</b> this relationship is not defined by ISO 19108. This method should be overridden
+ * only when an ISO 19108 extension can be easily defined, for example for the "equal" operation.</p>
+ */
+ protected boolean evaluate(T self, Period other) {
+ return false;
+ }
+
+ /**
+ * Evaluates the filter between a period and a temporal object.
+ * Both arguments given to this method shall be non-null, but period begin or end instant may be null.
+ * Note: the {@code self} and {@code other} argument names are chosen to match ISO 19108 tables.
+ */
+ protected boolean evaluate(Period self, T other) {
+ return false;
+ }
+
+ /**
+ * Evaluates the filter between two periods.
+ * Both arguments given to this method shall be non-null, but period begin or end instant may be null.
+ * Note: the {@code self} and {@code other} argument names are chosen to match ISO 19108 tables.
+ */
+ protected abstract boolean evaluate(Period self, Period other);
+
+ /**
+ * Returns {@code true} if {@code other} is non-null and the specified comparison evaluates to {@code true}.
+ * This is a helper function for {@code evaluate(…)} methods implementations.
+ *
+ * @param test enumeration value such as {@link TimeMethods#BEFORE} or {@link TimeMethods#AFTER}.
+ * @param self the object on which to invoke the method identified by {@code test}.
+ * @param other the argument to give to the test method call, or {@code null} if none.
+ * @return the result of performing the comparison identified by {@code test}.
- * @throws InvalidFilterValueException if the two objects cannot be compared.
++ * @throws IllegalArgumentException if the two objects cannot be compared.
+ */
+ final boolean compare(final int test, final T self, final Temporal other) {
+ return (other != null) && comparators.compare(test, self, other);
+ }
+
+ /**
+ * Returns {@code true} if both arguments are non-null and the specified comparison evaluates to {@code true}.
+ * This is a helper function for {@code evaluate(…)} methods implementations.
+ *
+ * @param test enumeration value such as {@link TimeMethods#BEFORE} or {@link TimeMethods#AFTER}.
+ * @param self the object on which to invoke the method identified by {@code test}, or {@code null} if none.
+ * @param other the argument to give to the test method call, or {@code null} if none.
+ * @return the result of performing the comparison identified by {@code test}.
- * @throws InvalidFilterValueException if the two objects cannot be compared.
++ * @throws IllegalArgumentException if the two objects cannot be compared.
+ */
+ @SuppressWarnings("unchecked")
+ static boolean compare(final int test, final Temporal self, final Temporal other) {
+ return (self != null) && (other != null) && TimeMethods.compare(test,
+ (Class) Classes.findCommonClass(self.getClass(), other.getClass()), self, other);
+ }
+
+
+ /**
+ * Reference to a sub-class constructor.
+ *
+ * @param <T> type of temporal object.
+ */
+ @FunctionalInterface
+ static interface Factory {
+ /**
+ * Creates a new temporal operation.
+ *
+ * @param <T> type of temporal objects that the operation will accept.
+ * @param comparators the set of methods to invoke for performing comparisons.
+ * @return the temporal operation using the given "is before", "is after" and "is equal" methods.
+ */
+ <T> TemporalOperation<T> create(TimeMethods<T> comparators);
+ }
+
+
+ /**
+ * The {@code "TEquals"} (=) operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self = other}</li>
+ * <li>{@literal self.begin = other.begin AND self.end = other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class Equals<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -6060822291802339424L;
+
+ /** Creates a new operation. */
+ Equals(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.EQUALS;
+ }
+
+ /** Symbol of this operation. */
+ @Override protected char symbol() {
+ return '=';
+ }
+
+ /** Condition defined by ISO 19108:2002 §5.2.3.5. */
+ @Override protected boolean evaluate(T self, T other) {
+ return comparators.isEqual.test(self, other);
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(T self, Period other) {
+ return compare(EQUAL, self, other.getBeginning()) &&
+ compare(EQUAL, self, other.getEnding());
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(Period self, T other) {
+ return compare(EQUAL, other, self.getBeginning()) &&
+ compare(EQUAL, other, self.getEnding());
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(Period self, Period other) {
+ return compare(EQUAL, self.getBeginning(), other.getBeginning()) &&
+ compare(EQUAL, self.getEnding(), other.getEnding());
+ }
+ }
+
+
+ /**
+ * The {@code "Before"} {@literal (<)} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self < other}</li>
+ * <li>{@literal self.end < other}</li>
+ * <li>{@literal self.end < other.begin}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class Before<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -3422629447456003982L;
+
+ /** Creates a new operation. */
+ Before(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.BEFORE;
+ }
+
+ /** Symbol of this operation. */
+ @Override protected char symbol() {
+ return '<';
+ }
+
+ /** Condition defined by ISO 19108:2002 §5.2.3.5. */
+ @Override protected boolean evaluate(T self, T other) {
+ return comparators.isBefore.test(self, other);
+ }
+
+ /** Relationship not defined by ISO 19108:2006. */
+ @Override public boolean evaluate(T self, Period other) {
+ return compare(BEFORE, self, other.getBeginning());
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(Period self, T other) {
+ return compare(AFTER, other, self.getEnding());
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(Period self, Period other) {
+ return compare(BEFORE, self.getEnding(), other.getBeginning());
+ }
+ }
+
+
+ /**
+ * The {@code "After"} {@literal (>)} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self > other}</li>
+ * <li>{@literal self.begin > other}</li>
+ * <li>{@literal self.begin > other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class After<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 5410476260417497682L;
+
+ /** Creates a new operation. */
+ After(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.AFTER;
+ }
+
+ /** Symbol of this operation. */
+ @Override protected char symbol() {
+ return '>';
+ }
+
+ /** Condition defined by ISO 19108:2002 §5.2.3.5. */
+ @Override protected boolean evaluate(T self, T other) {
+ return comparators.isAfter.test(self, other);
+ }
+
+ /** Relationship not defined by ISO 19108:2006. */
+ @Override public boolean evaluate(T self, Period other) {
+ return compare(AFTER, self, other.getEnding());
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(Period self, T other) {
+ return compare(BEFORE, other, self.getBeginning());
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(Period self, Period other) {
+ return compare(AFTER, self.getBeginning(), other.getEnding());
+ }
+ }
+
+
+ /**
+ * The {@code "Begins"} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin = other.begin AND self.end < other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class Begins<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -7880699329127762233L;
+
+ /** Creates a new operation. */
+ Begins(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.BEGINS;
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return compare(EQUAL, self.getBeginning(), other.getBeginning()) &&
+ compare(BEFORE, self.getEnding(), other.getEnding());
+ }
+ }
+
+
+ /**
+ * The {@code "Ends"} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin > other.begin AND self.end = other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class Ends<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -5508229966320563437L;
+
+ /** Creates a new operation. */
+ Ends(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.ENDS;
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return compare(EQUAL, self.getEnding(), other.getEnding()) &&
+ compare(AFTER, self.getBeginning(), other.getBeginning());
+ }
+ }
+
+
+ /**
+ * The {@code "BegunBy"} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin = other}</li>
+ * <li>{@literal self.begin = other.begin AND self.end > other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class BegunBy<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -7212413827394364384L;
+
+ /** Creates a new operation. */
+ BegunBy(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.BEGUN_BY;
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(Period self, T other) {
+ return compare(EQUAL, other, self.getBeginning());
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return compare(EQUAL, self.getBeginning(), other.getBeginning()) &&
+ compare(AFTER, self.getEnding(), other.getEnding());
+ }
+ }
+
+
+ /**
+ * The {@code "EndedBy"} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.end = other}</li>
+ * <li>{@literal self.begin < other.begin AND self.end = other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class EndedBy<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 8586566103462153666L;
+
+ /** Creates a new operation. */
+ EndedBy(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.ENDED_BY;
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final T other) {
+ return compare(EQUAL, other, self.getEnding());
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return compare(EQUAL, self.getEnding(), other.getEnding()) &&
+ compare(BEFORE, self.getBeginning(), other.getBeginning());
+ }
+ }
+
+
+ /**
+ * The {@code "Meets"} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.end = other.begin}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class Meets<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -3534843269384858443L;
+
+ /** Creates a new operation. */
+ Meets(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.MEETS;
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final T self, final T other) {
+ return comparators.isEqual.test(self, other);
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final T self, final Period other) {
+ return compare(EQUAL, self, other.getBeginning());
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final Period self, final T other) {
+ return compare(EQUAL, other, self.getEnding());
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return compare(EQUAL, self.getEnding(), other.getBeginning());
+ }
+ }
+
+
+ /**
+ * The {@code "MetBy"} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin = other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class MetBy<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 5358059498707330482L;
+
+ /** Creates a new operation. */
+ MetBy(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.MET_BY;
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final T self, final T other) {
+ return comparators.isEqual.test(self, other);
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final T self, final Period other) {
+ return compare(EQUAL, self, other.getEnding());
+ }
+
+ /** Extension to ISO 19108: handle instant as a tiny period. */
+ @Override public boolean evaluate(final Period self, final T other) {
+ return compare(EQUAL, other, self.getBeginning());
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return compare(EQUAL, self.getBeginning(), other.getEnding());
+ }
+ }
+
+
+ /**
+ * The {@code "During"} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin > other.begin AND self.end < other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class During<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = -4674319635076886196L;
+
+ /** Creates a new operation. */
+ During(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.DURING;
+ }
+
+ /** Symbol of this operation. */
+ @Override protected char symbol() {
+ return '⊊'; // `self` is a proper (or strict) subset of `other`.
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return compare(AFTER, self.getBeginning(), other.getBeginning()) &&
+ compare(BEFORE, self.getEnding(), other.getEnding());
+ }
+ }
+
+
+ /**
+ * The {@code "TContains"} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin < other AND self.end > other}</li>
+ * <li>{@literal self.begin < other.begin AND self.end > other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class Contains<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 9107531246948034411L;
+
+ /** Creates a new operation. */
+ Contains(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.CONTAINS;
+ }
+
+ /** Symbol of this operation. */
+ @Override protected char symbol() {
+ return '⊋'; // `self` is a proper (or strict) superset of `other`.
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final T other) {
+ return compare(AFTER, other, self.getBeginning()) &&
+ compare(BEFORE, other, self.getEnding());
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ return compare(BEFORE, self.getBeginning(), other.getBeginning()) &&
+ compare(AFTER, self.getEnding(), other.getEnding());
+ }
+ }
+
+
+ /**
+ * The {@code "TOverlaps"} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin < other.begin AND self.end > other.begin AND self.end < other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class Overlaps<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 1517443045593389773L;
+
+ /** Creates a new operation. */
+ Overlaps(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.OVERLAPS;
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ final Temporal selfBegin, selfEnd, otherBegin, otherEnd;
+ return ((otherBegin = other.getBeginning()) != null) &&
+ ((selfBegin = self .getBeginning()) != null) && compare(BEFORE, selfBegin, otherBegin) &&
+ ((selfEnd = self .getEnding()) != null) && compare(AFTER, selfEnd, otherBegin) &&
+ ((otherEnd = other.getEnding()) != null) && compare(BEFORE, selfEnd, otherEnd);
+ }
+ }
+
+
+ /**
+ * The {@code "OverlappedBy"} operation. Defined by ISO 19108 as:
+ * <ul>
+ * <li>{@literal self.begin > other.begin AND self.begin < other.end AND self.end > other.end}</li>
+ * </ul>
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class OverlappedBy<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 2228673820507226463L;
+
+ /** Creates a new operation. */
+ OverlappedBy(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.OVERLAPPED_BY;
+ }
+
+ /** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ final Temporal selfBegin, selfEnd, otherBegin, otherEnd;
+ return ((selfBegin = self .getBeginning()) != null) &&
+ ((otherBegin = other.getBeginning()) != null) && compare(AFTER, selfBegin, otherBegin) &&
+ ((otherEnd = other.getEnding()) != null) && compare(BEFORE, selfBegin, otherEnd) &&
+ ((selfEnd = self .getEnding()) != null) && compare(AFTER, selfEnd, otherEnd);
+ }
+ }
+
+
+ /**
+ * The {@code "AnyInteracts"} filter.
+ * This is a shortcut for NOT (Before OR Meets OR MetBy OR After).
+ *
+ * @param <T> the base type of temporal objects.
+ */
+ static final class AnyInteracts<T> extends TemporalOperation<T> {
+ /** For cross-version compatibility during (de)serialization. */
+ private static final long serialVersionUID = 5972351564286442392L;
+
+ /** Creates a new operation. */
+ AnyInteracts(TimeMethods<T> comparators) {
+ super(comparators);
+ }
+
+ /** Identification of this operation. */
+ @Override public TemporalOperatorName getOperatorType() {
+ return TemporalOperatorName.ANY_INTERACTS;
+ }
+
+ /** Condition defined by OGC filter specification. */
+ @Override public boolean evaluate(final Period self, final Period other) {
+ final Temporal selfBegin, selfEnd, otherBegin, otherEnd;
+ return ((selfBegin = self .getBeginning()) != null) &&
+ ((otherEnd = other.getEnding()) != null) && compare(BEFORE, selfBegin, otherEnd) &&
+ ((selfEnd = self .getEnding()) != null) &&
+ ((otherBegin = other.getBeginning()) != null) && compare(AFTER, selfEnd, otherBegin);
+ }
+ }
+ }
diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TimeMethods.java
index 0000000000,11cc0ca6b7..18d60debd9
mode 000000,100644..100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TimeMethods.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TimeMethods.java
@@@ -1,0 -1,396 +1,393 @@@
+ /*
+ * 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
+ *
+ * http://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.
+ */
+ package org.apache.sis.filter;
+
+ import java.util.Map;
+ import java.util.Date;
+ import java.time.Instant;
+ import java.time.Year;
+ import java.time.YearMonth;
+ import java.time.MonthDay;
+ import java.time.LocalTime;
+ import java.time.OffsetTime;
+ import java.time.OffsetDateTime;
+ import java.time.DateTimeException;
+ import java.time.chrono.ChronoLocalDate;
+ import java.time.chrono.ChronoLocalDateTime;
+ import java.time.chrono.ChronoZonedDateTime;
+ import java.time.temporal.ChronoField;
+ import java.time.temporal.Temporal;
+ import java.time.temporal.TemporalAccessor;
+ import java.util.function.BiPredicate;
+ import java.lang.reflect.Modifier;
+ import java.io.Serializable;
+ import java.io.ObjectStreamException;
+ import org.apache.sis.util.privy.Strings;
+ import org.apache.sis.util.resources.Errors;
+
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.filter.InvalidFilterValueException;
-
+
+ /**
+ * Provides the <i>is before</i> and <i>is after</i> operations for various {@code java.time} objects.
+ * This class delegates to the {@code isBefore(T)} or {@code isAfter(T)} methods of each supported classes.
+ *
+ * Instances of this classes are immutable and thread-safe.
+ * The same instance can be shared by many {@link TemporalOperation} instances.
+ *
+ * <h2>Design note about alternative approaches</h2>
+ * We do not delegate to {@link Comparable#compareTo(Object)} because the latter method compares not only
+ * positions on the timeline, but also other properties not relevant to an "is before" or "is after" test.
+ * We could use {@link ChronoLocalDate#timeLineOrder()} comparators instead, but those comparators are not
+ * defined for every classes where the "is before" and "is after" methods differ from "compare to" method.
+ * Furthermore, some temporal classes override {@code isBefore(T)} or {@code isAfter(T)} for performance.
+ *
+ * @param <T> the base type of temporal objects, or {@code Object.class} for any type.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ */
+ class TimeMethods<T> implements Serializable {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = 1075289362575825939L;
+
+ /**
+ * The type of temporal objects accepted by this set of operations.
+ */
+ public final Class<T> type;
+
+ /**
+ * Enumeration values for a test to apply.
+ *
+ * @see #compare(int, T, TemporalAccessor)
+ */
+ static final int BEFORE=1, AFTER=2, EQUAL=0;
+
+ /**
+ * Predicate to execute for testing the ordering between temporal objects.
+ * This comparison operator differs from the {@code compareTo(…)} method in that it compares only the
+ * positions on the timeline, ignoring metadata such as the calendar used for representing positions.
+ */
+ public final transient BiPredicate<T,T> isBefore, isAfter, isEqual;
+
+ /**
+ * Creates a new set of operators. This method is for subclasses only.
+ * For getting a {@code TimeMethods} instance, see {@link #find(Class)}.
+ */
+ private TimeMethods(final Class<T> type,
+ final BiPredicate<T,T> isBefore,
+ final BiPredicate<T,T> isAfter,
+ final BiPredicate<T,T> isEqual)
+ {
+ this.type = type;
+ this.isBefore = isBefore;
+ this.isAfter = isAfter;
+ this.isEqual = isEqual;
+ }
+
+ /**
+ * Returns whether the end point will be determined dynamically every time that a method is invoked.
+ *
+ * @return whether the methods are determined dynamically on an instance-by-instance basis.
+ */
+ public boolean isDynamic() {
+ return false;
+ }
+
+ /**
+ * Delegates the comparison to the method identified by the {@code test} argument.
+ * This method is overridden in subclasses where the delegation can be more direct.
+ *
+ * @param test {@link #BEFORE}, {@link #AFTER} or {@link #EQUAL}.
+ * @param self the object on which to invoke the method identified by {@code test}.
+ * @param other the argument to give to the test method call.
+ * @return the result of performing the comparison identified by {@code test}.
+ */
+ boolean delegate(final int test, final T self, final T other) {
+ final BiPredicate<T,T> p;
+ switch (test) {
+ case BEFORE: p = isBefore; break;
+ case AFTER: p = isAfter; break;
+ case EQUAL: p = isEqual; break;
+ default: throw new AssertionError(test);
+ }
+ return p.test(self, other);
+ }
+
+ /**
+ * Compares an object of class {@code <T>} with a temporal object of unknown class.
+ * The other object is typically the beginning or ending of a period.
+ *
+ * @param test {@link #BEFORE}, {@link #AFTER} or {@link #EQUAL}.
+ * @param self the object on which to invoke the method identified by {@code test}.
+ * @param other the argument to give to the test method call.
+ * @return the result of performing the comparison identified by {@code test}.
- * @throws InvalidFilterValueException if the two objects cannot be compared.
++ * @throws IllegalArgumentException if the two objects cannot be compared.
+ */
+ @SuppressWarnings("unchecked")
+ final boolean compare(final int test, final T self, final TemporalAccessor other) {
+ if (type.isInstance(other)) {
+ return delegate(test, self, (T) other); // Safe because of above `isInstance(…)` check.
+ }
+ return compareAsInstants(test, accessor(self), other);
+ }
+
+ /**
+ * Compares two temporal objects of unknown class. This method needs to check for specialized implementations
+ * before to delegate to {@link Comparable#compareTo(Object)}, because the comparison methods on the timeline
+ * are not always the same as {@code compareTo(…)}.
+ *
+ * @param <T> base class of the objects to compare.
+ * @param test {@link #BEFORE}, {@link #AFTER} or {@link #EQUAL}.
+ * @param type base class of the {@code self} and {@code other} arguments.
+ * @param self the object on which to invoke the method identified by {@code test}.
+ * @param other the argument to give to the test method call.
+ * @return the result of performing the comparison identified by {@code test}.
- * @throws InvalidFilterValueException if the two objects cannot be compared.
++ * @throws IllegalArgumentException if the two objects cannot be compared.
+ */
+ static <T> boolean compare(final int test, final Class<T> type, final T self, final T other) {
+ /*
+ * The following cast is not strictly true, it should be `<? extends T>`.
+ * However, because of the `isInstance(…)` check and because <T> is used
+ * only as parameter type (no collection), it is okay to use it that way.
+ */
+ final TimeMethods<? super T> tc = findSpecialized(type);
+ if (tc != null) {
+ /*
+ * Found one of the special cases listed in `INTERFACES` or `FINAL_TYPE`.
+ * If the other type is compatible, the comparison is executed directly.
+ * Note: the `switch` statement is equivalent to `tc.compare(test, …)`,
+ * but is inlined because that method is never overridden in this context.
+ */
+ if (tc.type.isInstance(other)) {
+ assert tc.type.isAssignableFrom(type) : tc; // Those types are not necessarily equal.
+ final BiPredicate<? super T, ? super T> p;
+ switch (test) {
+ case BEFORE: p = tc.isBefore; break;
+ case AFTER: p = tc.isAfter; break;
+ case EQUAL: p = tc.isEqual; break;
+ default: throw new AssertionError(test);
+ }
+ return p.test(self, other);
+ }
+ } else if (self instanceof Comparable<?> && type.isInstance(other)) {
+ /*
+ * The type of the first operand is not a special case, but the second operand is compatible
+ * for a call to the generic `compareTo(…)` method. This case does not happen often, because
+ * not many `java.time` classes have no "is before" or "is after" operations.
+ * Some examples are `Month` and `DayOfWeek`.
+ */
+ @SuppressWarnings("unchecked") // Safe because verification done by `isInstance(…)`.
+ final int c = ((Comparable) self).compareTo(other);
+ switch (test) {
+ case BEFORE: return c < 0;
+ case AFTER: return c > 0;
+ case EQUAL: return c == 0;
+ default: throw new AssertionError(test);
+ }
+ }
+ /*
+ * If we reach this point, the two operands are of different classes and we cannot compare them directly.
+ * Try to compare the two operands as instants on the timeline.
+ */
+ return compareAsInstants(test, accessor(self), accessor(other));
+ }
+
+ /**
+ * Returns the given object as a temporal accessor.
+ */
+ private static TemporalAccessor accessor(final Object value) {
+ if (value instanceof TemporalAccessor) {
+ return (TemporalAccessor) value;
+ } else if (value instanceof Date) {
+ return ((Date) value).toInstant(); // Overridden in `Date` subclasses.
+ } else {
- throw new InvalidFilterValueException(Errors.format(
++ throw new IllegalArgumentException(Errors.format(
+ Errors.Keys.CannotCompareInstanceOf_2, value.getClass(), TemporalAccessor.class));
+ }
+ }
+
+ /**
+ * Compares two temporal objects as instants.
+ * This is a last-resort fallback, when objects cannot be compared by their own methods.
+ *
+ * @param test {@link #BEFORE}, {@link #AFTER} or {@link #EQUAL}.
+ * @param self the object on which to invoke the method identified by {@code test}.
+ * @param other the argument to give to the test method call.
+ * @return the result of performing the comparison identified by {@code test}.
- * @throws InvalidFilterValueException if the two objects cannot be compared.
++ * @throws IllegalArgumentException if the two objects cannot be compared.
+ */
+ private static boolean compareAsInstants(final int test, final TemporalAccessor self, final TemporalAccessor other) {
+ try {
+ long t1 = self.getLong(ChronoField.INSTANT_SECONDS);
+ long t2 = other.getLong(ChronoField.INSTANT_SECONDS);
+ if (t1 == t2) {
+ t1 = self.getLong(ChronoField.NANO_OF_SECOND); // Should be present according Javadoc.
+ t2 = other.getLong(ChronoField.NANO_OF_SECOND);
+ if (t1 == t2) {
+ return test == EQUAL;
+ }
+ }
+ return test == ((t1 < t2) ? BEFORE : AFTER);
+ } catch (DateTimeException | ArithmeticException e) {
- throw new InvalidFilterValueException(Errors.format(
++ throw new IllegalArgumentException(Errors.format(
+ Errors.Keys.CannotCompareInstanceOf_2, self.getClass(), other.getClass()), e);
+ }
+ }
+
+ /**
+ * Returns the set of methods that can be invoked on instances of the given type, or {@code null} if none.
+ * This method returns only one of the methods defined in {@link #FINAL_TYPES} or {@link #INTERFACES}.
+ * It shall not try to create fallbacks.
+ *
+ * @param <T> compile-time value of the {@code type} argument.
+ * @param type the type of temporal object for which to get specialized methods.
+ * @return set of specialized methods for the given object type, or {@code null} if none.
+ */
+ @SuppressWarnings("unchecked")
+ private static <T> TimeMethods<? super T> findSpecialized(final Class<T> type) {
+ { // Block for keeping `tc` in local scope.
+ TimeMethods<?> tc = FINAL_TYPES.get(type);
+ if (tc != null) {
+ assert tc.type == type : tc;
+ return (TimeMethods<T>) tc; // Safe because of `==` checks.
+ }
+ }
+ for (TimeMethods<?> tc : INTERFACES) {
+ if (tc.type.isAssignableFrom(type)) {
+ return (TimeMethods<? super T>) tc; // Safe because of `isAssignableFrom(…)` checks.
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the set of methods that can be invoked on instances of the given type.
+ *
+ * @param <T> compile-time value of the {@code type} argument.
+ * @param type the type of temporal object for which to get specialized methods.
+ * @return set of comparison methods for the given object type.
+ */
+ @SuppressWarnings("unchecked") // For (Comparable) casts.
+ public static <T> TimeMethods<? super T> find(final Class<T> type) {
+ final TimeMethods<? super T> tc = findSpecialized(type);
+ if (tc != null) {
+ return tc;
+ }
+ if (Modifier.isFinal(type.getModifiers())) {
+ if (Comparable.class.isAssignableFrom(type)) {
+ return new TimeMethods<>(type,
+ (self, other) -> ((Comparable) self).compareTo(other) < 0,
+ (self, other) -> ((Comparable) self).compareTo(other) > 0,
+ (self, other) -> ((Comparable) self).compareTo(other) == 0);
+ } else {
- throw new InvalidFilterValueException(Errors.format(Errors.Keys.CannotCompareInstanceOf_2, type, type));
++ throw new IllegalArgumentException(Errors.format(Errors.Keys.CannotCompareInstanceOf_2, type, type));
+ }
+ } else {
+ return fallback(type);
+ }
+ }
+
+ /**
+ * Returns the last-resort fallback when the type of temporal objects cannot be determined in advance.
+ *
+ * @param <T> compile-time value of the {@code type} argument.
+ * @param type the type of temporal object for which to get the last-resource fallback methods.
+ * @return set of last-resort comparison methods for the given object type.
+ */
+ private static <T> TimeMethods<? super T> fallback(final Class<T> type) {
+ return new TimeMethods<>(type,
+ (self, other) -> compare(BEFORE, type, self, other),
+ (self, other) -> compare(AFTER, type, self, other),
+ (self, other) -> compare(EQUAL, type, self, other))
+ {
+ @Override public boolean isDynamic() {
+ return true;
+ }
+ @Override boolean delegate(final int test, final T self, final T other) {
+ return compare(test, type, self, other);
+ }
+ };
+ }
+
+ /**
+ * Returns the unique instance for the type after deserialization.
+ * This is needed for avoiding to serialize the lambda functions.
+ *
+ * @return the object to use after deserialization.
+ * @throws ObjectStreamException if the serialized object contains invalid data.
+ */
+ private Object readResolve() throws ObjectStreamException {
+ return find(type);
+ }
+
+ /**
+ * Operators for all supported temporal types that are interfaces or non-final classes.
+ * Those types need to be checked with {@link Class#isAssignableFrom(Class)} in iteration order.
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"}) // For `Chrono*` interfaces, because they are parameterized.
+ private static final TimeMethods<?>[] INTERFACES = {
+ new TimeMethods<>(ChronoZonedDateTime.class, ChronoZonedDateTime::isBefore, ChronoZonedDateTime::isAfter, ChronoZonedDateTime::isEqual),
+ new TimeMethods<>(ChronoLocalDateTime.class, ChronoLocalDateTime::isBefore, ChronoLocalDateTime::isAfter, ChronoLocalDateTime::isEqual),
+ new TimeMethods<>( ChronoLocalDate.class, ChronoLocalDate::isBefore, ChronoLocalDate::isAfter, ChronoLocalDate::isEqual),
+ new TimeMethods<>( Date.class, Date:: before, Date:: after, Date::equals)
+ };
+
+ /*
+ * No operation on numbers for now. We could revisit this policy in a future version if we
+ * allow the temporal function to have a CRS and to operate on temporal coordinate values.
+ */
+
+ /**
+ * Operators for all supported temporal types for which there is no need to check for subclasses.
+ * Those classes are usually final, except when wanting to intentionally ignore all subclasses.
+ * Those types should be tested before {@link #INTERFACES} because this check is quick.
+ *
+ * <h4>Implementation note</h4>
+ * {@link Year}, {@link YearMonth}, {@link MonthDay}, {@link LocalTime} and {@link Instant}
+ * could be replaced by {@link Comparable}. We nevertheless keep the specialized classes in
+ * case the implementations change in the future, and also for performance reason, because
+ * the code working on generic {@link Comparable} needs to check for special cases again.
+ */
+ private static final Map<Class<?>, TimeMethods<?>> FINAL_TYPES = Map.ofEntries(
+ entry(new TimeMethods<>(OffsetDateTime.class, OffsetDateTime::isBefore, OffsetDateTime::isAfter, OffsetDateTime::isEqual)),
+ entry(new TimeMethods<>( OffsetTime.class, OffsetTime::isBefore, OffsetTime::isAfter, OffsetTime::isEqual)),
+ entry(new TimeMethods<>( LocalTime.class, LocalTime::isBefore, LocalTime::isAfter, LocalTime::equals)),
+ entry(new TimeMethods<>( Year.class, Year::isBefore, Year::isAfter, Year::equals)),
+ entry(new TimeMethods<>( YearMonth.class, YearMonth::isBefore, YearMonth::isAfter, YearMonth::equals)),
+ entry(new TimeMethods<>( MonthDay.class, MonthDay::isBefore, MonthDay::isAfter, MonthDay::equals)),
+ entry(new TimeMethods<>( Instant.class, Instant::isBefore, Instant::isAfter, Instant::equals)),
+ entry(fallback(Temporal.class)), // Frequently declared type. Intentionally no "instance of" checks.
+ entry(fallback(Object.class))); // Not a final class, but to be used when the declared type is Object.
+
+ /**
+ * Helper method for adding entries to the {@link #FINAL_TYPES} map.
+ * Shall be used only for final classes.
+ */
+ private static Map.Entry<Class<?>, TimeMethods<?>> entry(final TimeMethods<?> op) {
+ return Map.entry(op.type, op);
+ }
+
+ /**
+ * Returns a string representation of this set of operations for debugging purposes.
+ *
+ * @return a string representation for debugging purposes.
+ */
+ @Override
+ public String toString() {
+ return Strings.toString(TimeMethods.class, "type", type.getSimpleName());
+ }
+ }
diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/TemporalOperatorName.java
index ddb62b817a,f35ee94813..a30135526f
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/TemporalOperatorName.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/pending/geoapi/filter/TemporalOperatorName.java
@@@ -18,11 -18,21 +18,15 @@@ package org.apache.sis.pending.geoapi.f
/**
- * Exception that may be thrown by a portraying operation.
- *
- * @author Johann Sorel (Geomatys)
+ * Placeholder for GeoAPI 3.1 interfaces (not yet released).
+ * Shall not be visible in public API, as it will be deleted after next GeoAPI release.
*/
-public class RenderingException extends Exception {
-
- public RenderingException(String message) {
- super(message);
- }
-
- public RenderingException(Throwable cause) {
- super(cause);
- }
+@SuppressWarnings("doclint:missing")
+public enum TemporalOperatorName {
+ AFTER, BEFORE, BEGINS, BEGUN_BY, CONTAINS, DURING, EQUALS, OVERLAPS, MEETS, ENDS,
+ OVERLAPPED_BY, MET_BY, ENDED_BY, ANY_INTERACTS;
+
- public RenderingException(String message, Throwable cause) {
- super(message, cause);
++ public String identifier() {
++ return name().toLowerCase();
+ }
}
diff --cc endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/TemporalFilterTest.java
index 71c23abbd6,b349e62672..a07fd7b129
--- a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/TemporalFilterTest.java
+++ b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/TemporalFilterTest.java
@@@ -22,12 -24,14 +24,12 @@@ import static org.apache.sis.util.privy
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import org.apache.sis.test.TestCase;
- import org.apache.sis.test.TestUtilities;
import static org.apache.sis.test.Assertions.assertSerializedEquals;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.temporal.Period;
-import org.opengis.feature.Feature;
-import org.opengis.filter.FilterFactory;
-import org.opengis.filter.TemporalOperator;
-import org.opengis.filter.TemporalOperatorName;
+// Specific to the main branch:
+import org.apache.sis.feature.AbstractFeature;
++import org.apache.sis.pending.geoapi.temporal.Period;
+import org.apache.sis.pending.geoapi.filter.TemporalOperatorName;
/**
@@@ -40,7 -44,7 +42,7 @@@ public final class TemporalFilterTest e
/**
* The factory to use for creating the objects to test.
*/
- private final DefaultFilterFactory<AbstractFeature,Object,Object> factory;
- private FilterFactory<Feature, Object, ? super Period> factory;
++ private DefaultFilterFactory<AbstractFeature, Object, ? super Period> factory;
/**
* The filter to test. This field shall be assigned by each {@code testFoo()} method by invoking
diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitation.java
index b3251941cf,7f06cf9de3..26e877abe8
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitation.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitation.java
@@@ -211,6 -206,7 +211,7 @@@ public class DefaultCitation extends IS
*
* @see #castOrCopy(Citation)
*/
- @SuppressWarnings({"this-escape", "deprecation"})
++ @SuppressWarnings("this-escape")
public DefaultCitation(final Citation object) {
super(object);
if (object != null) {
diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java
index a4e68742e0,2991ced2ec..6689ee1496
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java
@@@ -29,14 -30,8 +30,13 @@@ import org.opengis.metadata.distributio
import org.apache.sis.xml.bind.gco.GO_RecordType;
import org.apache.sis.xml.bind.gco.GO_Record;
import org.apache.sis.metadata.iso.ISOMetadata;
- import static org.apache.sis.metadata.privy.ImplementationHelper.toDate;
- import static org.apache.sis.metadata.privy.ImplementationHelper.toMilliseconds;
+ import org.apache.sis.util.privy.TemporalDate;
+// Specific to the main branch:
+import org.opengis.annotation.UML;
+import static org.opengis.annotation.Obligation.OPTIONAL;
+import static org.opengis.annotation.Specification.ISO_19115;
+
/**
* Common ways in which the resource may be obtained or received, and related instructions
@@@ -134,13 -129,11 +134,13 @@@ public class DefaultStandardOrderProces
super(object);
if (object != null) {
fees = object.getFees();
- plannedAvailableDateTime = toMilliseconds(object.getPlannedAvailableDateTime());
+ plannedAvailableDateTime = TemporalDate.toTemporal(object.getPlannedAvailableDateTime());
orderingInstructions = object.getOrderingInstructions();
turnaround = object.getTurnaround();
- orderOptionsType = object.getOrderOptionsType();
- orderOptions = object.getOrderOptions();
+ if (object instanceof DefaultStandardOrderProcess) {
+ orderOptionsType = ((DefaultStandardOrderProcess) object).getOrderOptionsType();
+ orderOptions = ((DefaultStandardOrderProcess) object).getOrderOptions();
+ }
}
}
diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultUsage.java
index 32c7a33efc,fa65552a55..8c6ea0c521
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultUsage.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultUsage.java
@@@ -163,15 -159,12 +164,15 @@@ public class DefaultUsage extends ISOMe
super(object);
if (object != null) {
specificUsage = object.getSpecificUsage();
- usageDate = toMilliseconds(object.getUsageDate());
+ usageDate = TemporalDate.toTemporal(object.getUsageDate());
userDeterminedLimitations = object.getUserDeterminedLimitations();
userContactInfo = copyCollection(object.getUserContactInfo(), ResponsibleParty.class);
- responses = copyCollection(object.getResponses(), InternationalString.class);
- additionalDocumentation = copyCollection(object.getAdditionalDocumentation(), Citation.class);
- identifiedIssues = copyCollection(object.getIdentifiedIssues(), Citation.class);
+ if (object instanceof DefaultUsage) {
+ final DefaultUsage c = (DefaultUsage) object;
+ responses = copyCollection(c.getResponses(), InternationalString.class);
+ additionalDocumentation = copyCollection(c.getAdditionalDocumentation(), Citation.class);
+ identifiedIssues = copyCollection(c.getIdentifiedIssues(), Citation.class);
+ }
}
}
diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/DefaultPeriod.java
index ce43f62a4b,6f4cff5259..afc79c7459
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/DefaultPeriod.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/DefaultPeriod.java
@@@ -17,10 -17,12 +17,10 @@@
package org.apache.sis.pending.temporal;
import java.util.Objects;
- import java.time.Instant;
+ import java.time.temporal.Temporal;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import java.time.Duration;
-import java.time.temporal.TemporalAmount;
-import org.opengis.temporal.Period;
+// Specific to the main branch:
+import org.apache.sis.pending.geoapi.temporal.Period;
/**
@@@ -29,12 -31,12 +29,12 @@@
*
* @author Martin Desruisseaux (Geomatys)
*/
- final class DefaultPeriod implements Period {
-public final class DefaultPeriod extends Primitive implements Period {
++public final class DefaultPeriod implements Period {
/** Bounds making this period. */
- private final Instant beginning, ending;
+ private final Temporal beginning, ending;
/** Creates a new period with the given bounds. */
- DefaultPeriod(final Instant beginning, final Instant ending) {
+ public DefaultPeriod(final Temporal beginning, final Temporal ending) {
this.beginning = beginning;
this.ending = ending;
}
diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataTest.java
index 06fcd20859,a3a48f2b93..7505b27228
--- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataTest.java
+++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataTest.java
@@@ -154,9 -142,10 +153,9 @@@ public final class MetadataTest extend
final var citation = new DefaultCitation("Some set of points");
citation.setAlternateTitles(Set.of(new SimpleInternationalString("Code XYZ")));
citation.setDates(List.of(
- new DefaultCitationDate(TestUtilities.date("1990-06-04 22:00:00"), DateType.REVISION),
- new DefaultCitationDate(TestUtilities.date("1979-08-02 22:00:00"), DateType.CREATION)));
+ new DefaultCitationDate(LocalDate.of(1990, 6, 5), DateType.REVISION),
+ new DefaultCitationDate(LocalDate.of(1979, 8, 3), DateType.CREATION)));
{
- @SuppressWarnings("deprecation")
final var originator = new DefaultResponsibleParty(Role.ORIGINATOR);
final var online = new DefaultOnlineResource(URI.create("http://www.com.univ-mrs.fr/LOB/"));
online.setProtocol(Constants.HTTP);
@@@ -222,10 -212,11 +221,10 @@@
final var aggregateInfo = new DefaultAggregateInformation();
final var name = new DefaultCitation("Some oceanographic campaign");
name.setAlternateTitles(Set.of(new SimpleInternationalString("Pseudo group of data")));
- name.setDates(Set.of(new DefaultCitationDate(TestUtilities.date("1990-06-04 22:00:00"), DateType.REVISION)));
+ name.setDates(Set.of(new DefaultCitationDate(LocalDate.of(1990, 6, 5), DateType.REVISION)));
aggregateInfo.setName(name);
aggregateInfo.setInitiativeType(InitiativeType.CAMPAIGN);
- aggregateInfo.setAssociationType(AssociationType.LARGER_WORK_CITATION);
+ aggregateInfo.setAssociationType(AssociationType.LARGER_WORD_CITATION); // There is a typo ("WORD" → "WORK"), but we have to use the wrong spelling for this branch.
identification.setAssociatedResources(Set.of(aggregateInfo));
}
/*
@@@ -380,11 -373,8 +380,9 @@@
"<gmx:Anchor xlink:href=\"SDN:L231:3:CDI\">Pseudo Common Data Index record</gmx:Anchor>");
replace(xml, "<gcol:CharacterString>4326</gcol:CharacterString>",
"<gmx:Anchor xlink:href=\"SDN:L101:2:4326\">4326</gmx:Anchor>");
+ replace(xml, "License", "Licence");
/*
- * The <gmd:EX_TemporalExtent> block cannot be marshalled es expected yet (need a "sis-temporal" module).
- * We need to instruct the XML comparator to ignore this block during the comparison. We also ignore for
- * now the "gml:id" attribute since SIS generates different values than the ones in our test XML file,
+ * Ignore the "gml:id" attribute because SIS generates different values than the ones in our test XML file,
* and those values may change in future SIS version.
*/
final var comparator = new DocumentComparator(getResource(), xml.toString());
diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
index d6701022c7,949b1c0a2d..56863a6c3b
--- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
+++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
@@@ -87,10 -88,10 +89,10 @@@ public final class MetadataVerticalTes
@Test
public void testMetadataWithVerticalCRS() throws JAXBException {
final Metadata metadata = unmarshalFile(Metadata.class, openTestFile());
- assertEquals("20090901", metadata.getFileIdentifier());
- assertEquals(Locale.ENGLISH, metadata.getLanguage());
- assertEquals(CharacterSet.UTF_8, metadata.getCharacterSet());
- assertEquals(xmlDate("2014-01-04 00:00:00"), metadata.getDateStamp());
- assertEquals("20090901", metadata.getMetadataIdentifier().getCode());
- assertEquals(Locale.ENGLISH, getSingleton(metadata.getLocalesAndCharsets().keySet()));
- assertEquals(StandardCharsets.UTF_8, getSingleton(metadata.getLocalesAndCharsets().values()));
- assertEquals(LocalDate.of(2014, 1, 4), TemporalDate.toTemporal(getSingleton(metadata.getDateInfo()).getDate()));
++ assertEquals("20090901", metadata.getFileIdentifier());
++ assertEquals(Locale.ENGLISH, metadata.getLanguage());
++ assertEquals(CharacterSet.UTF_8, metadata.getCharacterSet());
++ assertEquals(LocalDate.of(2014, 1, 4), TemporalDate.toTemporal(metadata.getDateStamp()));
/*
* <gmd:contact>
* <gmd:CI_ResponsibleParty>
diff --cc endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Period.java
index 9187bc9c74,a6eeffe0b8..f8ccb863ff
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Period.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/geoapi/temporal/Period.java
@@@ -14,31 -14,32 +14,31 @@@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sis.xml.bind.referencing;
+package org.apache.sis.pending.geoapi.temporal;
- import java.time.Instant;
-import org.opengis.referencing.datum.VerticalDatumType;
-import org.apache.sis.xml.bind.gml.CodeListAdapter;
++import java.time.temporal.Temporal;
+import org.opengis.temporal.TemporalPrimitive;
/**
- * JAXB adapter for (un)marshalling of GeoAPI code list.
+ * Placeholder for a GeoAPI interfaces not present in GeoAPI 3.0.
*
* @author Martin Desruisseaux (Geomatys)
+ * @since 0.3
+ * @version 1.5
*/
-@SuppressWarnings("deprecation")
-public final class CD_VerticalDatumType extends CodeListAdapter<VerticalDatumType> {
+public interface Period extends TemporalPrimitive {
/**
- * Empty constructor for JAXB only.
+ * Links this period to the instant at which it ends.
+ *
+ * @return The beginning instant.
*/
- Instant getBeginning();
- public CD_VerticalDatumType() {
- }
++ Temporal getBeginning();
/**
- * {@inheritDoc}
+ * Links this period to the instant at which it ends.
*
- * @return {@code VerticalDatumType.class}
+ * @return The end instant.
*/
- Instant getEnding();
- @Override
- protected Class<VerticalDatumType> getCodeListClass() {
- return VerticalDatumType.class;
- }
++ Temporal getEnding();
}
diff --cc optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/IdentificationInfo.java
index 7a32422577,08a6632288..e5617a1c59
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/IdentificationInfo.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/IdentificationInfo.java
@@@ -363,9 -364,9 +362,9 @@@ final class IdentificationInfo extends
*/
text = null;
Identifier identifier = null;
- Range<Instant> timeRange = null;
+ Range<Date> timeRange = null;
Range<Double> heights = null;
- for (final Extent extent : nonNull(info.getExtents())) {
+ for (final Extent extent : nonNull(dataInfo != null ? dataInfo.getExtents() : null)) {
if (extent != null) {
if (text == null) {
text = owner.string(extent.getDescription());