diff --git a/src/core/stac/qgsstaccollections.cpp b/src/core/stac/qgsstaccollections.cpp index 25680e7841be..87913d64b68c 100644 --- a/src/core/stac/qgsstaccollections.cpp +++ b/src/core/stac/qgsstaccollections.cpp @@ -17,14 +17,14 @@ QgsStacCollections::QgsStacCollections( const QVector< QgsStacCollection * > collections, const QVector< QgsStacLink > links, int numberMatched ) : mCollections( collections ) - , mLinks( links ) , mNumberMatched( numberMatched ) { - for ( const QgsStacLink &link : mLinks ) + for ( const QgsStacLink &link : links ) { if ( link.relation() == QLatin1String( "self" ) || link.relation() == QLatin1String( "root" ) || - link.relation() == QLatin1String( "next" ) ) + link.relation() == QLatin1String( "next" ) || + link.relation() == QLatin1String( "prev" ) ) mUrls.insert( link.relation(), link.href() ); } } @@ -71,3 +71,8 @@ QUrl QgsStacCollections::nextUrl() const { return QUrl( mUrls.value( QStringLiteral( "next" ), QString() ) ); } + +QUrl QgsStacCollections::prevUrl() const +{ + return QUrl( mUrls.value( QStringLiteral( "prev" ), QString() ) ); +} diff --git a/src/core/stac/qgsstaccollections.h b/src/core/stac/qgsstaccollections.h index b23f876afa5d..140455c0da21 100644 --- a/src/core/stac/qgsstaccollections.h +++ b/src/core/stac/qgsstaccollections.h @@ -87,9 +87,13 @@ class CORE_EXPORT QgsStacCollections */ QUrl nextUrl() const; + /** + * Returns the url of the collections' "prev" link + */ + QUrl prevUrl() const; + private: QVector< QgsStacCollection * > mCollections; - const QVector< QgsStacLink > mLinks; QMap< QString, QString > mUrls; int mNumberMatched = -1; }; diff --git a/tests/src/core/testqgsstac.cpp b/tests/src/core/testqgsstac.cpp index 1bfa570aa7fd..12f9d7c97426 100644 --- a/tests/src/core/testqgsstac.cpp +++ b/tests/src/core/testqgsstac.cpp @@ -24,6 +24,8 @@ #include "qgsstaccatalog.h" #include "qgsstaccollection.h" #include "qgsstacitem.h" +#include "qgsstacitemcollection.h" +#include "qgsstaccollections.h" #include "qgsapplication.h" #include "qgsproject.h" #include "qgis.h" @@ -48,6 +50,8 @@ class TestQgsStac : public QObject void testParseLocalCatalog(); void testParseLocalCollection(); void testParseLocalItem(); + void testParseLocalItemCollection(); + void testParseLocalCollections(); private: QString mDataDir; @@ -146,5 +150,50 @@ void TestQgsStac::testParseLocalItem() delete item; } +void TestQgsStac::testParseLocalItemCollection() +{ + const QString fileName = mDataDir + QStringLiteral( "itemcollection-sample-full.json" ); + QgsStacController c; + QgsStacItemCollection *ic = c.fetchItemCollection( QStringLiteral( "file://%1" ).arg( fileName ) ); + QVERIFY( ic ); + QCOMPARE( ic->numberReturned(), 1 ); + QCOMPARE( ic->numberMatched(), 10 ); + QCOMPARE( ic->rootUrl().toString(), QLatin1String( "http://stac.example.com/" ) ); + + QVector items = ic->items(); + QCOMPARE( items.size(), 1 ); + QCOMPARE( items.first()->id(), QLatin1String( "cs3-20160503_132131_05" ) ); + QCOMPARE( items.first()->stacVersion(), QLatin1String( "1.0.0" ) ); + QCOMPARE( items.first()->links().size(), 3 ); + QCOMPARE( items.first()->stacExtensions().size(), 0 ); + QCOMPARE( items.first()->assets().size(), 2 ); + + delete ic; +} + +void TestQgsStac::testParseLocalCollections() +{ + const QString fileName = mDataDir + QStringLiteral( "collectioncollection-sample-full.json" ); + QgsStacController c; + QgsStacCollections *cols = c.fetchCollections( QStringLiteral( "file://%1" ).arg( fileName ) ); + QVERIFY( cols ); + QCOMPARE( cols->numberReturned(), 1 ); + QCOMPARE( cols->numberMatched(), 11 ); + QCOMPARE( cols->rootUrl().toString(), QLatin1String( "http://stac.example.com/" ) ); + QCOMPARE( cols->url().toString(), QLatin1String( "http://stac.example.com/collections?page=2" ) ); + QCOMPARE( cols->nextUrl().toString(), QLatin1String( "http://stac.example.com/collections?page=3" ) ); + QCOMPARE( cols->prevUrl().toString(), QLatin1String( "http://stac.example.com/collections?page=1" ) ); + + QCOMPARE( cols->collections().size(), 1 ); + + QgsStacCollection *col = cols->collections().first(); + QCOMPARE( col->id(), QStringLiteral( "simple-collection" ) ); + QCOMPARE( col->stacVersion(), QLatin1String( "1.0.0" ) ); + QCOMPARE( col->links().size(), 3 ); + QCOMPARE( col->stacExtensions().size(), 0 ); + + delete cols; +} + QGSTEST_MAIN( TestQgsStac ) #include "testqgsstac.moc" diff --git a/tests/testdata/stac/collectioncollection-sample-full.json b/tests/testdata/stac/collectioncollection-sample-full.json new file mode 100644 index 000000000000..e26616b726df --- /dev/null +++ b/tests/testdata/stac/collectioncollection-sample-full.json @@ -0,0 +1,85 @@ +{ + "collections": [ + { + "id": "simple-collection", + "type": "Collection", + "stac_extensions": [], + "stac_version": "1.0.0", + "description": "A simple collection demonstrating core collection fields in an API", + "title": "Simple Example Collection", + "providers": [ + { + "name": "Remote Data, Inc", + "description": "Producers of awesome spatiotemporal assets", + "roles": [ + "producer", + "processor" + ], + "url": "http://remotedata.io" + } + ], + "extent": { + "spatial": { + "bbox": [ + [ + 172.91173669923782, + 1.3438851951615003, + 172.95469614953714, + 1.3690476620161975 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2020-12-11T22:38:32.125Z", + "2020-12-14T18:02:31.437Z" + ] + ] + } + }, + "license": "CC-BY-4.0", + "links": [ + { + "rel": "root", + "href": "http://stac.example.com/", + "type": "application/json" + }, + { + "rel": "items", + "href": "http://stac.example.com/collections/simple-collection/items", + "type": "application/geo+json" + }, + { + "rel": "self", + "href": "http://stac.example.com/collections/simple-collection", + "type": "application/json" + } + ] + } + ], + "links": [ + { + "rel": "self", + "href": "http://stac.example.com/collections?page=2", + "type": "application/json" + }, + { + "rel": "root", + "href": "http://stac.example.com/", + "type": "application/json" + }, + { + "rel": "next", + "href": "http://stac.example.com/collections?page=3", + "type": "application/json" + }, + { + "rel": "prev", + "href": "http://stac.example.com/collections?page=1", + "type": "application/json" + } + ], + "numberMatched": 11, + "numberReturned": 1 +} diff --git a/tests/testdata/stac/itemcollection-sample-full.json b/tests/testdata/stac/itemcollection-sample-full.json new file mode 100644 index 000000000000..e2fe86b5d0cb --- /dev/null +++ b/tests/testdata/stac/itemcollection-sample-full.json @@ -0,0 +1,101 @@ +{ + "type": "FeatureCollection", + "numberMatched": 10, + "numberReturned": 1, + "features": [ + { + "stac_version": "1.0.0", + "stac_extensions": [], + "type": "Feature", + "id": "cs3-20160503_132131_05", + "bbox": [ + -122.59750209, + 37.48803556, + -122.2880486, + 37.613537207 + ], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -122.308150179, + 37.488035566 + ], + [ + -122.597502109, + 37.538869539 + ], + [ + -122.576687533, + 37.613537207 + ], + [ + -122.288048600, + 37.562818007 + ], + [ + -122.308150179, + 37.488035566 + ] + ] + ] + }, + "properties": { + "datetime": "2016-05-03T13:22:30.040Z", + "title": "A CS3 item", + "license": "PDDL-1.0", + "providers": [ + { + "name": "CoolSat", + "roles": [ + "producer", + "licensor" + ], + "url": "https://stac-api.example.com" + } + ] + }, + "collection": "cs3", + "links": [ + { + "rel": "self", + "type": "application/json", + "href": "https://stac-api.example.com/collections/cs3/items/CS3-20160503_132131_05" + }, + { + "rel": "root", + "type": "application/json", + "href": "https://stac-api.example.com/" + }, + { + "rel": "collection", + "type": "application/json", + "href": "https://stac-api.example.com/collections/cs3" + } + ], + "assets": { + "analytic": { + "href": "https://stac-api.example.com/catalog/cs3-20160503_132130_04/analytic.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "4-Band Analytic" + }, + "thumbnail": { + "href": "https://stac-api.example.com/catalog/cs3-20160503_132130_04/thumbnail.png", + "type": "image/png", + "title": "Thumbnail", + "roles": [ + "thumbnail" + ] + } + } + } + ], + "links": [ + { + "rel": "root", + "href": "http://stac.example.com/", + "type": "application/json" + } + ] +} \ No newline at end of file