From 477e68b0011106414777cde6fbbef394f140dfd4 Mon Sep 17 00:00:00 2001 From: bramjanssen Date: Fri, 17 Oct 2025 14:07:03 +0200 Subject: [PATCH 1/7] feat(#235): added platform links to existing records --- .../records/wind_turbine_detection.json | 6 ++++ .../records/eurac_pv_farm_detection.json | 6 ++++ .../terradue/gep_bas/records/gep_bas.json | 6 ++++ .../terradue/gep_ost/records/gep_ost.json | 6 ++++ .../terradue/sar_coin/records/sar_coin.json | 6 ++++ .../records/snap_insar_sentinel1_iw_slc.json | 6 ++++ .../bap_composite/records/bap_composite.json | 8 ++++- .../vito/biopar/records/biopar.json | 6 ++++ .../fusets_mogpr/records/fusets_mogpr.json | 6 ++++ .../records/max_ndvi_composite.json | 6 ++++ .../records/parcel_delineation.json | 6 ++++ .../records/random_forest_firemapping.json | 6 ++++ .../records/sentinel1_stats.json | 8 ++++- .../records/variabilitymap.json | 6 ++++ .../records/worldcereal_crop_extent.json | 6 ++++ .../records/worldcereal_crop_type.json | 9 ++++-- .../records/worldcover_statistics.json | 8 ++++- .../records/wac_inference_africa.json | 6 ++++ .../cdse_openeo_federation.json | 0 .../openeo_platform.json | 0 schemas/record.json | 32 ++++++++++++++++++- 21 files changed, 143 insertions(+), 6 deletions(-) rename {backend_catalog => platform_catalog}/cdse_openeo_federation.json (100%) rename {backend_catalog => platform_catalog}/openeo_platform.json (100%) diff --git a/algorithm_catalog/dhi/wind_turbine/records/wind_turbine_detection.json b/algorithm_catalog/dhi/wind_turbine/records/wind_turbine_detection.json index 4c448a6b..317c8796 100644 --- a/algorithm_catalog/dhi/wind_turbine/records/wind_turbine_detection.json +++ b/algorithm_catalog/dhi/wind_turbine/records/wind_turbine_detection.json @@ -89,6 +89,12 @@ "title": "openEO platform", "href": "https://openeo.cloud" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/openeo_platform.json" + }, { "rel": "webapp", "type": "text/html", diff --git a/algorithm_catalog/eurac/eurac_pv_farm_detection/records/eurac_pv_farm_detection.json b/algorithm_catalog/eurac/eurac_pv_farm_detection/records/eurac_pv_farm_detection.json index 3a36a4c5..5cdb605d 100644 --- a/algorithm_catalog/eurac/eurac_pv_farm_detection/records/eurac_pv_farm_detection.json +++ b/algorithm_catalog/eurac/eurac_pv_farm_detection/records/eurac_pv_farm_detection.json @@ -108,6 +108,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "webapp", "type": "text/html", diff --git a/algorithm_catalog/terradue/gep_bas/records/gep_bas.json b/algorithm_catalog/terradue/gep_bas/records/gep_bas.json index e49f12a8..3b801bbb 100644 --- a/algorithm_catalog/terradue/gep_bas/records/gep_bas.json +++ b/algorithm_catalog/terradue/gep_bas/records/gep_bas.json @@ -95,6 +95,12 @@ "title": "End-User License Agreement", "href": "https://geohazards-tep.eu/downloadFiles/EULA-GEP.pdf" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/gep.json" + }, { "rel": "service", "type": "application/json", diff --git a/algorithm_catalog/terradue/gep_ost/records/gep_ost.json b/algorithm_catalog/terradue/gep_ost/records/gep_ost.json index 62417eca..0677fa74 100644 --- a/algorithm_catalog/terradue/gep_ost/records/gep_ost.json +++ b/algorithm_catalog/terradue/gep_ost/records/gep_ost.json @@ -95,6 +95,12 @@ "title": "End-User License Agreement", "href": "https://geohazards-tep.eu/downloadFiles/EULA-GEP.pdf" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/gep.json" + }, { "rel": "service", "type": "application/json", diff --git a/algorithm_catalog/terradue/sar_coin/records/sar_coin.json b/algorithm_catalog/terradue/sar_coin/records/sar_coin.json index 09bcf5a7..53e971bf 100644 --- a/algorithm_catalog/terradue/sar_coin/records/sar_coin.json +++ b/algorithm_catalog/terradue/sar_coin/records/sar_coin.json @@ -94,6 +94,12 @@ "title": "End-User License Agreement", "href": "https://geohazards-tep.eu/downloadFiles/EULA-GEP.pdf" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/gep.json" + }, { "rel": "service", "type": "application/json", diff --git a/algorithm_catalog/terradue/snap_insar_sentinel1_iw_slc/records/snap_insar_sentinel1_iw_slc.json b/algorithm_catalog/terradue/snap_insar_sentinel1_iw_slc/records/snap_insar_sentinel1_iw_slc.json index e050da41..5fc40dc2 100644 --- a/algorithm_catalog/terradue/snap_insar_sentinel1_iw_slc/records/snap_insar_sentinel1_iw_slc.json +++ b/algorithm_catalog/terradue/snap_insar_sentinel1_iw_slc/records/snap_insar_sentinel1_iw_slc.json @@ -95,6 +95,12 @@ "title": "End-User License Agreement", "href": "https://geohazards-tep.eu/downloadFiles/EULA-GEP.pdf" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/gep.json" + }, { "rel": "service", "type": "application/json", diff --git a/algorithm_catalog/vito/bap_composite/records/bap_composite.json b/algorithm_catalog/vito/bap_composite/records/bap_composite.json index a93a8eff..348c1886 100644 --- a/algorithm_catalog/vito/bap_composite/records/bap_composite.json +++ b/algorithm_catalog/vito/bap_composite/records/bap_composite.json @@ -101,6 +101,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "example-output", "type": "application/json", @@ -120,4 +126,4 @@ "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/algorithm_catalog/vito/bap_composite/records/thumbnail.png" } ] -} +} \ No newline at end of file diff --git a/algorithm_catalog/vito/biopar/records/biopar.json b/algorithm_catalog/vito/biopar/records/biopar.json index 5e7932ab..c0b7445b 100644 --- a/algorithm_catalog/vito/biopar/records/biopar.json +++ b/algorithm_catalog/vito/biopar/records/biopar.json @@ -114,6 +114,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "example-output", "type": "image/tif", diff --git a/algorithm_catalog/vito/fusets_mogpr/records/fusets_mogpr.json b/algorithm_catalog/vito/fusets_mogpr/records/fusets_mogpr.json index 1bc09ee8..a1abace5 100644 --- a/algorithm_catalog/vito/fusets_mogpr/records/fusets_mogpr.json +++ b/algorithm_catalog/vito/fusets_mogpr/records/fusets_mogpr.json @@ -128,6 +128,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "about", "type": "text/html", diff --git a/algorithm_catalog/vito/max_ndvi_composite/records/max_ndvi_composite.json b/algorithm_catalog/vito/max_ndvi_composite/records/max_ndvi_composite.json index 893329ac..5347afc3 100644 --- a/algorithm_catalog/vito/max_ndvi_composite/records/max_ndvi_composite.json +++ b/algorithm_catalog/vito/max_ndvi_composite/records/max_ndvi_composite.json @@ -104,6 +104,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "example-output", "type": "application/json", diff --git a/algorithm_catalog/vito/parcel_delineation/records/parcel_delineation.json b/algorithm_catalog/vito/parcel_delineation/records/parcel_delineation.json index b9a4d2e6..0a5b6671 100644 --- a/algorithm_catalog/vito/parcel_delineation/records/parcel_delineation.json +++ b/algorithm_catalog/vito/parcel_delineation/records/parcel_delineation.json @@ -105,6 +105,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "webapp", "type": "text/html", diff --git a/algorithm_catalog/vito/random_forest_firemapping/records/random_forest_firemapping.json b/algorithm_catalog/vito/random_forest_firemapping/records/random_forest_firemapping.json index 014e4def..e5d751fe 100644 --- a/algorithm_catalog/vito/random_forest_firemapping/records/random_forest_firemapping.json +++ b/algorithm_catalog/vito/random_forest_firemapping/records/random_forest_firemapping.json @@ -99,6 +99,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "example-output", "type": "image/tif", diff --git a/algorithm_catalog/vito/sentinel1_stats/records/sentinel1_stats.json b/algorithm_catalog/vito/sentinel1_stats/records/sentinel1_stats.json index ca3ffa95..e901440e 100644 --- a/algorithm_catalog/vito/sentinel1_stats/records/sentinel1_stats.json +++ b/algorithm_catalog/vito/sentinel1_stats/records/sentinel1_stats.json @@ -105,6 +105,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "example-output", "type": "application/netcdf", @@ -124,4 +130,4 @@ "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/algorithm_catalog/vito/sentinel1_stats/records/thumbnail.png" } ] -} +} \ No newline at end of file diff --git a/algorithm_catalog/vito/variabilitymap/records/variabilitymap.json b/algorithm_catalog/vito/variabilitymap/records/variabilitymap.json index c256adc1..97f87123 100644 --- a/algorithm_catalog/vito/variabilitymap/records/variabilitymap.json +++ b/algorithm_catalog/vito/variabilitymap/records/variabilitymap.json @@ -125,6 +125,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "example-output", "type": "application/netcdf", diff --git a/algorithm_catalog/vito/worldcereal_crop_extent/records/worldcereal_crop_extent.json b/algorithm_catalog/vito/worldcereal_crop_extent/records/worldcereal_crop_extent.json index cddf272e..b15381eb 100644 --- a/algorithm_catalog/vito/worldcereal_crop_extent/records/worldcereal_crop_extent.json +++ b/algorithm_catalog/vito/worldcereal_crop_extent/records/worldcereal_crop_extent.json @@ -108,6 +108,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "about", "type": "text/html", diff --git a/algorithm_catalog/vito/worldcereal_crop_type/records/worldcereal_crop_type.json b/algorithm_catalog/vito/worldcereal_crop_type/records/worldcereal_crop_type.json index 5e9e749c..5ed31d6b 100644 --- a/algorithm_catalog/vito/worldcereal_crop_type/records/worldcereal_crop_type.json +++ b/algorithm_catalog/vito/worldcereal_crop_type/records/worldcereal_crop_type.json @@ -108,6 +108,12 @@ "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "about", "type": "text/html", @@ -132,6 +138,5 @@ "title": "Thumbnail image", "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/algorithm_catalog/vito/worldcereal_crop_type/records/thumbnail.png" } - ] -} +} \ No newline at end of file diff --git a/algorithm_catalog/vito/worldcover_statistics/records/worldcover_statistics.json b/algorithm_catalog/vito/worldcover_statistics/records/worldcover_statistics.json index df7c05e0..053a6919 100644 --- a/algorithm_catalog/vito/worldcover_statistics/records/worldcover_statistics.json +++ b/algorithm_catalog/vito/worldcover_statistics/records/worldcover_statistics.json @@ -87,6 +87,12 @@ "title": "openEO platform", "href": "https://openeofed.dataspace.copernicus.eu" }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" + }, { "rel": "webapp", "type": "text/html", @@ -100,4 +106,4 @@ "href": "https://doi.org/10.5281/zenodo.7254221" } ] -} +} \ No newline at end of file diff --git a/algorithm_catalog/wur/worldagrocommodities/records/wac_inference_africa.json b/algorithm_catalog/wur/worldagrocommodities/records/wac_inference_africa.json index 3c4919d9..8a77c5ad 100644 --- a/algorithm_catalog/wur/worldagrocommodities/records/wac_inference_africa.json +++ b/algorithm_catalog/wur/worldagrocommodities/records/wac_inference_africa.json @@ -99,6 +99,12 @@ "type": "application/json", "title": "CDSE openEO federation", "href": "https://openeofed.dataspace.copernicus.eu" + }, + { + "rel": "platform", + "type": "application/json", + "title": "CDSE openEO federation", + "href": "https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/cdse_openeo_federation.json" } ] } \ No newline at end of file diff --git a/backend_catalog/cdse_openeo_federation.json b/platform_catalog/cdse_openeo_federation.json similarity index 100% rename from backend_catalog/cdse_openeo_federation.json rename to platform_catalog/cdse_openeo_federation.json diff --git a/backend_catalog/openeo_platform.json b/platform_catalog/openeo_platform.json similarity index 100% rename from backend_catalog/openeo_platform.json rename to platform_catalog/openeo_platform.json diff --git a/schemas/record.json b/schemas/record.json index ada4ebd3..2be782d5 100644 --- a/schemas/record.json +++ b/schemas/record.json @@ -424,6 +424,7 @@ "type": "string", "description": "The type or semantics of the relation.", "enum": [ + "platform", "application", "service", "example-output", @@ -457,7 +458,26 @@ "type", "title", "href" - ] + ], + "if": { + "properties": { + "rel": { + "const": "platform" + } + } + }, + "then": { + "properties": { + "href": { + "type": "string", + "description": "Platform record URI (must point into platform_catalog).", + "pattern": "^https://raw.githubusercontent.com/ESA-APEx/apex_algorithms/refs/heads/main/platform_catalog/[^\\s]+\\.json$" + } + }, + "required": [ + "href" + ] + } }, "minItems": 2, "allOf": [ @@ -480,6 +500,16 @@ } } } + }, + { + "contains": { + "type": "object", + "properties": { + "rel": { + "const": "platform" + } + } + } } ] } From c3d25184c6227a91c46cb92428108ae518b54387 Mon Sep 17 00:00:00 2001 From: bramjanssen Date: Fri, 17 Oct 2025 14:19:50 +0200 Subject: [PATCH 2/7] feat(#235): added platform records --- platform_catalog/cdse_openeo_federation.json | 10 ++- platform_catalog/gep.json | 77 ++++++++++++++++++++ platform_catalog/openeo_platform.json | 10 ++- 3 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 platform_catalog/gep.json diff --git a/platform_catalog/cdse_openeo_federation.json b/platform_catalog/cdse_openeo_federation.json index 6768b8e6..98acd7e3 100644 --- a/platform_catalog/cdse_openeo_federation.json +++ b/platform_catalog/cdse_openeo_federation.json @@ -56,7 +56,7 @@ "linkTemplates": [], "links": [ { - "rel": "alternate", + "rel": "documentation", "type": "text/html", "title": "CDSE openEO documentation", "href": "https://documentation.dataspace.copernicus.eu/APIs/openEO/openEO.html" @@ -66,6 +66,12 @@ "type": "application/json", "title": "openEO service", "href": "https://openeofed.dataspace.copernicus.eu" + }, + { + "rel": "logo", + "type": "image/svg+xml", + "title": "CDSE Logo", + "href": "https://dataspace.copernicus.eu/themes/custom/copernicus/logonew.svg" } ] -} +} \ No newline at end of file diff --git a/platform_catalog/gep.json b/platform_catalog/gep.json new file mode 100644 index 00000000..e6bf4dbd --- /dev/null +++ b/platform_catalog/gep.json @@ -0,0 +1,77 @@ +{ + "id": "gep", + "type": "Feature", + "conformsTo": [ + "http://www.opengis.net/spec/ogcapi-records-1/1.0/req/record-core" + ], + "properties": { + "created": "2024-05-17T00:00:00Z", + "updated": "2024-05-17T00:00:00Z", + "type": "ogc_backend", + "title": "Geohazards Exploitation Platform", + "description": "", + "keywords": [ + "ogc", + "data analysis", + "platform as a service" + ], + "language": { + "code": "en-US", + "name": "English (United States)" + }, + "languages": [ + { + "code": "en-US", + "name": "English (United States)" + } + ], + "contacts": [ + { + "name": "Platform team", + "organization": "Geohazards Exploitation Platform (GEP) by Terradue", + "position": "Customer Relations", + "roles": [ + "user on-boarding", + "platform operations", + "stakeholder engagement" + ], + "links": [ + { + "href": "https://geohazards-tep.eu", + "title": "Geohazards Exploitation Platform", + "rel": "about", + "type": "text/html" + } + ], + "contactInstructions": "For inquiries on selecting Processing Services from the GEP Portfolio, and on budgeting the processing costs for your study areas, please email the Platform team at Terradue", + "email": "contact@geohazards-tep.eu" + } + ], + "themes": [ + { + "concepts": [ + { + "id": "DATA ANALYSIS" + } + ], + "scheme": "https://gcmd.earthdata.nasa.gov/kms/concepts/concept_scheme/sciencekeywords" + } + ], + "license": "other" + }, + "linkTemplates": [], + "links": [ + { + "rel": "service", + "type": "application/json", + "title": "OGC API Processes Service Endpoint", + "href": "https://ades.gep.terradue.com/gep/wps3/processes" + }, + { + "rel": "logo", + "type": "image/png", + "title": "GEP Logo", + "href": "https://geohazards-tep.eu/styles/img/logo-geohazard-by-terradue.png" + } + ] +} \ No newline at end of file diff --git a/platform_catalog/openeo_platform.json b/platform_catalog/openeo_platform.json index 2f587a9f..2ccef841 100644 --- a/platform_catalog/openeo_platform.json +++ b/platform_catalog/openeo_platform.json @@ -56,7 +56,7 @@ "linkTemplates": [], "links": [ { - "rel": "alternate", + "rel": "documentation", "type": "text/html", "title": "openEO platform documentation", "href": "https://docs.openeo.cloud" @@ -66,6 +66,12 @@ "type": "application/json", "title": "openEO service", "href": "https://openeo.cloud" + }, + { + "rel": "logo", + "type": "image/svg+xml", + "title": "openEO Platform Logo", + "href": "https://openeo.cloud/wp-content/uploads/2023/10/logo-openeoplatform-wide-darkmode.svg" } ] -} +} \ No newline at end of file From 443ec52701e8b3fb4ba08d6be4853df083e7ffb3 Mon Sep 17 00:00:00 2001 From: bramjanssen Date: Fri, 17 Oct 2025 14:36:18 +0200 Subject: [PATCH 3/7] feat(#235): added validation of the platform records --- platform_catalog/cdse_openeo_federation.json | 1 + platform_catalog/openeo_platform.json | 1 + qa/tools/apex_algorithm_qa_tools/__init__.py | 2 +- qa/tools/apex_algorithm_qa_tools/records.py | 24 +- qa/unittests/tests/test_records.py | 36 +- schemas/platform.json | 407 +++++++++++++++++++ 6 files changed, 459 insertions(+), 12 deletions(-) create mode 100644 schemas/platform.json diff --git a/platform_catalog/cdse_openeo_federation.json b/platform_catalog/cdse_openeo_federation.json index 98acd7e3..f1c0547d 100644 --- a/platform_catalog/cdse_openeo_federation.json +++ b/platform_catalog/cdse_openeo_federation.json @@ -32,6 +32,7 @@ { "href": "https://www.vito.be/", "rel": "about", + "title": "VITO", "type": "text/html" } ], diff --git a/platform_catalog/openeo_platform.json b/platform_catalog/openeo_platform.json index 2ccef841..172b4174 100644 --- a/platform_catalog/openeo_platform.json +++ b/platform_catalog/openeo_platform.json @@ -32,6 +32,7 @@ { "href": "https://openeo.cloud", "rel": "about", + "title": "openEO Platform", "type": "text/html" } ], diff --git a/qa/tools/apex_algorithm_qa_tools/__init__.py b/qa/tools/apex_algorithm_qa_tools/__init__.py index ec757916..00dd7e1c 100644 --- a/qa/tools/apex_algorithm_qa_tools/__init__.py +++ b/qa/tools/apex_algorithm_qa_tools/__init__.py @@ -1,4 +1,4 @@ # TODO #15 Flatten apex_algorithm_qa_tools to a single module and push as much functionality to https://github.com/ESA-APEx/esa-apex-toolbox-python -__version__ = "0.2.0" +__version__ = "0.2.1" diff --git a/qa/tools/apex_algorithm_qa_tools/records.py b/qa/tools/apex_algorithm_qa_tools/records.py index c178fd0d..37af6be2 100644 --- a/qa/tools/apex_algorithm_qa_tools/records.py +++ b/qa/tools/apex_algorithm_qa_tools/records.py @@ -9,15 +9,31 @@ _log = logging.getLogger(__name__) -def _get_ogc_record_schema() -> dict: - with open(get_project_root() / "schemas" / "record.json") as f: +def _get_ogc_record_schema(name: str) -> dict: + with open(get_project_root() / "schemas" / name) as f: return json.load(f) -def get_ogc_records() -> List[Any]: +def get_service_ogc_record_schema() -> dict: + return _get_ogc_record_schema("record.json") + + +def get_platform_ogc_record_schema() -> dict: + return _get_ogc_record_schema("platform.json") + + +def _get_ogc_records(folder: str, glob: str) -> List[Any]: records = [] - for path in (get_project_root() / "algorithm_catalog").glob("**/records/*.json"): + for path in (get_project_root() / folder).glob(glob): with open(path) as f: data = json.load(f) records.append(data) return records + + +def get_service_ogc_records() -> List[Any]: + return _get_ogc_records("algorithm_catalog", "**/records/*.json") + + +def get_platform_ogc_records() -> List[Any]: + return _get_ogc_records("platform_catalog", "*.json") diff --git a/qa/unittests/tests/test_records.py b/qa/unittests/tests/test_records.py index e2e3ccf7..e03d685e 100644 --- a/qa/unittests/tests/test_records.py +++ b/qa/unittests/tests/test_records.py @@ -1,11 +1,21 @@ import jsonschema import pytest -from apex_algorithm_qa_tools.records import get_ogc_records, _get_ogc_record_schema +from apex_algorithm_qa_tools.records import ( + get_service_ogc_records, + get_service_ogc_record_schema, + get_platform_ogc_records, + get_platform_ogc_record_schema, +) + + +def test_get_service_ogc_records(): + records = get_service_ogc_records() + assert len(records) > 0 -def test_get_ogc_records(): - records = get_ogc_records() +def test_get_platform_ogc_records(): + records = get_platform_ogc_records() assert len(records) > 0 @@ -16,9 +26,21 @@ def test_get_ogc_records(): "record", [ # Use scenario id as parameterization id to give nicer test names. - pytest.param(record, id=record['id']) - for record in get_ogc_records() + pytest.param(record, id=record["id"]) + for record in get_service_ogc_records() + ], +) +def test_service_record_validation(record): + jsonschema.validate(instance=record, schema=get_service_ogc_record_schema()) + + +@pytest.mark.parametrize( + "record", + [ + # Use scenario id as parameterization id to give nicer test names. + pytest.param(record, id=record["id"]) + for record in get_platform_ogc_records() ], ) -def test_record_validation(record): - jsonschema.validate(instance=record, schema=_get_ogc_record_schema()) +def test_platform_record_validation(record): + jsonschema.validate(instance=record, schema=get_platform_ogc_record_schema()) diff --git a/schemas/platform.json b/schemas/platform.json new file mode 100644 index 00000000..41ac62db --- /dev/null +++ b/schemas/platform.json @@ -0,0 +1,407 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "APEx Platform - OGC API Record", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The unique identifier for the APEx Service." + }, + "type": { + "type": "string", + "description": "The type of the OGC API Record.", + "enum": [ + "Feature" + ] + }, + "conformsTo": { + "type": "array", + "description": "The extensions/conformance classes used in this record.", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true, + "anyOf": [ + { + "contains": { + "const": "http://www.opengis.net/spec/ogcapi-records-1/1.0/req/record-core" + } + } + ] + }, + "geometry": { + "type": "null" + }, + "properties": { + "type": "object", + "required": [ + "created", + "updated", + "type", + "title", + "description", + "contacts", + "themes" + ], + "properties": { + "created": { + "type": "string", + "description": "Create date/time of the record." + }, + "updated": { + "type": "string", + "description": "Update date/time of the record." + }, + "type": { + "type": "string", + "description": "Type of the OGC API Record", + "enum": [ + "openeo_backend", + "ogc_backend" + ] + }, + "title": { + "type": "string", + "description": "Title of the Platform" + }, + "description": { + "type": "string", + "description": "Description of the Platform" + }, + "keywords": { + "type": "array", + "description": "The topic or topics of the Platform. Typically represented using free-form keywords, tags, key phrases, or classification codes.", + "items": { + "type": "string" + } + }, + "language": { + "description": "The language used for textual values in this record representation.", + "$ref": "#/properties/properties/properties/languages/items" + }, + "languages": { + "type": "array", + "description": "This list of languages in which this record is available.", + "items": { + "type": "object", + "description": "The language used for textual values in this record.", + "required": [ + "code" + ], + "properties": { + "code": { + "type": "string", + "description": "The language tag as per RFC-5646." + }, + "name": { + "type": "string", + "minLength": 1, + "description": "The untranslated name of the language." + }, + "alternate": { + "type": "string", + "description": "The name of the language in another well-understood language, usually English." + }, + "dir": { + "type": "string", + "description": "The direction for text in this language. The default, `ltr` (left-to-right), represents the most common situation. However, care should be taken to set the value of `dir` appropriately if the language direction is not `ltr`. Other values supported are `rtl` (right-to-left), `ttb` (top-to-bottom), and `btt` (bottom-to-top).", + "enum": [ + "ltr", + "rtl", + "ttb", + "btt" + ], + "default": "ltr" + } + } + } + }, + "contacts": { + "type": "array", + "description": "A list of contacts qualified by their role(s) in association to the Platform described by the record.", + "items": { + "type": "object", + "description": "Identification of, and means of communication with, person responsible\nfor the Platform.", + "properties": { + "name": { + "type": "string", + "description": "The name of the responsible person or team." + }, + "position": { + "type": "string", + "description": "The name of the role or position of the responsible person or team taken from the organization's formal organizational hierarchy or chart." + }, + "organization": { + "type": "string", + "description": "Organization/affiliation of the contact." + }, + "logo": { + "description": "Graphic identifying a contact. The link relation should be `icon` and the media type should be an image media type.", + "allOf": [ + { + "$ref": "#/properties/links/items" + }, + { + "type": "object", + "required": [ + "rel", + "type" + ], + "properties": { + "rel": { + "enum": [ + "icon" + ] + } + } + } + ] + }, + "phones": { + "type": "array", + "description": "Telephone numbers at which contact can be made.", + "items": { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "string", + "description": "The value is the phone number itself.", + "pattern": "^\\+[1-9]{1}[0-9]{3,14}$" + }, + "roles": { + "description": "The type of phone number (e.g. home, work, fax, etc.).", + "$ref": "#/properties/properties/properties/contacts/items/properties/roles" + } + } + } + }, + "emails": { + "type": "array", + "description": "Email addresses at which contact can be made.", + "items": { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "string", + "description": "The value is the email number itself.", + "format": "email" + }, + "roles": { + "description": "The type of email (e.g. home, work, etc.).", + "$ref": "#/properties/properties/properties/contacts/items/properties/roles" + } + } + } + }, + "addresses": { + "type": "array", + "description": "Physical location at which contact can be made.", + "items": { + "type": "object", + "properties": { + "deliveryPoint": { + "type": "array", + "description": "Address lines for the location.", + "items": { + "type": "string" + } + }, + "city": { + "type": "string", + "description": "City for the location." + }, + "administrativeArea": { + "type": "string", + "description": "State or province of the location." + }, + "postalCode": { + "type": "string", + "description": "ZIP or other postal code." + }, + "country": { + "type": "string", + "description": "Country of the physical address. ISO 3166-1 is recommended." + }, + "roles": { + "description": "The type of address (e.g. office, home, etc.).", + "$ref": "#/properties/properties/properties/contacts/items/properties/roles" + } + } + } + }, + "links": { + "type": "array", + "description": "On-line information about the contact.", + "items": { + "allOf": [ + { + "$ref": "#/properties/links/items" + }, + { + "type": "object", + "required": [ + "type" + ] + } + ] + } + }, + "hoursOfService": { + "type": "string", + "description": "Time period when the contact can be contacted." + }, + "contactInstructions": { + "type": "string", + "description": "Supplemental instructions on how or when to contact the\nresponsible party." + }, + "roles": { + "description": "The set of named duties, job functions and/or permissions associated with this contact. (e.g. developer, administrator, etc.).", + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + } + } + } + }, + "themes": { + "type": "array", + "description": "A knowledge organization system used to classify the Platform.", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "concepts", + "scheme" + ], + "properties": { + "concepts": { + "type": "array", + "description": "One or more entity/concept identifiers from this knowledge system. it is recommended that a resolvable URI be used for each entity/concept identifier.", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "description": "An identifier for the concept." + }, + "title": { + "type": "string", + "description": "A human readable title for the concept." + }, + "description": { + "type": "string", + "description": "A human readable description for the concept." + }, + "url": { + "type": "string", + "format": "uri", + "description": "A URI providing further description of the concept." + } + } + } + }, + "scheme": { + "type": "string", + "description": "An identifier for the knowledge organization system used to classify the APEx service. It is recommended that the identifier be a resolvable URI. The list of schemes used in a searchable catalog can be determined by inspecting the server's OpenAPI document or, if the server implements CQL2, by exposing a queryable (e.g. named `scheme`) and enumerating the list of schemes in the queryable's schema definition." + } + } + } + } + } + }, + "linkTemplates": { + "type": "array", + "items": { + "allOf": [ + { + "$ref": "#/properties/links/items" + }, + { + "type": "object", + "required": [ + "uriTemplate" + ], + "properties": { + "uriTemplate": { + "type": "string", + "description": "Supplies a resolvable URI to a remote resource (or resource fragment)." + }, + "varBase": { + "type": "string", + "description": "The base URI to which the variable name can be appended to retrieve the definition of the variable as a JSON Schema fragment.", + "format": "uri" + }, + "variables": { + "type": "object", + "description": "This object contains one key per substitution variable in the templated URL. Each key defines the schema of one substitution variable using a JSON Schema fragment and can thus include things like the data type of the variable, enumerations, minimum values, maximum values, etc." + } + } + } + ] + } + }, + "links": { + "type": "array", + "items": { + "type": "object", + "properties": { + "rel": { + "type": "string", + "description": "The type or semantics of the relation.", + "enum": [ + "about", + "documentation", + "logo", + "service" + ] + }, + "type": { + "type": "string", + "description": "A hint indicating what the media type of the result of dereferencing the link should be." + }, + "title": { + "type": "string", + "description": "Used to label the destination of a link such that it can be used as a human-readable identifier." + }, + "href": { + "type": "string", + "format": "uri", + "description": "URL pointing to an external resource." + } + }, + "required": [ + "rel", + "type", + "title", + "href" + ] + }, + "minItems": 1, + "allOf": [ + { + "contains": { + "type": "object", + "properties": { + "rel": { + "const": "logo" + } + } + } + } + ] + } + } +} \ No newline at end of file From ccd2896e82b93a4d6bbb97330fd38f2e026add5b Mon Sep 17 00:00:00 2001 From: bramjanssen Date: Fri, 17 Oct 2025 14:37:00 +0200 Subject: [PATCH 4/7] fix(#235): updated validation of record to force platform link --- schemas/record.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemas/record.json b/schemas/record.json index 2be782d5..c3d57c08 100644 --- a/schemas/record.json +++ b/schemas/record.json @@ -479,7 +479,7 @@ ] } }, - "minItems": 2, + "minItems": 3, "allOf": [ { "contains": { From 117698c273244298f2a5a67942d36001a6530e8c Mon Sep 17 00:00:00 2001 From: bramjanssen Date: Thu, 30 Oct 2025 16:40:26 +0100 Subject: [PATCH 5/7] chore: updated backends to focus on marketing --- platform_catalog/cdse_openeo_federation.json | 30 ++++---------------- platform_catalog/gep.json | 25 ++++------------ platform_catalog/openeo_platform.json | 30 ++++---------------- 3 files changed, 18 insertions(+), 67 deletions(-) diff --git a/platform_catalog/cdse_openeo_federation.json b/platform_catalog/cdse_openeo_federation.json index f1c0547d..b39d5f7e 100644 --- a/platform_catalog/cdse_openeo_federation.json +++ b/platform_catalog/cdse_openeo_federation.json @@ -9,12 +9,9 @@ "updated": "2024-05-17T00:00:00Z", "type": "openeo_backend", "title": "openEO processing backend", + "short_title": "CDSE", "description": "The CDSE openEO federation enables processing using openEO.", - "keywords": [ - "openeo", - "data analysis", - "platform as a service" - ], + "keywords": [], "language": { "code": "en-US", "name": "English (United States)" @@ -42,31 +39,16 @@ ] } ], - "themes": [ - { - "concepts": [ - { - "id": "DATA ANALYSIS" - } - ], - "scheme": "https://gcmd.earthdata.nasa.gov/kms/concepts/concept_scheme/sciencekeywords" - } - ], + "themes": [], "license": "other" }, "linkTemplates": [], "links": [ { - "rel": "documentation", + "rel": "website", "type": "text/html", - "title": "CDSE openEO documentation", - "href": "https://documentation.dataspace.copernicus.eu/APIs/openEO/openEO.html" - }, - { - "rel": "service", - "type": "application/json", - "title": "openEO service", - "href": "https://openeofed.dataspace.copernicus.eu" + "title": "CDSE openEO Federation", + "href": "https://documentation.dataspace.copernicus.eu/APIs/openEO/federation/openeo_federation.html" }, { "rel": "logo", diff --git a/platform_catalog/gep.json b/platform_catalog/gep.json index e6bf4dbd..dd53fcce 100644 --- a/platform_catalog/gep.json +++ b/platform_catalog/gep.json @@ -10,11 +10,7 @@ "type": "ogc_backend", "title": "Geohazards Exploitation Platform", "description": "", - "keywords": [ - "ogc", - "data analysis", - "platform as a service" - ], + "keywords": [], "language": { "code": "en-US", "name": "English (United States)" @@ -47,25 +43,16 @@ "email": "contact@geohazards-tep.eu" } ], - "themes": [ - { - "concepts": [ - { - "id": "DATA ANALYSIS" - } - ], - "scheme": "https://gcmd.earthdata.nasa.gov/kms/concepts/concept_scheme/sciencekeywords" - } - ], + "themes": [], "license": "other" }, "linkTemplates": [], "links": [ { - "rel": "service", - "type": "application/json", - "title": "OGC API Processes Service Endpoint", - "href": "https://ades.gep.terradue.com/gep/wps3/processes" + "rel": "website", + "type": "text/html", + "title": "Geohazards TEP", + "href": "https://geohazards-tep.eu/" }, { "rel": "logo", diff --git a/platform_catalog/openeo_platform.json b/platform_catalog/openeo_platform.json index 172b4174..0aa151b1 100644 --- a/platform_catalog/openeo_platform.json +++ b/platform_catalog/openeo_platform.json @@ -9,12 +9,9 @@ "updated": "2024-05-17T00:00:00Z", "type": "openeo_backend", "title": "openEO platform processing backend", + "short_title": "openEO Platform", "description": "The openEO Platform enables processing using openEO.", - "keywords": [ - "openeo", - "data analysis", - "platform as a service" - ], + "keywords": [], "language": { "code": "en-US", "name": "English (United States)" @@ -42,31 +39,16 @@ ] } ], - "themes": [ - { - "concepts": [ - { - "id": "DATA ANALYSIS" - } - ], - "scheme": "https://gcmd.earthdata.nasa.gov/kms/concepts/concept_scheme/sciencekeywords" - } - ], + "themes": [], "license": "other" }, "linkTemplates": [], "links": [ { - "rel": "documentation", + "rel": "website", "type": "text/html", - "title": "openEO platform documentation", - "href": "https://docs.openeo.cloud" - }, - { - "rel": "service", - "type": "application/json", - "title": "openEO service", - "href": "https://openeo.cloud" + "title": "openEO Platform", + "href": "https://openeo.cloud/" }, { "rel": "logo", From cebdb96833a36475cb5dcc875cd6b07e8986b164 Mon Sep 17 00:00:00 2001 From: bramjanssen Date: Thu, 30 Oct 2025 16:55:23 +0100 Subject: [PATCH 6/7] chore: updated platform schema --- schemas/platform.json | 1 - 1 file changed, 1 deletion(-) diff --git a/schemas/platform.json b/schemas/platform.json index 41ac62db..34181e02 100644 --- a/schemas/platform.json +++ b/schemas/platform.json @@ -275,7 +275,6 @@ "themes": { "type": "array", "description": "A knowledge organization system used to classify the Platform.", - "minItems": 1, "items": { "type": "object", "required": [ From e9155aed591358b5e7aed2815e6bb51681390e04 Mon Sep 17 00:00:00 2001 From: bramjanssen Date: Thu, 30 Oct 2025 16:59:28 +0100 Subject: [PATCH 7/7] chore: updated platform record --- schemas/platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemas/platform.json b/schemas/platform.json index 34181e02..def98a92 100644 --- a/schemas/platform.json +++ b/schemas/platform.json @@ -364,7 +364,7 @@ "about", "documentation", "logo", - "service" + "website" ] }, "type": {