Skip to content

Commit

Permalink
make 'extensions' as nested maps
Browse files Browse the repository at this point in the history
  • Loading branch information
kb0 committed Dec 5, 2024
1 parent 426a6e9 commit d563967
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 56 deletions.
6 changes: 3 additions & 3 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ linter:
- always_declare_return_types
- always_put_control_body_on_new_line
- always_put_required_named_parameters_first
- always_require_non_null_named_parameters
# - always_require_non_null_named_parameters
# - always_specify_types
- annotate_overrides
- avoid_annotating_with_dynamic
Expand All @@ -26,8 +26,8 @@ linter:
- avoid_relative_lib_imports
- avoid_renaming_method_parameters
- avoid_return_types_on_setters
- avoid_returning_null
- avoid_returning_null_for_future
# - avoid_returning_null
# - avoid_returning_null_for_future
- avoid_returning_null_for_void
- avoid_returning_this
- avoid_setters_without_getters
Expand Down
61 changes: 36 additions & 25 deletions lib/src/gpx_reader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,39 @@ class GpxReader {
return string;
}

Object? _readMap(Iterator<XmlEvent> iterator, String tagName) {
final elm = iterator.current;
if (!(elm is XmlStartElementEvent &&
elm.name == tagName &&
!elm.isSelfClosing)) {
return null;
}

final valueMap = <String, Object>{};
String? valueText;
while (iterator.moveNext()) {
final val = iterator.current;

if (val is XmlStartElementEvent) {
valueMap[val.name] = _readMap(iterator, val.name) ?? {};
}

if (val is XmlTextEvent) {
valueText = val.value;
}

if (val is XmlCDATAEvent) {
valueText = val.value;
}

if (val is XmlEndElementEvent && val.name == tagName) {
break;
}
}

return valueMap.isNotEmpty ? valueMap : valueText;
}

