diff --git a/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/ColumnTypeRdfMapper.java b/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/ColumnTypeRdfMapper.java index 2d8f7a3a1f..5978bef7ce 100644 --- a/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/ColumnTypeRdfMapper.java +++ b/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/ColumnTypeRdfMapper.java @@ -2,6 +2,8 @@ import static java.util.Map.entry; import static org.eclipse.rdf4j.model.util.Values.literal; +import static org.molgenis.emx2.Constants.API_FILE; +import static org.molgenis.emx2.rdf.RdfUtils.getSchemaNamespace; import com.google.common.net.UrlEscapers; import java.time.LocalDateTime; @@ -15,7 +17,6 @@ import org.eclipse.rdf4j.model.base.CoreDatatype; import org.eclipse.rdf4j.model.util.Values; import org.molgenis.emx2.*; -import org.molgenis.emx2.utils.TypeUtils; import org.molgenis.emx2.utils.URIUtils; /** @@ -200,7 +201,8 @@ Set retrieveValues(String baseURL, Row row, Column column) { Values.iri( baseURL + schemaPath - + "/api/file/" + + API_FILE + + "/" + tablePath + "/" + columnPath @@ -274,14 +276,6 @@ public CoreDatatype.XSD getCoreDatatype() { this.coreDatatype = coreDatatype; } - // TODO: Fix code duplicity with RDFService. - private static Namespace getSchemaNamespace(final String baseURL, final SchemaMetadata schema) { - final String schemaName = UrlEscapers.urlPathSegmentEscaper().escape(schema.getName()); - final String url = baseURL + schemaName + "/api/rdf/"; - final String prefix = TypeUtils.convertToPascalCase(schema.getName()); - return Values.namespace(prefix, url); - } - /** * Generic retrieval function. Can be used for {@link Values#literal(Object)} or any custom * function which outputs a {@link Value}. diff --git a/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/RDFService.java b/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/RDFService.java index e74e9f278a..e9cbf45d4d 100644 --- a/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/RDFService.java +++ b/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/RDFService.java @@ -5,6 +5,7 @@ import static org.molgenis.emx2.FilterBean.f; import static org.molgenis.emx2.Operator.EQUALS; import static org.molgenis.emx2.SelectColumn.s; +import static org.molgenis.emx2.rdf.RdfUtils.getSchemaNamespace; import com.google.common.net.UrlEscapers; import java.io.IOException; @@ -25,7 +26,6 @@ import org.eclipse.rdf4j.rio.WriterConfig; import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings; import org.molgenis.emx2.*; -import org.molgenis.emx2.utils.TypeUtils; // TODO check null value handling // TODO check value types @@ -55,7 +55,8 @@ public class RDFService { public static final IRI IRI_CONTROLLED_VOCABULARY = Values.iri("http://purl.obolibrary.org/obo/NCIT_C48697"); - private static final String SETTING_CUSTOM_RDF = "custom_rdf"; + // Advanced setting containing valid Turtle-formatted RDF. + public static final String SETTING_CUSTOM_RDF = "custom_rdf"; /** * SIO:001055 = observing (definition: observing is a process of passive interaction in which one @@ -225,7 +226,7 @@ private void buildgenericRdf(ModelBuilder builder, Schema[] schemas) throws IOEx boolean allIncludeCustomRdf = true; // Define the schemas at the start of the document. for (final Schema schema : schemas) { - final Namespace ns = getSchemaNamespace(schema); + final Namespace ns = getSchemaNamespace(baseURL, schema); builder.setNamespace(ns); // Adds custom RDF to model. if (schema.hasSetting(SETTING_CUSTOM_RDF)) { @@ -281,23 +282,6 @@ protected void describeRoot(final ModelBuilder builder) { .add(DCTERMS.CREATOR, IRI_MOLGENIS); } - /** - * Get the namespace for this schema - * - * @param schema the schema - * @return A namespace that defines a local unique prefix for this schema. - */ - private Namespace getSchemaNamespace(final SchemaMetadata schema) { - final String schemaName = UrlEscapers.urlPathSegmentEscaper().escape(schema.getName()); - final String url = baseURL + schemaName + "/api/rdf/"; - final String prefix = TypeUtils.convertToPascalCase(schema.getName()); - return Values.namespace(prefix, url); - } - - private Namespace getSchemaNamespace(final Schema schema) { - return getSchemaNamespace(schema.getMetadata()); - } - /** * Get an IRI for the table. Taking the schema in which the table resides into consideration. * @@ -305,13 +289,13 @@ private Namespace getSchemaNamespace(final Schema schema) { * @return An IRI that is based on the schema namespace. */ private IRI getTableIRI(final Table table) { - final Namespace ns = getSchemaNamespace(table.getSchema()); + final Namespace ns = getSchemaNamespace(baseURL, table.getSchema()); return Values.iri(ns, table.getIdentifier()); } private void describeSchema(final ModelBuilder builder, final Schema schema) { // The name from a name space is the IRI. - final String subject = getSchemaNamespace(schema).getName(); + final String subject = getSchemaNamespace(baseURL, schema).getName(); builder .subject(subject) .add(RDFS.LABEL, schema.getName()) @@ -393,7 +377,7 @@ private IRI getColumnIRI(final Column column) { Schema schema = table.getTable().getSchema(); final String tableName = UrlEscapers.urlPathSegmentEscaper().escape(table.getIdentifier()); final String columnName = UrlEscapers.urlPathSegmentEscaper().escape(column.getIdentifier()); - final Namespace ns = getSchemaNamespace(schema); + final Namespace ns = getSchemaNamespace(baseURL, schema); return Values.iri(ns, tableName + "/column/" + columnName); } @@ -647,7 +631,7 @@ private IRI getIriForRow(final Row row, final TableMetadata metadata) { keyParts.put(column.getIdentifier(), row.get(column).toString()); } } - final Namespace ns = getSchemaNamespace(metadata.getRootTable().getSchema()); + final Namespace ns = getSchemaNamespace(baseURL, metadata.getRootTable().getSchema()); PrimaryKey key = new PrimaryKey(keyParts); return Values.iri(ns, rootTableName + "?" + key.getEncodedValue()); } diff --git a/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/RdfUtils.java b/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/RdfUtils.java new file mode 100644 index 0000000000..5597df3704 --- /dev/null +++ b/backend/molgenis-emx2-rdf/src/main/java/org/molgenis/emx2/rdf/RdfUtils.java @@ -0,0 +1,30 @@ +package org.molgenis.emx2.rdf; + +import static org.molgenis.emx2.Constants.API_RDF; + +import com.google.common.net.UrlEscapers; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.util.Values; +import org.molgenis.emx2.Schema; +import org.molgenis.emx2.SchemaMetadata; +import org.molgenis.emx2.utils.TypeUtils; + +abstract class RdfUtils { + /** + * Get the namespace for a schema + * + * @param baseURL the baseURL that needs to be used + * @param schema the schema + * @return A namespace that defines a local unique prefix for this schema. + */ + static Namespace getSchemaNamespace(final String baseURL, final SchemaMetadata schema) { + final String schemaName = UrlEscapers.urlPathSegmentEscaper().escape(schema.getName()); + final String url = baseURL + schemaName + API_RDF + "/"; + final String prefix = TypeUtils.convertToPascalCase(schema.getName()); + return Values.namespace(prefix, url); + } + + static Namespace getSchemaNamespace(final String baseURL, final Schema schema) { + return getSchemaNamespace(baseURL, schema.getMetadata()); + } +} diff --git a/backend/molgenis-emx2-rdf/src/test/java/org/molgenis/emx2/rdf/RdfUtilsTest.java b/backend/molgenis-emx2-rdf/src/test/java/org/molgenis/emx2/rdf/RdfUtilsTest.java new file mode 100644 index 0000000000..746085be7b --- /dev/null +++ b/backend/molgenis-emx2-rdf/src/test/java/org/molgenis/emx2/rdf/RdfUtilsTest.java @@ -0,0 +1,44 @@ +package org.molgenis.emx2.rdf; + +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.util.Values; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.molgenis.emx2.Database; +import org.molgenis.emx2.Schema; +import org.molgenis.emx2.sql.TestDatabaseFactory; + +class RdfUtilsTest { + static final String TEST_SCHEMA = "TestRdfUtils"; + static final String BASE_URL = "http://molgenis.org/"; + static final String NAMESPACE_IRI = BASE_URL + TEST_SCHEMA + "/api/rdf/"; + + static Database database; + static Schema rdfUtilsTest; + + @BeforeAll + public static void setup() { + database = TestDatabaseFactory.getTestDatabase(); + rdfUtilsTest = database.dropCreateSchema(TEST_SCHEMA); + } + + @AfterAll + public static void tearDown() { + database = TestDatabaseFactory.getTestDatabase(); + database.dropSchema(rdfUtilsTest.getName()); + } + + @Test + void testSchemaNamespaceRetrieval() { + Namespace expected = Values.namespace(TEST_SCHEMA, NAMESPACE_IRI); + + Assertions.assertAll( + () -> + Assertions.assertEquals(expected, RdfUtils.getSchemaNamespace(BASE_URL, rdfUtilsTest)), + () -> + Assertions.assertEquals( + expected, RdfUtils.getSchemaNamespace(BASE_URL, rdfUtilsTest.getMetadata()))); + } +} diff --git a/backend/molgenis-emx2-webapi/src/main/java/org/molgenis/emx2/web/GraphGenomeApi.java b/backend/molgenis-emx2-webapi/src/main/java/org/molgenis/emx2/web/GraphGenomeApi.java index 04db5aafb7..0a4a662b2c 100644 --- a/backend/molgenis-emx2-webapi/src/main/java/org/molgenis/emx2/web/GraphGenomeApi.java +++ b/backend/molgenis-emx2-webapi/src/main/java/org/molgenis/emx2/web/GraphGenomeApi.java @@ -1,5 +1,7 @@ package org.molgenis.emx2.web; +import static org.molgenis.emx2.Constants.API_RDF; + import io.javalin.Javalin; import io.javalin.http.Context; import java.io.IOException; @@ -37,7 +39,7 @@ private static int graphGenomeForDatabase(Context ctx) throws IOException { + (ctx.port() > 0 ? ":" + ctx.port() : "") + (!ctx.path().isEmpty() ? "/" + ctx.path() + "/" : "/"); var format = RDFApi.selectFormat(ctx); - new GraphGenome(baseURL, RDFApi.RDF_API_LOCATION, format) + new GraphGenome(baseURL, API_RDF, format) .graphGenomeAsRDF( outputStream, gene, assembly, ucscgenome, GRAPH_GENOME_API_LOCATION, tables); outputStream.flush(); diff --git a/backend/molgenis-emx2-webapi/src/main/java/org/molgenis/emx2/web/RDFApi.java b/backend/molgenis-emx2-webapi/src/main/java/org/molgenis/emx2/web/RDFApi.java index 2c253039e5..cc4a97e027 100644 --- a/backend/molgenis-emx2-webapi/src/main/java/org/molgenis/emx2/web/RDFApi.java +++ b/backend/molgenis-emx2-webapi/src/main/java/org/molgenis/emx2/web/RDFApi.java @@ -1,5 +1,8 @@ package org.molgenis.emx2.web; +import static org.molgenis.emx2.Constants.API_JSONLD; +import static org.molgenis.emx2.Constants.API_RDF; +import static org.molgenis.emx2.Constants.API_TTL; import static org.molgenis.emx2.web.MolgenisWebservice.*; import io.javalin.Javalin; @@ -21,9 +24,6 @@ public class RDFApi { public static final String FORMAT = "format"; private static MolgenisSessionManager sessionManager; - public static final String RDF_API_LOCATION = "/api/rdf"; - public static final String TTL_API_LOCATION = "/api/ttl"; - public static final String JSONLD_API_LOCATION = "/api/jsonld"; private static final List acceptedRdfFormats = List.of( @@ -41,9 +41,9 @@ public static void create(Javalin app, MolgenisSessionManager sm) { // created on-the-fly, there is no way of knowing (or is there?) sessionManager = sm; - defineApiRoutes(app, RDF_API_LOCATION, null); - defineApiRoutes(app, TTL_API_LOCATION, RDFFormat.TURTLE); - defineApiRoutes(app, JSONLD_API_LOCATION, RDFFormat.JSONLD); + defineApiRoutes(app, API_RDF, null); + defineApiRoutes(app, API_TTL, RDFFormat.TURTLE); + defineApiRoutes(app, API_JSONLD, RDFFormat.JSONLD); } private static void defineApiRoutes(Javalin app, String apiLocation, RDFFormat format) { @@ -111,7 +111,7 @@ private static void rdfForSchema(Context ctx, RDFFormat format) throws IOExcepti } final String baseURL = URLUtils.extractBaseURL(ctx); - RDFService rdf = new RDFService(baseURL, RDF_API_LOCATION, format); + RDFService rdf = new RDFService(baseURL, API_RDF, format); ctx.contentType(rdf.getMimeType()); OutputStream outputStream = ctx.outputStream(); @@ -130,7 +130,7 @@ private static void rdfForTable(Context ctx, RDFFormat format) throws IOExceptio } final String baseURL = URLUtils.extractBaseURL(ctx); - RDFService rdf = new RDFService(baseURL, RDF_API_LOCATION, format); + RDFService rdf = new RDFService(baseURL, API_RDF, format); ctx.contentType(rdf.getMimeType()); OutputStream outputStream = ctx.outputStream(); @@ -145,7 +145,7 @@ private static void rdfForRow(Context ctx, RDFFormat format) throws IOException String rowId = sanitize(ctx.pathParam("row")); final String baseURL = URLUtils.extractBaseURL(ctx); - RDFService rdf = new RDFService(baseURL, RDF_API_LOCATION, format); + RDFService rdf = new RDFService(baseURL, API_RDF, format); ctx.contentType(rdf.getMimeType()); OutputStream outputStream = ctx.outputStream(); @@ -162,7 +162,7 @@ private static void rdfForColumn(Context ctx, RDFFormat format) throws IOExcepti final String baseURL = URLUtils.extractBaseURL(ctx); - RDFService rdf = new RDFService(baseURL, RDF_API_LOCATION, format); + RDFService rdf = new RDFService(baseURL, API_RDF, format); ctx.contentType(rdf.getMimeType()); OutputStream outputStream = ctx.outputStream(); diff --git a/backend/molgenis-emx2/src/main/java/org/molgenis/emx2/Constants.java b/backend/molgenis-emx2/src/main/java/org/molgenis/emx2/Constants.java index 2ec3e4773d..c1dcf2158b 100644 --- a/backend/molgenis-emx2/src/main/java/org/molgenis/emx2/Constants.java +++ b/backend/molgenis-emx2/src/main/java/org/molgenis/emx2/Constants.java @@ -114,6 +114,11 @@ public class Constants { public static final String CONTACT_RECIPIENTS_QUERY_SETTING_KEY = "contactRecipientsQuery"; public static final String CONTACT_BCC_ADDRESS = "contactBccAddress"; + public static final String API_RDF = "/api/rdf"; + public static final String API_TTL = "/api/ttl"; + public static final String API_JSONLD = "/api/jsonld"; + public static final String API_FILE = "/api/file"; + private Constants() { // hide constructor }