diff --git a/dart/geobase/lib/coordinates.dart b/dart/geobase/lib/coordinates.dart index f12d215e..1f0ca873 100644 --- a/dart/geobase/lib/coordinates.dart +++ b/dart/geobase/lib/coordinates.dart @@ -35,5 +35,7 @@ export 'src/coordinates/projection/projection.dart'; export 'src/coordinates/projection/projection_adapter.dart'; export 'src/coordinates/reference/coord_ref_sys.dart'; export 'src/coordinates/reference/coord_ref_sys_resolver.dart'; +export 'src/coordinates/reference/temporal_ref_sys.dart'; +export 'src/coordinates/reference/temporal_ref_sys_resolver.dart'; export 'src/coordinates/scalable/scalable.dart'; export 'src/coordinates/scalable/scalable2i.dart'; diff --git a/dart/geobase/lib/geobase.dart b/dart/geobase/lib/geobase.dart index 968f3b4d..3dade912 100644 --- a/dart/geobase/lib/geobase.dart +++ b/dart/geobase/lib/geobase.dart @@ -52,6 +52,8 @@ export 'src/coordinates/projection/projection.dart'; export 'src/coordinates/projection/projection_adapter.dart'; export 'src/coordinates/reference/coord_ref_sys.dart'; export 'src/coordinates/reference/coord_ref_sys_resolver.dart'; +export 'src/coordinates/reference/temporal_ref_sys.dart'; +export 'src/coordinates/reference/temporal_ref_sys_resolver.dart'; export 'src/coordinates/scalable/scalable.dart'; export 'src/coordinates/scalable/scalable2i.dart'; diff --git a/dart/geobase/lib/src/coordinates/reference/coord_ref_sys_resolver.dart b/dart/geobase/lib/src/coordinates/reference/coord_ref_sys_resolver.dart index 6ea79f00..90eaaed1 100644 --- a/dart/geobase/lib/src/coordinates/reference/coord_ref_sys_resolver.dart +++ b/dart/geobase/lib/src/coordinates/reference/coord_ref_sys_resolver.dart @@ -14,13 +14,13 @@ import '/src/codes/geo_representation.dart'; /// custom instance using [register]). /// /// NOTE: The current version of this resolver class provides only methods -/// [normalizeId], [axisOrder] and [epsg]. In future other methods might be -/// added. +/// [normalizeId], [isGeographic], [axisOrder], [swapXY] and [epsg]. In future +/// other methods might be added. abstract class CoordRefSysResolver { const CoordRefSysResolver._(); /// Normalizes the coordinate reference system identifier to the template - /// `http://www.opengis.net/def/crs/EPSG/0/4326`. + /// `http://www.opengis.net/def/crs/{authority}/{version}/{code}`. /// /// Examples: /// * `http://www.opengis.net/def/crs/EPSG/0/4326` diff --git a/dart/geobase/lib/src/coordinates/reference/temporal_ref_sys.dart b/dart/geobase/lib/src/coordinates/reference/temporal_ref_sys.dart new file mode 100644 index 00000000..3def59e2 --- /dev/null +++ b/dart/geobase/lib/src/coordinates/reference/temporal_ref_sys.dart @@ -0,0 +1,73 @@ +// Copyright (c) 2020-2023 Navibyte (https://navibyte.com). All rights reserved. +// Use of this source code is governed by a “BSD-3-Clause”-style license that is +// specified in the LICENSE file. +// +// Docs: https://github.com/navibyte/geospatial + +import 'package:meta/meta.dart'; + +import 'temporal_ref_sys_resolver.dart'; + +/// Metadata about a temporal coordinate reference system (TRS) identified and +/// specified by [id]. +@immutable +class TemporalRefSys { + /// Metadata about a temporal coordinate reference system (TRS) identified and + /// specified by [id]. + /// + /// No normalization of identifiers is done. + /// + /// See also [TemporalRefSys.normalized]. + const TemporalRefSys.id(this.id); + + /// Metadata about a temporal coordinate reference system (TRS) identified and + /// specified by the normalized identifier of [id]. + /// + /// Normalization: `TemporalRefSysResolver.registry.normalizeId(id)`. + /// + /// The default implementation returns [id] unmodified (however when necessary + /// a custom logic can be registered for [TemporalRefSysResolver]). + TemporalRefSys.normalized(String id) + : id = TemporalRefSysResolver.registry.normalizeId(id); + + /// The temporal coordinate reference system (TRS) identifier. + /// + /// The identifier is authorative, it identifies a well known or referenced + /// specification that defines properties for a temporal coordinate reference + /// system. + /// + /// Examples: + /// * `http://www.opengis.net/def/uom/ISO-8601/0/Gregorian`: dates or + /// timestamps are in the Gregorian calendar and conform to + /// [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html). + final String id; + + /// The temporal coordinate reference system resolved in this order: + /// 1. [temporalRefSys] if it's non-null + /// 2. otherwise `TemporalRefSys.normalized(trs)` if [trs] is non-null + /// 3. otherwise `TemporalRefSys.gregorian` + factory TemporalRefSys.from({ + TemporalRefSys? temporalRefSys, + String? trs, + }) => + temporalRefSys ?? + (trs != null ? TemporalRefSys.normalized(trs) : gregorian); + + /// The temporal coordinate reference system identified by + /// 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian'. + /// + /// References temporal coordinates, dates or timestamps, that are in the + /// Gregorian calendar and conform to + /// [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html). + static const TemporalRefSys gregorian = + TemporalRefSys.id('http://www.opengis.net/def/uom/ISO-8601/0/Gregorian'); + + @override + String toString() => id; + + @override + bool operator ==(Object other) => other is TemporalRefSys && id == other.id; + + @override + int get hashCode => id.hashCode; +} diff --git a/dart/geobase/lib/src/coordinates/reference/temporal_ref_sys_resolver.dart b/dart/geobase/lib/src/coordinates/reference/temporal_ref_sys_resolver.dart new file mode 100644 index 00000000..793b35a3 --- /dev/null +++ b/dart/geobase/lib/src/coordinates/reference/temporal_ref_sys_resolver.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2020-2023 Navibyte (https://navibyte.com). All rights reserved. +// Use of this source code is governed by a “BSD-3-Clause”-style license that is +// specified in the LICENSE file. +// +// Docs: https://github.com/navibyte/geospatial + +// NOTE: implement normalization for the template +// `http://www.opengis.net/def/uom/{authority}/{version}/{code}`. + +/// An abstract class for resolving temporal coordinate reference system +/// information. +/// +/// A resolver can be accessed using [registry] that is initially instantiated +/// with the basic default implementation. It be customized by registering a +/// custom instance using [register]). +/// +/// NOTE: The current version of this resolver class provides only the method +/// [normalizeId]. In future other methods might be added. +abstract class TemporalRefSysResolver { + const TemporalRefSysResolver._(); + + /// Normalizes the temporal coordinate reference system identifier. + /// + /// The normalization logic depends on the resolver of [registry]. + String normalizeId(String id); + + /// The current instance of [TemporalRefSysResolver], initially instantiated + /// with the basic default implementation. + /// + /// Currently the basic default implemention returns identifiers unmodified. + /// + /// NOTE: In future the basic implementation is going to be extended to + /// support also other identifier and more wide normalization logic. + static TemporalRefSysResolver registry = const _BasicTemporalRefSysRegistry(); + + /// Registers a custom instance of [TemporalRefSysResolver], available at + /// static [registry] after calling this. + // ignore: use_setters_to_change_properties + static void register(TemporalRefSysResolver resolver) => + TemporalRefSysResolver.registry = resolver; +} + +class _BasicTemporalRefSysRegistry implements TemporalRefSysResolver { + const _BasicTemporalRefSysRegistry(); + + @override + String normalizeId(String id) { + return id; + } +} diff --git a/dart/geobase/lib/src/meta/extent/geo_extent.dart b/dart/geobase/lib/src/meta/extent/geo_extent.dart index 24d4e7c0..24d5d080 100644 --- a/dart/geobase/lib/src/meta/extent/geo_extent.dart +++ b/dart/geobase/lib/src/meta/extent/geo_extent.dart @@ -8,6 +8,7 @@ import 'package:meta/meta.dart'; import '/src/coordinates/geographic/geobox.dart'; import '/src/coordinates/reference/coord_ref_sys.dart'; +import '/src/coordinates/reference/temporal_ref_sys.dart'; import '/src/meta/time/interval.dart'; import 'spatial_extent.dart'; @@ -31,12 +32,12 @@ class GeoExtent { /// A geospatial extent of one [bbox] and optional [interval]. /// /// A coordinate reference system can be specified by [crs], and a - /// temporal reference system by [trs]. + /// temporal coordinate reference system by [trs]. GeoExtent.single({ required GeoBox bbox, Interval? interval, CoordRefSys crs = CoordRefSys.CRS84, - String trs = 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian', + TemporalRefSys trs = TemporalRefSys.gregorian, }) : _spatial = SpatialExtent.single( bbox, crs: crs, @@ -51,12 +52,12 @@ class GeoExtent { /// A geospatial extent of [boxes] and optional [intervals]. /// /// A coordinate reference system can be specified by [crs], and a - /// temporal reference system by [trs]. + /// temporal coordinate reference system by [trs]. GeoExtent.multi({ required Iterable boxes, Iterable? intervals, CoordRefSys crs = CoordRefSys.CRS84, - String trs = 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian', + TemporalRefSys trs = TemporalRefSys.gregorian, }) : _spatial = SpatialExtent.multi( boxes, crs: crs, diff --git a/dart/geobase/lib/src/meta/extent/temporal_extent.dart b/dart/geobase/lib/src/meta/extent/temporal_extent.dart index 356e32fb..63c923fc 100644 --- a/dart/geobase/lib/src/meta/extent/temporal_extent.dart +++ b/dart/geobase/lib/src/meta/extent/temporal_extent.dart @@ -6,27 +6,31 @@ import 'package:meta/meta.dart'; +import '/src/coordinates/reference/temporal_ref_sys.dart'; import '/src/meta/time/interval.dart'; -/// An extent with 1 to N intervals in defined temporal reference system. +/// An extent with 1 to N intervals in defined temporal coordinate reference +/// system. @immutable class TemporalExtent { final Interval _first; final Iterable? _intervals; - final String _trs; + final TemporalRefSys _trs; - /// A temporal extent of one [interval] (temporal reference system in [trs]). + /// A temporal extent of one [interval] (temporal coordinate reference system + /// in [trs]). const TemporalExtent.single( Interval interval, { - String trs = 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian', + TemporalRefSys trs = TemporalRefSys.gregorian, }) : _first = interval, _intervals = null, _trs = trs; - /// A temporal extent of [intervals] (temporal reference system in [trs]). + /// A temporal extent of [intervals] (temporal coordinate reference system in + /// [trs]). TemporalExtent.multi( Iterable intervals, { - String trs = 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian', + TemporalRefSys trs = TemporalRefSys.gregorian, }) : _intervals = _validate(intervals), _first = intervals.first, _trs = trs; @@ -44,12 +48,12 @@ class TemporalExtent { /// All intervals for this extent. Iterable get intervals => _intervals ?? [_first]; - /// The temporal reference system for intervals of this extent. - String get trs => _trs; + /// The temporal coordinate reference system for intervals of this extent. + TemporalRefSys get trs => _trs; /// Copy this temporal extent with optional [interval] and/or [trs] /// parameters changed. - TemporalExtent copyWith({Interval? interval, String? trs}) { + TemporalExtent copyWith({Interval? interval, TemporalRefSys? trs}) { if (interval != null) { return TemporalExtent.single(interval, trs: trs ?? _trs); } else { diff --git a/dart/geobase/test/meta/extent_test.dart b/dart/geobase/test/meta/extent_test.dart index 72f85b73..a522d27b 100644 --- a/dart/geobase/test/meta/extent_test.dart +++ b/dart/geobase/test/meta/extent_test.dart @@ -64,7 +64,7 @@ void main() { ); expect(extent1.temporal!.first, interval1); expect( - extent1.temporal!.trs, + extent1.temporal!.trs.toString(), 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian', ); expect(