Trkseg _readSegment(Iterator<XmlEvent> iterator) {
final trkseg = Trkseg();
final elm = iterator.current;
Expand Down Expand Up @@ -407,31 +440,9 @@ class GpxReader {
return trkseg;
}

Map<String, String> _readExtensions(Iterator<XmlEvent> iterator) {
final exts = <String, String>{};
final elm = iterator.current;

/*if (elm is XmlStartElementEvent) {
link.href = elm.attributes
.firstWhere((attr) => attr.name == GpxTagV11.href)
.value;
}*/

if ((elm is XmlStartElementEvent) && !elm.isSelfClosing) {
while (iterator.moveNext()) {
final val = iterator.current;

if (val is XmlStartElementEvent) {
exts[val.name] = _readString(iterator, val.name) ?? '';
}

if (val is XmlEndElementEvent && val.name == GpxTagV11.extensions) {
break;
}
}
}

return exts;
Map<String, Object> _readExtensions(Iterator<XmlEvent> iterator) {
final exts = _readMap(iterator, GpxTagV11.extensions) ?? {};
return (exts is Map<String, Object>) ? exts : {};
}

Link _readLink(Iterator<XmlEvent> iterator) {
Expand Down
12 changes: 10 additions & 2 deletions lib/src/gpx_writer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class GpxWriter {
}
}

void _writeExtensions(XmlBuilder builder, Map<String, String>? value) {
void _writeExtensions(XmlBuilder builder, Map<String, Object>? value) {
if (value != null && value.isNotEmpty) {
builder.element(GpxTagV11.extensions, nest: () {
value.forEach((k, v) {
Expand All @@ -216,7 +216,15 @@ class GpxWriter {

void _writeElement(XmlBuilder builder, String tagName, Object? value) {
if (value != null) {
builder.element(tagName, nest: value);
if (value is Map) {
builder.element(tagName, nest: () {
value.forEach((k, v) {
_writeElement(builder, k, v);
});
});
} else {
builder.element(tagName, nest: value);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/src/model/gpx.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Gpx {

/// You can add extend GPX by adding your own elements from another schema
/// here.
Map<String, String> extensions = {};
Map<String, Object> extensions = {};

@override
// ignore: type_annotate_public_apis
Expand All @@ -44,7 +44,7 @@ class Gpx {
const ListEquality().equals(other.wpts, wpts) &&
const ListEquality().equals(other.rtes, rtes) &&
const ListEquality().equals(other.trks, trks) &&
const MapEquality().equals(other.extensions, extensions);
const DeepCollectionEquality().equals(other.extensions, extensions);
}

return false;
Expand Down
8 changes: 4 additions & 4 deletions lib/src/model/metadata.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Metadata {

/// You can add extend GPX by adding your own elements from another schema
/// here.
Map<String, String> extensions = {};
Map<String, Object> extensions = {};

/// Construct a new [Metadata] object.
Metadata(
Expand All @@ -50,9 +50,9 @@ class Metadata {
this.time,
this.keywords,
this.bounds,
Map<String, String>? extensions})
Map<String, Object>? extensions})
: links = links ?? [],
extensions = extensions ?? <String, String>{};
extensions = extensions ?? <String, Object>{};

@override
// ignore: type_annotate_public_apis
Expand All @@ -66,7 +66,7 @@ class Metadata {
other.time == time &&
other.keywords == keywords &&
other.bounds == bounds &&
const MapEquality().equals(other.extensions, extensions);
const DeepCollectionEquality().equals(other.extensions, extensions);
}

return false;
Expand Down
8 changes: 4 additions & 4 deletions lib/src/model/rte.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Rte {

/// You can add extend GPX by adding your own elements from another schema
/// here.
Map<String, String> extensions;
Map<String, Object> extensions;

/// A list of route points.
List<Wpt> rtepts;
Expand All @@ -45,10 +45,10 @@ class Rte {
List<Link>? links,
this.number,
this.type,
Map<String, String>? extensions,
Map<String, Object>? extensions,
List<Wpt>? rtepts})
: links = links ?? [],
extensions = extensions ?? <String, String>{},
extensions = extensions ?? <String, Object>{},
rtepts = rtepts ?? [];

@override
Expand All @@ -62,7 +62,7 @@ class Rte {
const ListEquality().equals(other.links, links) &&
other.number == number &&
other.type == type &&
const MapEquality().equals(other.extensions, extensions) &&
const DeepCollectionEquality().equals(other.extensions, extensions) &&
const ListEquality().equals(other.rtepts, rtepts);
}

Expand Down
8 changes: 4 additions & 4 deletions lib/src/model/trk.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Trk {

/// You can add extend GPX by adding your own elements from another schema
/// here.
Map<String, String> extensions;
Map<String, Object> extensions;

/// A Track Segment holds a list of Track Points which are logically connected
/// in order. To represent a single GPS track where GPS reception was lost, or
Expand All @@ -47,10 +47,10 @@ class Trk {
List<Link>? links,
this.number,
this.type,
Map<String, String>? extensions,
Map<String, Object>? extensions,
List<Trkseg>? trksegs})
: links = links ?? [],
extensions = extensions ?? <String, String>{},
extensions = extensions ?? <String, Object>{},
trksegs = trksegs ?? [];

@override
Expand All @@ -64,7 +64,7 @@ class Trk {
const ListEquality().equals(other.links, links) &&
other.number == number &&
other.type == type &&
const MapEquality().equals(other.extensions, extensions) &&
const DeepCollectionEquality().equals(other.extensions, extensions) &&
const ListEquality().equals(other.trksegs, trksegs);
}

Expand Down
8 changes: 4 additions & 4 deletions lib/src/model/trkseg.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ class Trkseg {

/// You can add extend GPX by adding your own elements from another schema
/// here.
Map<String, String> extensions;
Map<String, Object> extensions;

/// Construct a new [Trkseg] object.
Trkseg({List<Wpt>? trkpts, Map<String, String>? extensions})
Trkseg({List<Wpt>? trkpts, Map<String, Object>? extensions})
: trkpts = trkpts ?? [],
extensions = extensions ?? <String, String>{};
extensions = extensions ?? <String, Object>{};

@override
// ignore: type_annotate_public_apis
bool operator ==(other) {
if (other is Trkseg) {
return const ListEquality().equals(other.trkpts, trkpts) &&
const MapEquality().equals(other.extensions, extensions);
const DeepCollectionEquality().equals(other.extensions, extensions);
}

return false;
Expand Down
8 changes: 4 additions & 4 deletions lib/src/model/wpt.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class Wpt {

/// You can add extend GPX by adding your own elements from another schema
/// here.
Map<String, String> extensions;
Map<String, Object> extensions;

/// Construct a new [Wpt] object.
Wpt(
Expand All @@ -103,9 +103,9 @@ class Wpt {
this.pdop,
this.ageofdgpsdata,
this.dgpsid,
Map<String, String>? extensions})
Map<String, Object>? extensions})
: links = links ?? [],
extensions = extensions ?? <String, String>{};
extensions = extensions ?? <String, Object>{};

@override
// ignore: type_annotate_public_apis
Expand All @@ -131,7 +131,7 @@ class Wpt {
other.pdop == pdop &&
other.ageofdgpsdata == ageofdgpsdata &&
other.dgpsid == dgpsid &&
const MapEquality().equals(other.extensions, extensions);
const DeepCollectionEquality().equals(other.extensions, extensions);
}

return false;
Expand Down
8 changes: 8 additions & 0 deletions test/assets/complex.gpx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
<extensions>
<m1>v1</m1>
<m2>v2</m2>
<mext:ext>
<mext:val>val</mext:val>
<mext:num>10</mext:num>
</mext:ext>
</extensions>
</metadata>
<extensions>
Expand All @@ -23,6 +27,10 @@
<extensions>
<k1>v1</k1>
<k2>v2</k2>
<wext:ext>
<wext:val>val</wext:val>
<wext:num>10</wext:num>
</wext:ext>
</extensions>
</wpt>
<wpt lat="36.62" lon="101.77">
Expand Down
1 change: 1 addition & 0 deletions test/gpx_reader_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void main() {
.fromString(await File('test/assets/complex.gpx').readAsString());
final src = createComplexGPX();

expect(gpx.metadata?.extensions, src.metadata?.extensions);
expect(gpx.metadata, src.metadata);
expect(gpx.extensions, src.extensions);
expect(gpx.trks, src.trks);
Expand Down
6 changes: 4 additions & 2 deletions test/gpx_writer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ void main() {
final xml = await File('test/assets/namespace.gpx').readAsString();

final gpxXml = GpxWriter().asXml(gpx);
gpxXml.children[1].setAttribute("xmlns:trp", "http://www.garmin.com/xmlschemas/TripExtensions/v1");
gpxXml.children[1].setAttribute("xsi:schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd");
gpxXml.children[1].setAttribute(
'xmlns:trp', 'http://www.garmin.com/xmlschemas/TripExtensions/v1');
gpxXml.children[1].setAttribute('xsi:schemaLocation',
'http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd');
expectXml(gpxXml.toXmlString(), xml);
});
}
12 changes: 10 additions & 2 deletions test/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,23 @@ Gpx createComplexGPX() {
gpx.metadata!.time = DateTime.utc(2010, 1, 2, 3, 4, 5);
gpx.metadata!.copyright =
Copyright(author: 'lib', year: 2019, license: 'UNKNOWN');
gpx.metadata!.extensions = {'m1': 'v1', 'm2': 'v2'};
gpx.metadata!.extensions = {
'm1': 'v1',
'm2': 'v2',
'mext:ext': {'mext:val': 'val', 'mext:num': '10'}
};
gpx.wpts = [
Wpt(
lat: -25.7996,
lon: -62.8666,
ele: 10.2,
name: 'Monte Quemado',
desc: 'Argentina',
extensions: {'k1': 'v1', 'k2': 'v2'}),
extensions: {
'k1': 'v1',
'k2': 'v2',
'wext:ext': {'wext:val': 'val', 'wext:num': '10'}
}),
Wpt(lat: 36.62, lon: 101.77, ele: 10.2, name: 'Xining', desc: 'China'),
];
gpx.rtes = [
Expand Down

0 comments on commit d563967

Please sign in to comment.