Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Add SKOSMOS integration #5

Merged
merged 11 commits into from
Jul 23, 2024
64 changes: 64 additions & 0 deletions src/main/java/org/semantics/apigateway/api/SkosmosTransformer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.semantics.apigateway.api;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SkosmosTransformer implements DatabaseTransformer {
@Override
public Map<String, Object> transformItem(Map<String, Object> item) {
if (item == null) {
return null;
}

Map<String, Object> transformedItem = new HashMap<>();

// Check for null values before accessing properties
if (item.containsKey("@id") && item.get("@id") != null) {
transformedItem.put("iri", item.get("@id"));
}
if (item.containsKey("label") && item.get("label") != null) {
transformedItem.put("prefLabel", item.get("label"));
}
if (item.containsKey("ontology") && item.get("ontology") != null) {
transformedItem.put("vocab", item.get("ontology"));
}
if (item.containsKey("synonym") && item.get("synonym") != null) {
transformedItem.put("altLabel", item.get("synonym"));
}
if (item.containsKey("backend_type") && item.get("backend_type") != null) {
transformedItem.put("backend_type", item.get("backend_type"));
}
if (item.containsKey("short_form") && item.get("short_form") != null) {
transformedItem.put("short_form", item.get("short_form"));
}
if (item.containsKey("description") && item.get("description") != null) {
transformedItem.put("scopeNote", item.get("description"));
}
if (item.containsKey("source") && item.get("source") != null) {
transformedItem.put("source", item.get("source"));
}
if (item.containsKey("type") && item.get("type") != null) {
// the value of the key @type in OntoPortal is saved as an IRI
if (item.containsKey("backend_type") && String.valueOf(item.get("backend_type")).equals("ols")) {
if (item.get("type").equals("class")) {
transformedItem.put("type", "http://www.w3.org/2002/07/owl#Class");
} else {
transformedItem.put("type", item.get("type"));
}
} else {
transformedItem.put("type", item.get("type"));
}
}
return transformedItem;
}

@Override
public Map<String, Object> constructResponse(List<Map<String, Object>> transformedResults) {
Map<String, Object> response = new HashMap<>();
response.put("results", transformedResults);
response.put("@context", Collections.singletonMap("@context", ""));
return response;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.semantics.apigateway.api.OntoPortalTransformer;
import org.semantics.apigateway.api.DatabaseTransformer;
import org.semantics.apigateway.api.OlsTransformer;
import org.semantics.apigateway.api.SkosmosTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
Expand All @@ -15,6 +16,7 @@ public class DynDatabaseTransform {
private Map<String, String> responseMapping;
private DatabaseTransformer olsTransformer;
private DatabaseTransformer ontoPortalTransformer;
private DatabaseTransformer skosmosTransformer;

// Constructor initializes the field mappings, JSON schema, response mappings, and transformers
public DynDatabaseTransform(Map<String, String> fieldMapping, Map<String, Object> jsonSchema, Map<String, String> responseMapping) {
Expand All @@ -24,6 +26,7 @@ public DynDatabaseTransform(Map<String, String> fieldMapping, Map<String, Object
logger.info("Loaded JSON Schema: {}", jsonSchema);
this.olsTransformer = new OlsTransformer();
this.ontoPortalTransformer = new OntoPortalTransformer();
this.skosmosTransformer = new SkosmosTransformer();
}

// Method to transform the JSON response from a database into a specific format
Expand All @@ -50,6 +53,13 @@ public Map<String, Object> transformJsonResponse(List<Map<String, Object>> origi
break;

// Add more cases here for other databases as needed
case "skosmos":
List<Map<String, Object>> transformedResultsSkosmos = originalResponse.stream()
.map(skosmosTransformer::transformItem)
.filter(Objects::nonNull)
.collect(Collectors.toList());
response = skosmosTransformer.constructResponse(transformedResultsSkosmos);
break;

default:
response.put("error", "No database configuration found");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public List<Map<String, Object>> dynTransformResponse(Map<String, Object> respon
Object nestedData = response.getOrDefault(nestedJsonKey, new ArrayList<>());
logger.info("Nested JSON key: {}", nestedJsonKey);
logger.info("Nested data type: {}", nestedData.getClass().getSimpleName());

// Processing the data based on its type (List or Map)
if (nestedData instanceof List) {
processList((List<?>) nestedData, result, config);
Expand Down Expand Up @@ -85,9 +85,15 @@ private Map<String, Object> processItem(Map<String, Object> item, OntologyConfig
if (responseMapping.getSynonym() != null && item.containsKey(responseMapping.getSynonym())) {
newItem.put("synonym", item.get(responseMapping.getSynonym()));
}

if (responseMapping.getShortForm() != null && item.containsKey(responseMapping.getShortForm())) {
newItem.put("short_form", item.get(responseMapping.getShortForm()));
} else if (newItem.containsKey("iri") && newItem.get("iri") != null) {
newItem.put("short_form",
ResourceFactory.createResource(String.valueOf(newItem.get("iri"))).getLocalName().toLowerCase());

}

if (responseMapping.getDescription() != null && item.containsKey(responseMapping.getDescription())) {
newItem.put("description", item.get(responseMapping.getDescription()));
}
Expand All @@ -101,8 +107,15 @@ private Map<String, Object> processItem(Map<String, Object> item, OntologyConfig
}
}
if (responseMapping.getType() != null && item.containsKey(responseMapping.getType())) {
newItem.put("type", item.get(responseMapping.getType()));
if (config.getDatabase().equals("ontoportal")) {
newItem.put("type", "class"); // ontoportal do the search only on classes for now
} else if (config.getDatabase().equals("skosmos")) {
newItem.put("type", "individual"); // workaround ols type implementation that do not support skos types
} else {
newItem.put("type", item.get(responseMapping.getType()));
}
}

// Adding the source database as part of the new item
if (String.valueOf(config.getUrl()).contains("/search?")) {
newItem.put("source", String.valueOf(config.getUrl()).substring(0, String.valueOf(config.getUrl()).indexOf("/search?")));
Expand All @@ -111,6 +124,7 @@ private Map<String, Object> processItem(Map<String, Object> item, OntologyConfig
} else {
newItem.put("source", config.getUrl());
}

// Adding the backend database type as part of the new item
newItem.put("backend_type", config.getDatabase());

Expand Down
14 changes: 14 additions & 0 deletions src/main/resources/response-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@
"ontology": "internal",
"description": "description"
}
},
{
"database": "skosmos",
"url": "https://agrovoc.fao.org/browse/rest/v1/search?query=%s&lang=en&fields=scopeNote",
"apiKey": "",
"responseMapping": {
"nestedJson": "results",
"iri": "uri",
"label": "prefLabel",
"synonym": "altLabel",
"ontology": "vocab",
"type": "type",
"description":"scopeNote"
}
}
]
}
Expand Down
60 changes: 60 additions & 0 deletions src/main/resources/skosmos.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"request": {
"type": "object",
"properties": {
"query": {
"type": "string",
"format": "uri"
}
},
"required": ["query"]
},
"@context": {
"type": "object",
"properties": {
"skos": { "type": "string", "format": "uri" },
"isothes": { "type": "string", "format": "uri" },
"onki": { "type": "string", "format": "uri" },
"uri": { "type": "string" },
"type": { "type": "string" },
"prefLabel": { "type": "string" },
"altLabel": { "type": "string" },
"hiddenLabel": { "type": "string" },
"results": { "type": "array",
"items": {
"@id": { "type": "string" },
"@container": { "type": "array" }
}
}
}
},
"uri": { "type": "string" },
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"uri": {
"type": "string",
"format": "uri"
},
"type": {
"type": "array",
"items": { "type": "string" }
},
"prefLabel": { "type": "string" },
"lang": { "type": "string" },
"hiddenLabel": { "type": "string" },
"altLabel": { "type": "string" },
"vocab": { "type": "string" },
"exvocab": { "type": "string" }
},
"required": ["prefLabel", "uri", "vocab", "type"]
}
}
},
"required": ["request", "results"]
}