diff --git a/pom.xml b/pom.xml index 74904364..2c2064d7 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.openeo openeo-opensearch-client - 1.3.1_2.12-SNAPSHOT + 1.4.0_2.12-SNAPSHOT UTF-8 diff --git a/src/main/scala/org/openeo/opensearch/OpenSearchResponses.scala b/src/main/scala/org/openeo/opensearch/OpenSearchResponses.scala index 2cbd2bad..1b2df770 100644 --- a/src/main/scala/org/openeo/opensearch/OpenSearchResponses.scala +++ b/src/main/scala/org/openeo/opensearch/OpenSearchResponses.scala @@ -750,6 +750,16 @@ object OpenSearchResponses { suffixes.map(s=>Link(URI.create(s"${getGDALPrefix(path)}$path/${prefix}_$s.tif"),Some(s))) } + private def getGlobalMosaicsSentinel1FilePaths(path: String): Seq[Link] = { + val bandNames = + if (path contains "_IW_") Seq("VH", "VV") + else if (path contains "_DH_") Seq("HH", "HV") + else throw new IllegalArgumentException(path) + + bandNames + .map(bandName => Link(URI.create(s"${getGDALPrefix(path)}$path/$bandName.tif"), title = Some(bandName))) + } + private def ensureValidGeometry(geometry: Json): Json = { // TODO: This is required because the old Creodias API can return incorrect MultiPolygon geometries. // This can be removed once the API is fixed. @@ -834,6 +844,8 @@ object OpenSearchResponses { getLandsat8FilePaths(path = f.id).toArray } else if (f.id.startsWith("/eodata/Sentinel-1-RTC")) { getSentinel1RTCFilePaths(path = f.id).toArray + } else if (f.id.startsWith("/eodata/Global-Mosaics/Sentinel-1")) { + getGlobalMosaicsSentinel1FilePaths(path = f.id).toArray } else { f.links } diff --git a/src/test/resources/org/openeo/creodiasGlobalMosaicsSentinel1.json b/src/test/resources/org/openeo/creodiasGlobalMosaicsSentinel1.json new file mode 100644 index 00000000..db793e8e --- /dev/null +++ b/src/test/resources/org/openeo/creodiasGlobalMosaicsSentinel1.json @@ -0,0 +1,137 @@ +{ + "type": "FeatureCollection", + "properties": { + "id": "4126eeb8-956b-5bd0-b6d8-99cf088365fb", + "totalResults": null, + "exactCount": 0, + "startIndex": 1, + "itemsPerPage": 1000, + "query": { + "originalFilters": { + "box": "116.56784977351838,33.818177847881614,116.67755861181377,33.88958185515551", + "status": "ONLINE", + "dataset": "ESA-DATASET", + "platform": "SENTINEL-1", + "startDate": "2023-09-01T00:00:00Z", + "completionDate": "2024-10-01T00:00:00Z", + "collection": "GLOBAL-MOSAICS" + }, + "appliedFilters": { + "box": "116.56784977351838,33.818177847881614,116.67755861181377,33.88958185515551", + "status": "ONLINE", + "dataset": "ESA-DATASET", + "platform": "SENTINEL-1", + "startDate": "2023-09-01T00:00:00Z", + "completionDate": "2024-10-01T00:00:00Z", + "collection": "GLOBAL-MOSAICS" + }, + "processingTime": 0.812684961 + }, + "links": [ + { + "rel": "self", + "type": "application/json", + "title": "self", + "href": "https://catalogue.dataspace.copernicus.eu/resto/api/collections/GLOBAL-MOSAICS/search.json?box=116.56784977351838%2C33.818177847881614%2C116.67755861181377%2C33.88958185515551&page=1&maxRecords=1000&status=ONLINE&dataset=ESA-DATASET&platform=SENTINEL-1&startDate=2023-09-01T00%3A00%3A00Z&completionDate=2024-10-01T00%3A00%3A00Z" + }, + { + "rel": "search", + "type": "application/opensearchdescription+xml", + "title": "OpenSearch Description Document", + "href": "https://catalogue.dataspace.copernicus.eu/resto/api/collections/GLOBAL-MOSAICS/describe.xml" + } + ] + }, + "features": [ + { + "type": "Feature", + "id": "e605002a-63a5-49ca-9abf-7e65c6d94f6a", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 115.923810175081, + 33.4343643656752 + ], + [ + 115.912416716213, + 34.3368332245052 + ], + [ + 117.000434893879, + 34.3416634578714 + ], + [ + 117.000430336879, + 33.4390338814186 + ], + [ + 115.923810175081, + 33.4343643656752 + ] + ] + ] + }, + "properties": { + "collection": "GLOBAL-MOSAICS", + "status": "ONLINE", + "license": { + "licenseId": "unlicensed", + "hasToBeSigned": "never", + "grantedCountries": null, + "grantedOrganizationCountries": null, + "grantedFlags": null, + "viewService": "public", + "signatureQuota": -1, + "description": { + "shortName": "No license" + } + }, + "parentIdentifier": null, + "title": "Sentinel-1_IW_mosaic_2023_M12_50SMC_0_0", + "description": null, + "organisationName": null, + "startDate": "2023-12-01T00:00:00.000Z", + "completionDate": "2023-12-31T23:59:59.000Z", + "productType": "S1SAR_L3_IW_MCM", + "processingLevel": null, + "platform": "SENTINEL-1", + "instrument": null, + "resolution": 0, + "sensorMode": null, + "orbitNumber": 0, + "quicklook": null, + "thumbnail": null, + "updated": "2024-06-19T03:28:32.729Z", + "published": "2024-06-19T03:28:32.729Z", + "snowCover": 0, + "cloudCover": 0, + "gmlgeometry": "115.923810175081,33.4343643656752 115.912416716213,34.3368332245052 117.000434893879,34.3416634578714 117.000430336879,33.4390338814186 115.923810175081,33.4343643656752", + "centroid": { + "type": "Point", + "coordinates": [ + 116.459279094554, + 33.8887658994282 + ] + }, + "productIdentifier": "/eodata/Global-Mosaics/Sentinel-1/S1SAR_L3_IW_MCM/2023/12/01/Sentinel-1_IW_mosaic_2023_M12_50SMC_0_0", + "services": { + "download": { + "url": "https://catalogue.dataspace.copernicus.eu/download/e605002a-63a5-49ca-9abf-7e65c6d94f6a", + "mimeType": "application/octet-stream", + "size": -1 + } + }, + "links": [ + { + "rel": "self", + "type": "application/json", + "title": "GeoJSON link for e605002a-63a5-49ca-9abf-7e65c6d94f6a", + "href": "https://catalogue.dataspace.copernicus.eu/resto/collections/GLOBAL-MOSAICS/e605002a-63a5-49ca-9abf-7e65c6d94f6a.json" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/src/test/scala/org/openeo/opensearch/CreoFeatureCollectionTest.scala b/src/test/scala/org/openeo/opensearch/CreoFeatureCollectionTest.scala index 96987b74..0d9b27a1 100644 --- a/src/test/scala/org/openeo/opensearch/CreoFeatureCollectionTest.scala +++ b/src/test/scala/org/openeo/opensearch/CreoFeatureCollectionTest.scala @@ -209,4 +209,23 @@ class CreoFeatureCollectionTest { assertTrue(featureIds.forall(_.startsWith("/eodata/Sentinel-2")), "unexpected product identifiers") assertFalse(featureIds contains corruptTileProductIdentifier, "corrupt tile is still present") } + + @Test + def globalMosaicsSentinel1Response(): Unit = { + val productsResponse = loadJsonResource("creodiasGlobalMosaicsSentinel1.json") + + val FeatureCollection(_, features) = CreoFeatureCollection.parse(productsResponse, dedup = true) + + val titledHrefs = for { + feature <- features + link <- feature.links + } yield (link.title, link.href.toString) + + val expected = Set( + (Some("VV"), "/eodata/Global-Mosaics/Sentinel-1/S1SAR_L3_IW_MCM/2023/12/01/Sentinel-1_IW_mosaic_2023_M12_50SMC_0_0/VV.tif"), + (Some("VH"), "/eodata/Global-Mosaics/Sentinel-1/S1SAR_L3_IW_MCM/2023/12/01/Sentinel-1_IW_mosaic_2023_M12_50SMC_0_0/VH.tif"), + ) + + assertEquals(expected, titledHrefs.toSet) + } }