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 ccea3d19..5c799881 100644 --- a/algorithm_catalog/dhi/wind_turbine/records/wind_turbine_detection.json +++ b/algorithm_catalog/dhi/wind_turbine/records/wind_turbine_detection.json @@ -90,6 +90,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 c77051df..3f3e3638 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 @@ -109,6 +109,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 a56ab803..b9cb10d0 100644 --- a/algorithm_catalog/terradue/gep_bas/records/gep_bas.json +++ b/algorithm_catalog/terradue/gep_bas/records/gep_bas.json @@ -91,6 +91,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 3db75f77..a40e2fee 100644 --- a/algorithm_catalog/terradue/gep_ost/records/gep_ost.json +++ b/algorithm_catalog/terradue/gep_ost/records/gep_ost.json @@ -89,6 +89,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 03959883..1e76fc5b 100644 --- a/algorithm_catalog/terradue/sar_coin/records/sar_coin.json +++ b/algorithm_catalog/terradue/sar_coin/records/sar_coin.json @@ -90,6 +90,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 062645df..4b283546 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 @@ -90,6 +90,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 18c47118..00502dc7 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", diff --git a/algorithm_catalog/vito/biopar/records/biopar.json b/algorithm_catalog/vito/biopar/records/biopar.json index 94be2b7f..f7f0cb13 100644 --- a/algorithm_catalog/vito/biopar/records/biopar.json +++ b/algorithm_catalog/vito/biopar/records/biopar.json @@ -118,6 +118,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 add3f018..ce0b87e3 100644 --- a/algorithm_catalog/vito/fusets_mogpr/records/fusets_mogpr.json +++ b/algorithm_catalog/vito/fusets_mogpr/records/fusets_mogpr.json @@ -129,6 +129,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 10b921a6..28381db1 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 @@ -106,6 +106,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 31985c88..f24e8a82 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 9a1a1470..709fb292 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 @@ -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": "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 30274130..e20285b5 100644 --- a/algorithm_catalog/vito/sentinel1_stats/records/sentinel1_stats.json +++ b/algorithm_catalog/vito/sentinel1_stats/records/sentinel1_stats.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/netcdf", diff --git a/algorithm_catalog/vito/variabilitymap/records/variabilitymap.json b/algorithm_catalog/vito/variabilitymap/records/variabilitymap.json index 0fc243b9..ecc6f398 100644 --- a/algorithm_catalog/vito/variabilitymap/records/variabilitymap.json +++ b/algorithm_catalog/vito/variabilitymap/records/variabilitymap.json @@ -122,6 +122,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 b1912f36..2e1aefeb 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 @@ -111,6 +111,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 cafc197c..018bc764 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 @@ -109,6 +109,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/worldcover_statistics/records/worldcover_statistics.json b/algorithm_catalog/vito/worldcover_statistics/records/worldcover_statistics.json index 48919377..334334d9 100644 --- a/algorithm_catalog/vito/worldcover_statistics/records/worldcover_statistics.json +++ b/algorithm_catalog/vito/worldcover_statistics/records/worldcover_statistics.json @@ -88,6 +88,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", diff --git a/algorithm_catalog/wur/worldagrocommodities/records/wac_inference_africa.json b/algorithm_catalog/wur/worldagrocommodities/records/wac_inference_africa.json index 9645b79b..1b611d67 100644 --- a/algorithm_catalog/wur/worldagrocommodities/records/wac_inference_africa.json +++ b/algorithm_catalog/wur/worldagrocommodities/records/wac_inference_africa.json @@ -101,6 +101,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 65% rename from backend_catalog/cdse_openeo_federation.json rename to platform_catalog/cdse_openeo_federation.json index 6768b8e6..b39d5f7e 100644 --- a/backend_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)" @@ -32,6 +29,7 @@ { "href": "https://www.vito.be/", "rel": "about", + "title": "VITO", "type": "text/html" } ], @@ -41,31 +39,22 @@ ] } ], - "themes": [ - { - "concepts": [ - { - "id": "DATA ANALYSIS" - } - ], - "scheme": "https://gcmd.earthdata.nasa.gov/kms/concepts/concept_scheme/sciencekeywords" - } - ], + "themes": [], "license": "other" }, "linkTemplates": [], "links": [ { - "rel": "alternate", + "rel": "website", "type": "text/html", - "title": "CDSE openEO documentation", - "href": "https://documentation.dataspace.copernicus.eu/APIs/openEO/openEO.html" + "title": "CDSE openEO Federation", + "href": "https://documentation.dataspace.copernicus.eu/APIs/openEO/federation/openeo_federation.html" }, { - "rel": "service", - "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..dd53fcce --- /dev/null +++ b/platform_catalog/gep.json @@ -0,0 +1,64 @@ +{ + "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": [], + "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": [], + "license": "other" + }, + "linkTemplates": [], + "links": [ + { + "rel": "website", + "type": "text/html", + "title": "Geohazards TEP", + "href": "https://geohazards-tep.eu/" + }, + { + "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/backend_catalog/openeo_platform.json b/platform_catalog/openeo_platform.json similarity index 64% rename from backend_catalog/openeo_platform.json rename to platform_catalog/openeo_platform.json index 2f587a9f..0aa151b1 100644 --- a/backend_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)" @@ -32,6 +29,7 @@ { "href": "https://openeo.cloud", "rel": "about", + "title": "openEO Platform", "type": "text/html" } ], @@ -41,31 +39,22 @@ ] } ], - "themes": [ - { - "concepts": [ - { - "id": "DATA ANALYSIS" - } - ], - "scheme": "https://gcmd.earthdata.nasa.gov/kms/concepts/concept_scheme/sciencekeywords" - } - ], + "themes": [], "license": "other" }, "linkTemplates": [], "links": [ { - "rel": "alternate", + "rel": "website", "type": "text/html", - "title": "openEO platform documentation", - "href": "https://docs.openeo.cloud" + "title": "openEO Platform", + "href": "https://openeo.cloud/" }, { - "rel": "service", - "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 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..def98a92 --- /dev/null +++ b/schemas/platform.json @@ -0,0 +1,406 @@ +{ + "$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.", + "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", + "website" + ] + }, + "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 diff --git a/schemas/record.json b/schemas/record.json index c98f2182..29163f38 100644 --- a/schemas/record.json +++ b/schemas/record.json @@ -447,6 +447,7 @@ "type": "string", "description": "The type or semantics of the relation.", "enum": [ + "platform", "application", "service", "example-output", @@ -480,9 +481,28 @@ "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, + "minItems": 3, "allOf": [ { "contains": { @@ -503,6 +523,16 @@ } } } + }, + { + "contains": { + "type": "object", + "properties": { + "rel": { + "const": "platform" + } + } + } } ] }