From 761b9aa2f55b6a7bf18ea00177480b5e4ba96400 Mon Sep 17 00:00:00 2001 From: Juanje Mendoza Date: Mon, 4 May 2026 15:30:03 +0200 Subject: [PATCH 1/4] new endpoint score benchmark --- src/main/java/fair/Constants.java | 12 +++++++++ src/main/java/fair/FOOPS.java | 24 +++++++++++++++++ src/main/java/server/FOOPSController.java | 33 +++++++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/src/main/java/fair/Constants.java b/src/main/java/fair/Constants.java index bdc1dec2..4b70d92c 100644 --- a/src/main/java/fair/Constants.java +++ b/src/main/java/fair/Constants.java @@ -720,6 +720,18 @@ public static String getFullListOfTestsMetadata() { " {\"@id\": \""+URI2_URL+"\", \"title\": \""+URI2_TITLE+"\", \"description\": \""+URI2_DESC+"\", \"endpointURL:\"" + FOOPS_TESTS_ENDPOINT + URI2 + "\", \"isDefinedBy: {\"@id:\"" + URI2_URL + "\"}, \"landingPage: {\"@id:\"" + FOOPS_DOC_BASE_URL + URI2 + "/" + URI2 + ".html\"}}\n" + "]"; } + + public static String JSON_LD_BENCHMARK_SCORE_TEMPLATE = + "{\n" + FTR_CONTEXT + + " \"@id\": \"$SCORE_ID\",\n" + + " \"@type\": \"https://w3id.org/ftr#BenchmarkScore\",\n" + + " \"outputFromAlgorithm\": {\n" + + " \"@id\": \"https://w3id.org/foops/algorithm/$BENCHMARK_ID\"\n" + + " },\n" + + " \"value\": \"$SCORE_VALUE\",\n" + + " \"log\": \"$SCORE_LOG\",\n" + + " \"scoredTestResults\": $TEST_RESULT_SET\n" + + "}\n"; } diff --git a/src/main/java/fair/FOOPS.java b/src/main/java/fair/FOOPS.java index e7ceac7f..4b3cb814 100644 --- a/src/main/java/fair/FOOPS.java +++ b/src/main/java/fair/FOOPS.java @@ -435,5 +435,29 @@ public static void main(String[] args){ } } } + + public String exportBenchmarkScore(String benchmarkId) { + String template = Constants.JSON_LD_BENCHMARK_SCORE_TEMPLATE; + String scoreId = "urn:foops:" + java.util.UUID.randomUUID(); + float score = getTotalScore() * 100; + int totalPassed = 0; + int totalRun = 0; + + for (Check c : this.checksToRun.getChecks()) { + totalPassed += c.getTotal_passed_tests(); + totalRun += c.getTotal_tests_run(); + } + + String log = "The score was obtained as follows: all passed tests are added and divided " + + "by the total number of tests run. " + + "Since " + totalPassed + "/" + totalRun + " tests passed, your score is " + score + "%"; + + template = template.replace("$SCORE_ID", scoreId); + template = template.replace("$BENCHMARK_ID", benchmarkId); + template = template.replace("$SCORE_VALUE", String.valueOf(score)); + template = template.replace("$SCORE_LOG", log); + template = template.replace("$TEST_RESULT_SET", fillTestResultSetTemplate()); + return template; + } } diff --git a/src/main/java/server/FOOPSController.java b/src/main/java/server/FOOPSController.java index 114c8a8a..14ebee86 100644 --- a/src/main/java/server/FOOPSController.java +++ b/src/main/java/server/FOOPSController.java @@ -399,6 +399,39 @@ public String assessPOST( } + @Operation( + summary = "Returns a benchmark score for a resource following the FTR specification.", + description = "Returns a BenchmarkScore according to the FTR specification. " + + "Available benchmark identifiers: ALL, PRE.\n" + + "Example request JSON:\n" + + "```\n" + + "{\n" + + " \"resource_identifier\": \"https://w3id.org/example#\"\n" + + "}\n" + + "```" + ) + @CrossOrigin(origins = "*") + @PostMapping(path = "assess/score/{identifier}", consumes = "application/json", produces = "application/json") + public String postBenchmarkScore(@PathVariable String identifier, + @RequestBody OntologyAssessmentRequest body) { + FOOPS f = null; + try { + String targetResource = body.getResourceIdentifier(); + logger.info("Received benchmark score request - benchmark: " + identifier + ", resource: " + targetResource); + f = new FOOPS(targetResource, false); + f.fairTest(); + return applyOstrailsStatusMapping(f.exportBenchmarkScore(identifier)); + } catch (FileTooLargeException el) { + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, + "File sent for assessment is too big (max 50MB)"); + } catch (Exception e) { + logger.error("Error " + e.getMessage()); + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Malformed JSON request"); + } finally { + if (f != null) f.removeTemporaryFolders(); + } + } + private String applyOstrailsStatusMapping(String jsonLD) { return jsonLD .replace("\"value\": \"ok\"", "\"value\": \"pass\"") From 1eb3b8596e4a9542f79c124014712a1f1615e0c6 Mon Sep 17 00:00:00 2001 From: Juanje Mendoza Date: Tue, 5 May 2026 10:44:43 +0200 Subject: [PATCH 2/4] new endpoint benchmark score with test. --- src/main/java/fair/Constants.java | 3 ++- src/main/java/fair/FOOPS.java | 18 ++++++++++++------ src/test/java/fair/FOOPSTest.java | 27 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/main/java/fair/Constants.java b/src/main/java/fair/Constants.java index 41333cb6..97f92d5e 100644 --- a/src/main/java/fair/Constants.java +++ b/src/main/java/fair/Constants.java @@ -765,8 +765,9 @@ public static String getFullListOfTestsMetadata() { " },\n" + " \"value\": \"$SCORE_VALUE\",\n" + " \"log\": \"$SCORE_LOG\",\n" + - " \"scoredTestResults\": $TEST_RESULT_SET\n" + + " \"scoredTestResults\": [ $TEST_RESULT_SET_LIST ]\n" + "}\n"; + } diff --git a/src/main/java/fair/FOOPS.java b/src/main/java/fair/FOOPS.java index cab89ada..1e7b2a0a 100644 --- a/src/main/java/fair/FOOPS.java +++ b/src/main/java/fair/FOOPS.java @@ -41,6 +41,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Date; +import java.util.List; public class FOOPS { private static final Logger logger = LoggerFactory.getLogger(FOOPS.class); @@ -439,7 +440,8 @@ public static void main(String[] args){ public String exportBenchmarkScore(String benchmarkId) { String template = Constants.JSON_LD_BENCHMARK_SCORE_TEMPLATE; String scoreId = "urn:foops:" + java.util.UUID.randomUUID(); - float score = getTotalScore() * 100; + float scoreFloat = getTotalScore() * 100; + int scoreInt = (int) scoreFloat; int totalPassed = 0; int totalRun = 0; @@ -449,14 +451,18 @@ public String exportBenchmarkScore(String benchmarkId) { } String log = "The score was obtained as follows: all passed tests are added and divided " + - "by the total number of tests run. " + - "Since " + totalPassed + "/" + totalRun + " tests passed, your score is " + score + "%"; - + "by the total number of tests run. " + + "Since " + totalPassed + "/" + totalRun + " tests passed, your score is " + scoreInt + "%"; + + String testResultSetNoContext = fillTestResultSetTemplate() + .replace(Constants.FTR_CONTEXT, ""); + template = template.replace("$TEST_RESULT_SET_LIST", testResultSetNoContext); + template = template.replace("$SCORE_ID", scoreId); template = template.replace("$BENCHMARK_ID", benchmarkId); - template = template.replace("$SCORE_VALUE", String.valueOf(score)); + template = template.replace("$SCORE_VALUE", String.valueOf(scoreInt)); template = template.replace("$SCORE_LOG", log); - template = template.replace("$TEST_RESULT_SET", fillTestResultSetTemplate()); + return template; } } diff --git a/src/test/java/fair/FOOPSTest.java b/src/test/java/fair/FOOPSTest.java index 7ffdb51f..5aefaf79 100644 --- a/src/test/java/fair/FOOPSTest.java +++ b/src/test/java/fair/FOOPSTest.java @@ -412,4 +412,31 @@ public void testVersionInJsonLdResultSetOutput(){ } } + /** + * This test verifies that the benchmark score endpoint returns a valid + * BenchmarkScore JSON-LD with the required fields (scoring algorithm feature) + */ + @Test + public void testExportBenchmarkScore() { + try { + ClassLoader classLoader = getClass().getClassLoader(); + File is = new File(classLoader.getResource("ontology_100.ttl").getFile()); + FOOPS f = new FOOPS(is.toString(), true); + f.fairTest(); + String result = f.exportBenchmarkScore("ALL"); + assertNotNull(result); + assertTrue("Result must contain BenchmarkScore type", result.contains("ftr#BenchmarkScore")); + assertTrue("Result must contain outputFromAlgorithm", result.contains("outputFromAlgorithm")); + assertTrue("Result must contain algorithm ALL", result.contains("https://w3id.org/foops/algorithm/ALL")); + assertTrue("Result must contain value", result.contains("\"value\"")); + assertTrue("Result must contain log", result.contains("\"log\"")); + assertTrue("Result must contain scoredTestResults", result.contains("scoredTestResults")); + assertTrue("Result must contain TestResultSet", result.contains("ftr#TestResultSet")); + f.removeTemporaryFolders(); + } catch (Exception e) { + logger.error("Could not load the resource file"); + fail(); + } + } + } From 0ed6771b3650a36b256437de28609f1dd6f47020 Mon Sep 17 00:00:00 2001 From: Juanje Mendoza Date: Wed, 6 May 2026 08:37:40 +0200 Subject: [PATCH 3/4] improve scoringAlgorithm --- src/main/java/fair/Constants.java | 7 +++++-- src/main/java/fair/FOOPS.java | 18 ++++++++++++++++++ src/main/java/server/FOOPSController.java | 4 ++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/main/java/fair/Constants.java b/src/main/java/fair/Constants.java index 97f92d5e..bba5a2a6 100644 --- a/src/main/java/fair/Constants.java +++ b/src/main/java/fair/Constants.java @@ -761,11 +761,14 @@ public static String getFullListOfTestsMetadata() { " \"@id\": \"$SCORE_ID\",\n" + " \"@type\": \"https://w3id.org/ftr#BenchmarkScore\",\n" + " \"outputFromAlgorithm\": {\n" + - " \"@id\": \"https://w3id.org/foops/algorithm/$BENCHMARK_ID\"\n" + + " \"@id\": \"https://w3id.org/foops/algorithm/$BENCHMARK_ID\",\n" + + " \"@type\": \"https://w3id.org/ftr#ScoringAlgorithm\",\n" + + " \"title\": \"$BENCHMARK_TITLE\",\n" + + " \"description\": \"$BENCHMARK_DESCRIPTION\"\n" + " },\n" + " \"value\": \"$SCORE_VALUE\",\n" + " \"log\": \"$SCORE_LOG\",\n" + - " \"scoredTestResults\": [ $TEST_RESULT_SET_LIST ]\n" + + " \"scoredTestResults\": $TEST_RESULT_SET_LIST \n" + "}\n"; diff --git a/src/main/java/fair/FOOPS.java b/src/main/java/fair/FOOPS.java index 1e7b2a0a..86d084ab 100644 --- a/src/main/java/fair/FOOPS.java +++ b/src/main/java/fair/FOOPS.java @@ -440,6 +440,8 @@ public static void main(String[] args){ public String exportBenchmarkScore(String benchmarkId) { String template = Constants.JSON_LD_BENCHMARK_SCORE_TEMPLATE; String scoreId = "urn:foops:" + java.util.UUID.randomUUID(); + String benchmarkTitle; + String benchmarkDescription; float scoreFloat = getTotalScore() * 100; int scoreInt = (int) scoreFloat; int totalPassed = 0; @@ -463,6 +465,22 @@ public String exportBenchmarkScore(String benchmarkId) { template = template.replace("$SCORE_VALUE", String.valueOf(scoreInt)); template = template.replace("$SCORE_LOG", log); + if ("ALL".equals(benchmarkId)) { + benchmarkTitle = "General Benchmark for FAIR Principles"; + benchmarkDescription = "This algorithm represents how each test is scored. " + + "All passed tests are added and divided by the total number of tests run."; + } else if ("PRE".equals(benchmarkId)) { + benchmarkTitle = "Priority Benchmark for FAIR Principles"; + benchmarkDescription = "This algorithm represents how each test is scored. " + + "It only runs the priority FOOPS! tests."; + } else { + benchmarkTitle = "Unknown Benchmark"; + benchmarkDescription = "No description available."; + } + + template = template.replace("$BENCHMARK_TITLE", benchmarkTitle); + template = template.replace("$BENCHMARK_DESCRIPTION", benchmarkDescription); + return template; } } diff --git a/src/main/java/server/FOOPSController.java b/src/main/java/server/FOOPSController.java index 12d0cbb8..c8d25481 100644 --- a/src/main/java/server/FOOPSController.java +++ b/src/main/java/server/FOOPSController.java @@ -438,7 +438,7 @@ public String assessPOST( } } - + @Operation( summary = "Returns a benchmark score for a resource following the FTR specification.", description = "Returns a BenchmarkScore according to the FTR specification. " + @@ -451,7 +451,7 @@ public String assessPOST( "```" ) @CrossOrigin(origins = "*") - @PostMapping(path = "assess/score/{identifier}", consumes = "application/json", produces = "application/json") + @PostMapping(path = "assess/scoringAlgorithm/{identifier}", consumes = "application/json", produces = "application/json") public String postBenchmarkScore(@PathVariable String identifier, @RequestBody OntologyAssessmentRequest body) { FOOPS f = null; From 0a0973f8fceda4c7bd610765e97d34cf415edbfe Mon Sep 17 00:00:00 2001 From: Juanje Mendoza Date: Tue, 26 May 2026 13:12:13 +0200 Subject: [PATCH 4/4] wrong endpoint in uri1 and uri2 --- doc/test/URI1/URI1.html | 2 +- doc/test/URI1/URI1.jsonld | 2 +- doc/test/URI1/URI1.ttl | 2 +- doc/test/URI2/URI2.html | 2 +- doc/test/URI2/URI2.jsonld | 2 +- doc/test/URI2/URI2.ttl | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/test/URI1/URI1.html b/doc/test/URI1/URI1.html index b82b7878..37e8fd9a 100644 --- a/doc/test/URI1/URI1.html +++ b/doc/test/URI1/URI1.html @@ -139,7 +139,7 @@

Test information

Applicable for
diff --git a/doc/test/URI1/URI1.jsonld b/doc/test/URI1/URI1.jsonld index 59d858d1..ad562035 100644 --- a/doc/test/URI1/URI1.jsonld +++ b/doc/test/URI1/URI1.jsonld @@ -91,7 +91,7 @@ ], "http://www.w3.org/ns/dcat#endpointURL": [ { - "@id": "https://foops.linkeddata.es/assess/test/URL1" + "@id": "https://foops.linkeddata.es/assess/test/URI1" } ], "http://www.w3.org/ns/dcat#keyword": [ diff --git a/doc/test/URI1/URI1.ttl b/doc/test/URI1/URI1.ttl index 2ab59a70..51100ee2 100644 --- a/doc/test/URI1/URI1.ttl +++ b/doc/test/URI1/URI1.ttl @@ -28,7 +28,7 @@ The test will pass if the vocabulary is resolvable in any of the following RDF s dcterms:identifier "https://w3id.org/foops/test/URI1" ; dcat:keyword "URI resolvable"@en , "Test"@en , "Resolvable"@en; dcat:endpointDescription ; - dcat:endpointURL ; + dcat:endpointURL ; dpv:isApplicableFor ; ftr:supportedBy ; ; diff --git a/doc/test/URI2/URI2.html b/doc/test/URI2/URI2.html index d7b768e6..d71a2ea1 100644 --- a/doc/test/URI2/URI2.html +++ b/doc/test/URI2/URI2.html @@ -137,7 +137,7 @@

Test information

Applicable for
diff --git a/doc/test/URI2/URI2.jsonld b/doc/test/URI2/URI2.jsonld index 443f2003..cf5122ce 100644 --- a/doc/test/URI2/URI2.jsonld +++ b/doc/test/URI2/URI2.jsonld @@ -85,7 +85,7 @@ ], "http://www.w3.org/ns/dcat#endpointURL": [ { - "@id": "https://foops.linkeddata.es/assess/test/URL2" + "@id": "https://foops.linkeddata.es/assess/test/URI2" } ], "http://www.w3.org/ns/dcat#keyword": [ diff --git a/doc/test/URI2/URI2.ttl b/doc/test/URI2/URI2.ttl index 260369c5..29c7ea07 100644 --- a/doc/test/URI2/URI2.ttl +++ b/doc/test/URI2/URI2.ttl @@ -26,7 +26,7 @@ This check verifies if the ontology URI is equal to the ontology ID. The test pa dcterms:identifier "https://w3id.org/foops/test/URI2" ; dcat:keyword "Consistent ontology ID"@en , "Test"@en , "Findable"@en ; dcat:endpointDescription ; - dcat:endpointURL ; + dcat:endpointURL ; dpv:isApplicableFor ; ftr:supportedBy ; ;