From 4bbbde7a67a8c7170b8baf4e313eec542061ab0a Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Tue, 27 Aug 2024 07:39:12 +0200 Subject: [PATCH] WIP --- dbrepo-metadata-db/1_setup-schema.sql | 12 +- .../table/columns/ColumnCreateDto.java | 6 + .../concepts/ColumnSemanticsUpdateDto.java | 6 + .../java/at/tuwien/mapper/MetadataMapper.java | 6 + .../at/tuwien/endpoints/OntologyEndpoint.java | 71 +------- .../at/tuwien/endpoints/TableEndpoint.java | 94 +--------- .../endpoints/OntologyEndpointUnitTest.java | 109 ------------ .../endpoints/TableEndpointUnitTest.java | 91 ---------- .../tuwien/mvc/PrometheusEndpointMvcTest.java | 15 -- .../tuwien/service/EntityServiceUnitTest.java | 163 ----------------- .../java/at/tuwien/service/EntityService.java | 64 ------- .../service/impl/EntityServiceImpl.java | 167 ------------------ .../tuwien/service/impl/TableServiceImpl.java | 53 ++++-- dbrepo-ui/components/table/TableSchema.vue | 14 +- dbrepo-ui/composables/table-service.ts | 23 +-- dbrepo-ui/dto/index.ts | 11 ++ 16 files changed, 88 insertions(+), 817 deletions(-) delete mode 100644 dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/EntityServiceUnitTest.java delete mode 100644 dbrepo-metadata-service/services/src/main/java/at/tuwien/service/EntityService.java delete mode 100644 dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/EntityServiceImpl.java diff --git a/dbrepo-metadata-db/1_setup-schema.sql b/dbrepo-metadata-db/1_setup-schema.sql index 62dc5c3095..9213b8ea88 100644 --- a/dbrepo-metadata-db/1_setup-schema.sql +++ b/dbrepo-metadata-db/1_setup-schema.sql @@ -543,7 +543,7 @@ VALUES (1, '%Y-%c-%d %H:%i:%S.%f', 'yyyy-MM-dd HH:mm:ss.SSSSSS', '2022-01-30 13: (1, '%d.%c.%Y', 'dd.MM.yyyy', '30.01.2022', false); INSERT INTO `mdb_ontologies` (prefix, uri, uri_pattern, sparql_endpoint, rdf_path) -VALUES ('om', 'http://www.ontology-of-units-of-measure.org/resource/om-2/', +VALUES ('om2', 'http://www.ontology-of-units-of-measure.org/resource/om-2/', 'http://www.ontology-of-units-of-measure.org/resource/om-2/.*', null, 'rdf/om-2.0.rdf'), ('wd', 'http://www.wikidata.org/', 'http://www.wikidata.org/entity/.*', 'https://query.wikidata.org/sparql', null), @@ -557,5 +557,13 @@ VALUES ('om', 'http://www.ontology-of-units-of-measure.org/resource/om-2/', ('rdfs', 'http://www.w3.org/2000/01/rdf-schema#', null, null, null), ('owl', 'http://www.w3.org/2002/07/owl#', null, null, null), ('prov', 'http://www.w3.org/ns/prov#', null, null, null), - ('db', 'http://dbpedia.org', 'http://dbpedia.org/ontology/.*', 'http://dbpedia.org/sparql', null); + ('db', 'http://dbpedia.org', 'http://dbpedia.org/ontology/.*', 'http://dbpedia.org/sparql', null), + ('aq', 'http://vocab.linkeddata.es/datosabiertos/def/medio-ambiente/calidad-aire', 'http://vocab.linkeddata.es/datosabiertos/def/medio-ambiente/calidad-aire/*', null, null), + ('building', 'https://www.auto.tuwien.ac.at/downloads/thinkhome/ontology/BuildingOntology.owl', 'https://www.auto.tuwien.ac.at/downloads/thinkhome/ontology/BuildingOntology.owl/*', null, null), + ('car', 'https://spec.edmcouncil.org/auto/ontology/VC/VehicleCore/', 'https://spec.edmcouncil.org/auto/ontology/VC/VehicleCore/*', null, null), + ('fff', 'http://sbmi.uth.edu/ontology/offf', 'http://sbmi.uth.edu/ontology/offf/*', null, null), + ('wq', 'http://purl.org/nemo/doce#/2022-02-23', 'http://purl.org/nemo/doce#/2022-02-23/*', null, null), + ('weather', 'https://www.auto.tuwien.ac.at/downloads/thinkhome/ontology/WeatherOntology.owl', 'https://www.auto.tuwien.ac.at/downloads/thinkhome/ontology/WeatherOntology.owl/*', null, null), + ('qudt', 'http://qudt.org/2.1/vocab/quantitykind', 'http://qudt.org/2.1/vocab/quantitykind/*', null, null), + ('ucum', 'http://elite.polito.it/ontologies/ucum-instances.owl', 'http://elite.polito.it/ontologies/ucum-instances.owl/*', null, null); COMMIT; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java index 37aa493020..03e224bc31 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/ColumnCreateDto.java @@ -49,9 +49,15 @@ public class ColumnCreateDto { @JsonProperty("concept_uri") private String conceptUri; + @JsonProperty("concept_label") + private String conceptLabel; + @JsonProperty("unit_uri") private String unitUri; + @JsonProperty("unit_label") + private String unitLabel; + @Schema(description = "date format id") private Long dfid; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java index 77a38f70b4..4d0533e11a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/concepts/ColumnSemanticsUpdateDto.java @@ -16,6 +16,12 @@ public class ColumnSemanticsUpdateDto { @JsonProperty("concept_uri") private String conceptUri; + @JsonProperty("concept_label") + private String conceptLabel; + @JsonProperty("unit_uri") private String unitUri; + + @JsonProperty("unit_label") + private String unitLabel; } diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java index 557d1e49ab..ff5b4f5361 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -455,8 +455,14 @@ public interface MetadataMapper { TableColumnUnit unitSaveDtoToTableColumnUnit(UnitSaveDto data); + @Mappings({ + @Mapping(target = "name", source = "label"), + }) TableColumnUnit entityDtoToTableColumnUnit(EntityDto data); + @Mappings({ + @Mapping(target = "name", source = "label"), + }) TableColumnConcept entityDtoToTableColumnConcept(EntityDto data); TableColumnConcept conceptSaveDtoToTableColumnConcept(ConceptSaveDto data); diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java index cd17c7ac0b..ac14066b41 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java @@ -5,8 +5,6 @@ import at.tuwien.api.semantics.*; import at.tuwien.entities.semantics.Ontology; import at.tuwien.exception.*; import at.tuwien.mapper.MetadataMapper; -import at.tuwien.mapper.SparqlMapper; -import at.tuwien.service.EntityService; import at.tuwien.service.OntologyService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; @@ -34,14 +32,11 @@ import java.util.List; @RequestMapping(path = "/api/ontology") public class OntologyEndpoint { - private final EntityService entityService; private final MetadataMapper metadataMapper; private final OntologyService ontologyService; @Autowired - public OntologyEndpoint(EntityService entityService, MetadataMapper metadataMapper, - OntologyService ontologyService) { - this.entityService = entityService; + public OntologyEndpoint(MetadataMapper metadataMapper, OntologyService ontologyService) { this.metadataMapper = metadataMapper; this.ontologyService = ontologyService; } @@ -164,68 +159,4 @@ public class OntologyEndpoint { .build(); } - @GetMapping("/{ontologyId}/entity") - @PreAuthorize("hasAuthority('execute-semantic-query')") - @Observed(name = "dbrepo_ontologies_entities_find") - @Operation(summary = "Find entities", - description = "Finds semantic entities by label or uri in an ontology with id. Requires role `execute-semantic-query`.", - security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "Found entities", - content = {@Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = EntityDto.class)))}), - @ApiResponse(responseCode = "400", - description = "Filter params are invalid", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "404", - description = "Could not find ontology", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "417", - description = "Generated query or uri is malformed", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "422", - description = "Ontology does not have rdf or sparql endpoint", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - }) - public ResponseEntity<List<EntityDto>> find(@NotNull @PathVariable("ontologyId") Long id, - @RequestParam(name = "label", required = false) String label, - @RequestParam(name = "uri", required = false) String uri) - throws OntologyNotFoundException, UriMalformedException, FilterBadRequestException, MalformedException { - log.debug("endpoint find entities by uri, id={}, label={}, uri={}", id, label, uri); - final Ontology ontology = ontologyService.find(id); - /* check */ - if ((label != null && uri != null) || (label == null && uri == null)) { - log.error("Failed to find entities: either label or uri must be defined"); - throw new FilterBadRequestException("Failed to find entities: either label or uri must be defined"); - } - if (uri != null && !uri.startsWith(ontology.getUri())) { - log.error("Failed to find entities: uri {} does not start with expected ontology uri {}", uri, ontology.getUri()); - throw new UriMalformedException("Failed to find entity: uri " + uri + " does not start with expected ontology uri " + ontology.getUri()); - } - if (ontology.getSparqlEndpoint() == null) { - log.error("Failed to find SPARQL endpoint for ontology with id {}", ontology.getId()); - throw new OntologyNotFoundException("Failed to find SPARQL endpoint for ontology with id " + ontology.getId()); - } - /* get */ - final List<EntityDto> dtos; - if (uri != null) { - dtos = entityService.findByUri(uri); - return ResponseEntity.ok() - .body(dtos); - } - dtos = entityService.findByLabel(ontology, label); - return ResponseEntity.ok() - .body(dtos); - } - } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index 4fb8240b1d..9b4fb753a3 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -8,8 +8,6 @@ import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; import at.tuwien.api.error.ApiErrorDto; -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.TableColumnEntityDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.Table; import at.tuwien.entities.database.table.columns.TableColumn; @@ -50,18 +48,15 @@ public class TableEndpoint { private final UserService userService; private final TableService tableService; - private final EntityService entityService; private final MetadataMapper metadataMapper; private final DatabaseService databaseService; private final EndpointValidator endpointValidator; @Autowired - public TableEndpoint(UserService userService, TableService tableService, EntityService entityService, - MetadataMapper metadataMapper, DatabaseService databaseService, - EndpointValidator endpointValidator) { + public TableEndpoint(UserService userService, TableService tableService, MetadataMapper metadataMapper, + DatabaseService databaseService, EndpointValidator endpointValidator) { this.userService = userService; this.tableService = tableService; - this.entityService = entityService; this.metadataMapper = metadataMapper; this.databaseService = databaseService; this.endpointValidator = endpointValidator; @@ -105,50 +100,6 @@ public class TableEndpoint { return ResponseEntity.ok(dto); } - @GetMapping("/{tableId}/suggest") - @Transactional(readOnly = true) - @PreAuthorize("hasAuthority('table-semantic-analyse')") - @Observed(name = "dbrepo_semantic_table_analyse") - @Operation(summary = "Suggest semantics", - description = "Suggests semantic concepts for a table. Requires role `table-semantic-analyse`.", - security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "Suggested table semantics successfully", - content = {@Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = EntityDto.class)))}), - @ApiResponse(responseCode = "400", - description = "Failed to parse statistic in search service", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "404", - description = "Failed to find database/table in metadata database", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "417", - description = "Generated query is malformed", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "422", - description = "Ontology does not have rdf or sparql endpoint", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - }) - public ResponseEntity<List<EntityDto>> analyseTable(@NotNull @PathVariable("databaseId") Long databaseId, - @NotNull @PathVariable("tableId") Long tableId) - throws MalformedException, TableNotFoundException, DatabaseNotFoundException { - log.debug("endpoint analyse table semantics, databaseId={}, tableId={}", databaseId, tableId); - final Table table = tableService.findById(databaseId, tableId); - final List<EntityDto> dtos = entityService.suggestByTable(table); - return ResponseEntity.ok() - .body(dtos); - } - @PutMapping("/{tableId}") @Transactional @PreAuthorize("hasAuthority('update-table-statistic')") @@ -254,47 +205,6 @@ public class TableEndpoint { .body(columnDto); } - @GetMapping("/{tableId}/column/{columnId}/suggest") - @Transactional(readOnly = true) - @PreAuthorize("hasAuthority('table-semantic-analyse')") - @Observed(name = "dbrepo_semantic_column_analyse") - @Operation(summary = "Suggest semantics", - description = "Suggests column semantics. Requires role `table-semantic-analyse`.", - security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "Suggested table column semantics successfully", - content = {@Content( - mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = TableColumnEntityDto.class)))}), - @ApiResponse(responseCode = "400", - description = "Generated query is malformed", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "404", - description = "Failed to find database/table in metadata database", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "422", - description = "Ontology does not have rdf or sparql endpoint", - content = {@Content( - mediaType = "application/json", - schema = @Schema(implementation = ApiErrorDto.class))}), - }) - public ResponseEntity<List<TableColumnEntityDto>> analyseTableColumn(@NotNull @PathVariable("databaseId") Long databaseId, - @NotNull @PathVariable("tableId") Long tableId, - @NotNull @PathVariable("columnId") Long columnId) - throws MalformedException, TableNotFoundException, DatabaseNotFoundException { - log.debug("endpoint analyse table column semantics, databaseId={}, tableId={}, columnId={}", databaseId, tableId, columnId); - final Table table = tableService.findById(databaseId, tableId); - TableColumn column = tableService.findColumnById(table, columnId); - final List<TableColumnEntityDto> dtos = entityService.suggestByColumn(column); - return ResponseEntity.ok() - .body(dtos); - } - @PostMapping @Transactional(rollbackFor = {Exception.class}) @PreAuthorize("hasAuthority('create-table')") diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/OntologyEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/OntologyEndpointUnitTest.java index fc20a0b9e3..297c21a386 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/OntologyEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/OntologyEndpointUnitTest.java @@ -5,7 +5,6 @@ import at.tuwien.api.semantics.*; import at.tuwien.entities.semantics.Ontology; import at.tuwien.entities.user.User; import at.tuwien.exception.*; -import at.tuwien.service.EntityService; import at.tuwien.service.OntologyService; import at.tuwien.service.UserService; import lombok.extern.log4j.Log4j2; @@ -37,9 +36,6 @@ public class OntologyEndpointUnitTest extends AbstractUnitTest { @MockBean private OntologyService ontologyService; - @MockBean - private EntityService entityService; - @MockBean private UserService userService; @@ -177,78 +173,6 @@ public class OntologyEndpointUnitTest extends AbstractUnitTest { delete_generic(ONTOLOGY_1_ID, ONTOLOGY_1); } - @Test - @WithAnonymousUser - public void find_anonymous_fails() { - - /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - find_generic(ONTOLOGY_2_ID, "Apache Jena", null, ONTOLOGY_2, null); - }); - } - - @Test - @WithMockUser(username = USER_4_USERNAME, authorities = {}) - public void find_noRole_fails() { - - /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - find_generic(ONTOLOGY_2_ID, "Apache Jena", null, ONTOLOGY_2, null); - }); - } - - @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"execute-semantic-query"}) - public void find_hasRoleInvalidParams_succeeds() { - - /* test */ - assertThrows(FilterBadRequestException.class, () -> { - find_generic(ONTOLOGY_2_ID, "Apache Jena", "http://www.wikidata.org/entity/Q1686799", ONTOLOGY_2, null); - }); - } - - @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"execute-semantic-query"}) - public void find_hasRoleNotOntologyUri_succeeds() { - - /* test */ - assertThrows(UriMalformedException.class, () -> { - find_generic(ONTOLOGY_2_ID, null, "https://wikidata.org/entity/Q1686799", ONTOLOGY_2, null); - }); - } - - @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"execute-semantic-query"}) - public void find_hasRoleLabel_succeeds() throws MalformedException, UriMalformedException, OntologyNotFoundException, - FilterBadRequestException { - final EntityDto entityDto = EntityDto.builder() - .label("Apache Jena") - .uri("http://www.wikidata.org/entity/Q1686799") - .build(); - - /* test */ - final List<EntityDto> response = find_generic(ONTOLOGY_2_ID, "Apache Jena", null, ONTOLOGY_2, entityDto); - final EntityDto entity0 = response.get(0); - assertEquals("Apache Jena", entity0.getLabel()); - assertEquals("http://www.wikidata.org/entity/Q1686799", entity0.getUri()); - } - - @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"execute-semantic-query"}) - public void find_hasRoleUri_succeeds() throws MalformedException, UriMalformedException, OntologyNotFoundException, - FilterBadRequestException { - final EntityDto entityDto = EntityDto.builder() - .label("Apache Jena") - .uri("http://www.wikidata.org/entity/Q1686799") - .build(); - - /* test */ - final List<EntityDto> response = find_generic(ONTOLOGY_2_ID, null, "http://www.wikidata.org/entity/Q1686799", ONTOLOGY_2, entityDto); - final EntityDto entity0 = response.get(0); - assertEquals("Apache Jena", entity0.getLabel()); - assertEquals("http://www.wikidata.org/entity/Q1686799", entity0.getUri()); - } - /* ################################################################################################### */ /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ @@ -347,37 +271,4 @@ public class OntologyEndpointUnitTest extends AbstractUnitTest { final ResponseEntity<?> response = ontologyEndpoint.delete(ontologyId); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } - - public List<EntityDto> find_generic(Long ontologyId, String label, String uri, Ontology ontology, - EntityDto entityDto) throws MalformedException, UriMalformedException, - FilterBadRequestException, OntologyNotFoundException { - - /* mock */ - if (ontology != null) { - when(ontologyService.find(ontologyId)) - .thenReturn(ontology); - } else { - doThrow(OntologyNotFoundException.class) - .when(ontologyService) - .find(ontologyId); - } - if (entityDto != null) { - when(entityService.findByLabel(ontology, label)) - .thenReturn(List.of(entityDto)); - when(entityService.findByUri(uri)) - .thenReturn(List.of(entityDto)); - } else { - when(entityService.findByLabel(ontology, label)) - .thenReturn(List.of()); - when(entityService.findByUri(uri)) - .thenReturn(List.of()); - } - - /* test */ - final ResponseEntity<List<EntityDto>> response = ontologyEndpoint.find(ontologyId, label, uri); - assertEquals(HttpStatus.OK, response.getStatusCode()); - final List<EntityDto> body = response.getBody(); - assertNotNull(body); - return body; - } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java index 154ebda86c..2a9b4ec382 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java @@ -8,8 +8,6 @@ import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.TableColumnEntityDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.database.table.Table; @@ -58,9 +56,6 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @MockBean private UserService userService; - @MockBean - private EntityService entityService; - @MockBean private BrokerService messageQueueService; @@ -395,64 +390,6 @@ public class TableEndpointUnitTest extends AbstractUnitTest { generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, null); } - @Test - @WithAnonymousUser - public void analyseTable_anonymous_fails() { - - /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - analyseTable_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1); - }); - } - - @Test - @WithMockUser(username = USER_4_USERNAME) - public void findAll_noRole_fails() { - - /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - analyseTable_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1); - }); - } - - @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"table-semantic-analyse"}) - public void findAll_hasRole_succeeds() throws MalformedException, TableNotFoundException, - DatabaseNotFoundException { - - /* test */ - analyseTable_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1); - } - - @Test - @WithAnonymousUser - public void analyseTableColumn_anonymous_fails() { - - /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - analyseTableColumn_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0)); - }); - } - - @Test - @WithMockUser(username = USER_4_USERNAME) - public void analyseTableColumn_noRole_fails() { - - /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - analyseTableColumn_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0)); - }); - } - - @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"table-semantic-analyse"}) - public void analyseTableColumn_hasRole_succeeds() throws MalformedException, TableNotFoundException, - DatabaseNotFoundException { - - /* test */ - analyseTableColumn_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0)); - } - @Test @WithAnonymousUser public void update_publicAnonymous_fails() { @@ -837,34 +774,6 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - public void analyseTable_generic(Long databaseId, Long tableId, Table table) throws MalformedException, - TableNotFoundException, DatabaseNotFoundException { - - /* mock */ - when(entityService.suggestByTable(table)) - .thenReturn(List.of()); - - /* test */ - final ResponseEntity<List<EntityDto>> response = tableEndpoint.analyseTable(databaseId, tableId); - assertEquals(HttpStatus.OK, response.getStatusCode()); - final List<EntityDto> body = response.getBody(); - assertNotNull(body); - } - - public void analyseTableColumn_generic(Long databaseId, Long tableId, Long columnId, TableColumn tableColumn) - throws MalformedException, TableNotFoundException, DatabaseNotFoundException { - - /* mock */ - when(entityService.suggestByColumn(tableColumn)) - .thenReturn(List.of()); - - /* test */ - final ResponseEntity<List<TableColumnEntityDto>> response = tableEndpoint.analyseTableColumn(databaseId, tableId, columnId); - assertEquals(HttpStatus.OK, response.getStatusCode()); - final List<TableColumnEntityDto> body = response.getBody(); - assertNotNull(body); - } - protected ResponseEntity<List<TableBriefDto>> generic_list(Long databaseId, Database database, Principal principal, User user, DatabaseAccess access) throws NotAllowedException, DatabaseNotFoundException, AccessNotFoundException, UserNotFoundException { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java index d3f75d7060..ce621be569 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java @@ -446,11 +446,6 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } catch (Exception e) { /* ignore */ } - try { - ontologyEndpoint.find(ONTOLOGY_1_ID, "thing", null); - } catch (Exception e) { - /* ignore */ - } /* test */ for (String metric : List.of("dbrepo_ontologies_findall", "dbrepo_ontologies_find", "dbrepo_ontologies_create", "dbrepo_ontologies_update", "dbrepo_ontologies_delete", "dbrepo_ontologies_entities_find")) { @@ -529,21 +524,11 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { } catch (Exception e) { /* ignore */ } - try { - tableEndpoint.analyseTable(DATABASE_1_ID, TABLE_1_ID); - } catch (Exception e) { - /* ignore */ - } try { tableEndpoint.updateStatistic(DATABASE_1_ID, TABLE_1_ID); } catch (Exception e) { /* ignore */ } - try { - tableEndpoint.analyseTableColumn(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId()); - } catch (Exception e) { - /* ignore */ - } try { tableEndpoint.update(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(3).getId(), request, USER_1_PRINCIPAL); } catch (Exception e) { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/EntityServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/EntityServiceUnitTest.java deleted file mode 100644 index fd6ac82762..0000000000 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/EntityServiceUnitTest.java +++ /dev/null @@ -1,163 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.test.AbstractUnitTest; -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.TableColumnEntityDto; -import at.tuwien.exception.*; -import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; - -@Log4j2 -@SpringBootTest -@ExtendWith(SpringExtension.class) -public class EntityServiceUnitTest extends AbstractUnitTest { - - @MockBean - private OntologyService ontologyService; - - @Autowired - private EntityService entityService; - - @BeforeEach - public void beforeEach() { - genesis(); - } - - @Test - public void findByLabel_wikidataSparql_succeeds() throws MalformedException { - - /* mock */ - when(ontologyService.findAll()) - .thenReturn(List.of(ONTOLOGY_1, ONTOLOGY_2, ONTOLOGY_3, ONTOLOGY_4)); - - /* test */ - final List<EntityDto> response = entityService.findByLabel(ONTOLOGY_2, "temperature"); - assertFalse(response.isEmpty()); - final EntityDto entity0 = response.get(0); - assertNotNull(entity0.getUri()); - log.trace("found concept {}", entity0); - } - - @Test - public void findByUri_wikidataSparql_succeeds() throws MalformedException, OntologyNotFoundException { - - /* mock */ - when(ontologyService.find(CONCEPT_1_URI)) - .thenReturn(ONTOLOGY_1); - when(ontologyService.findAll()) - .thenReturn(List.of(ONTOLOGY_1, ONTOLOGY_2, ONTOLOGY_3, ONTOLOGY_4)); - - /* test */ - final List<EntityDto> response = entityService.findByUri(CONCEPT_1_URI); - assertEquals(1, response.size()); - final EntityDto entity0 = response.get(0); - assertNotNull(entity0.getUri()); - log.trace("found concept {}", entity0); - } - - @Test - public void findOneByUri_wikidataSparql_succeeds() throws MalformedException, SemanticEntityNotFoundException, - OntologyNotFoundException { - - /* mock */ - when(ontologyService.find(CONCEPT_1_URI)) - .thenReturn(ONTOLOGY_1); - when(ontologyService.findAll()) - .thenReturn(List.of(ONTOLOGY_1, ONTOLOGY_2, ONTOLOGY_3, ONTOLOGY_4)); - - /* test */ - final EntityDto response = entityService.findOneByUri(CONCEPT_1_URI); - assertNotNull(response.getUri()); - log.trace("found concept {}", response); - } - - @Test - public void findByLabel_om2Rdf_succeeds() throws MalformedException { - - /* mock */ - when(ontologyService.findAll()) - .thenReturn(List.of(ONTOLOGY_1, ONTOLOGY_2, ONTOLOGY_3, ONTOLOGY_4)); - - /* test */ - final List<EntityDto> response = entityService.findByLabel(ONTOLOGY_1, "millimetre"); - assertFalse(response.isEmpty()); - final EntityDto entity0 = response.get(0); - assertNotNull(entity0.getUri()); - log.trace("found unit {}", entity0); - } - - @Test - public void findByUri_om2Rdf_succeeds() throws MalformedException, OntologyNotFoundException { - - /* mock */ - when(ontologyService.find(UNIT_1_URI)) - .thenReturn(ONTOLOGY_1); - when(ontologyService.findAll()) - .thenReturn(List.of(ONTOLOGY_1, ONTOLOGY_2, ONTOLOGY_3, ONTOLOGY_4, ONTOLOGY_5)); - - /* test */ - final List<EntityDto> response = entityService.findByUri(UNIT_1_URI); - assertEquals(1, response.size()); - final EntityDto entity0 = response.get(0); - assertNotNull(entity0.getUri()); - log.trace("found unit {}", entity0); - } - - @Test - @Disabled("integration") - public void suggestByTable_succeeds() throws MalformedException { - - /* mock */ - when(ontologyService.findAll()) - .thenReturn(List.of(ONTOLOGY_1, ONTOLOGY_2, ONTOLOGY_3, ONTOLOGY_4, ONTOLOGY_5)); - when(ontologyService.findAllProcessable()) - .thenReturn(List.of(ONTOLOGY_2, ONTOLOGY_5)); - - /* test */ - final List<EntityDto> response = entityService.suggestByTable(TABLE_2); - assertEquals(1, response.size()); - } - - @Test - public void suggestTableColumnSemantics_succeeds() throws MalformedException { - - /* mock */ - when(ontologyService.findAll()) - .thenReturn(List.of(ONTOLOGY_1, ONTOLOGY_2, ONTOLOGY_3, ONTOLOGY_4, ONTOLOGY_5)); - when(ontologyService.findAllProcessable()) - .thenReturn(List.of(ONTOLOGY_2, ONTOLOGY_5)); - - /* test */ - final List<TableColumnEntityDto> response = entityService.suggestByColumn(TABLE_1_COLUMNS.get(0)); - assertFalse(response.isEmpty()); - } - - @Test - public void findByUri_noRdfNoSparql_fails() throws OntologyNotFoundException { - - /* mock */ - doThrow(OntologyNotFoundException.class) - .when(ontologyService) - .find(anyString()); - - /* test */ - assertThrows(OntologyNotFoundException.class, () -> { - entityService.findByUri("http://schema.org/MedicalCondition"); - }); - } - -} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/EntityService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/EntityService.java deleted file mode 100644 index 69a801cf5c..0000000000 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/EntityService.java +++ /dev/null @@ -1,64 +0,0 @@ -package at.tuwien.service; - -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.TableColumnEntityDto; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.semantics.Ontology; -import at.tuwien.exception.*; - -import java.util.List; - -public interface EntityService { - - /** - * Finds entities in the ontology whose label match the given label. - * - * @param ontology The ontology. - * @param label The label. - * @return The list of entities that match. - */ - List<EntityDto> findByLabel(Ontology ontology, String label) throws MalformedException; - - /** - * Finds entities in the ontology whose label match the given label with maximum number of entities. - * - * @param ontology The ontology. - * @param label The label. - * @param limit The maximum number of entities to return. - * @return The list of entities that match. - */ - List<EntityDto> findByLabel(Ontology ontology, String label, Integer limit) throws MalformedException; - - /** - * Finds entities in the ontology whose uri match the given uri. - * - * @param uri The uri. - * @return The list of entities that match. - */ - List<EntityDto> findByUri(String uri) throws MalformedException, OntologyNotFoundException; - - /** - * Finds an entity in the ontology whose uri match the given uri. - * - * @param uri The uri. - * @return The entity, if successful. - */ - EntityDto findOneByUri(String uri) throws MalformedException, SemanticEntityNotFoundException, OntologyNotFoundException; - - /** - * Attempts to suggest table semantics for a table with given id in database with given id. - * - * @param table The table. - * @return The list of entities that were suggested. - */ - List<EntityDto> suggestByTable(Table table) throws MalformedException; - - /** - * Attempts to suggest table column semantics for a table column in table with given id in database with given id. - * - * @param column The table column. - * @return The list of entities that were suggested. - */ - List<TableColumnEntityDto> suggestByColumn(TableColumn column) throws MalformedException; -} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/EntityServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/EntityServiceImpl.java deleted file mode 100644 index dba30481f5..0000000000 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/EntityServiceImpl.java +++ /dev/null @@ -1,167 +0,0 @@ -package at.tuwien.service.impl; - -import at.tuwien.api.semantics.EntityDto; -import at.tuwien.api.semantics.TableColumnEntityDto; -import at.tuwien.config.JenaConfig; -import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.semantics.Ontology; -import at.tuwien.exception.*; -import at.tuwien.mapper.SparqlMapper; -import at.tuwien.service.EntityService; -import at.tuwien.service.OntologyService; -import lombok.extern.log4j.Log4j2; -import org.apache.jena.query.*; -import org.apache.jena.rdf.model.RDFNode; -import org.apache.jena.riot.RDFDataMgr; -import org.apache.jena.riot.RiotException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -@Log4j2 -@Service -public class EntityServiceImpl implements EntityService { - - private final Dataset dataset; - private final JenaConfig jenaConfig; - private final SparqlMapper ontologyMapper; - private final OntologyService ontologyService; - - @Autowired - public EntityServiceImpl(Dataset dataset, JenaConfig jenaConfig, SparqlMapper ontologyMapper, - OntologyService ontologyService) { - this.dataset = dataset; - this.jenaConfig = jenaConfig; - this.ontologyMapper = ontologyMapper; - this.ontologyService = ontologyService; - } - - public void validateOntology(Ontology ontology) throws MalformedException { - if (ontology.getRdfPath() == null && ontology.getSparqlEndpoint() == null) { - log.error("Ontology with uri {} is invalid: no RDF file present and no SPARQL endpoint found", ontology.getUri()); - throw new MalformedException("Ontology with uri " + ontology.getUri() + " is invalid: no RDF file present and no SPARQL endpoint found"); - } - } - - @Override - public List<EntityDto> findByLabel(Ontology ontology, String label) throws MalformedException { - return findByLabel(ontology, label, 10); - } - - @Override - public List<EntityDto> findByLabel(Ontology ontology, String label, Integer limit) throws MalformedException { - /* check */ - validateOntology(ontology); - /* find */ - final List<Ontology> ontologies = ontologyService.findAll(); - final String statement = ontologyMapper.ontologyToFindByLabelQuery(ontologies, ontology, label, limit); - log.trace("execute sparql query:\n{}", statement); - final List<EntityDto> results = new LinkedList<>(); - if (ontology.getSparqlEndpoint() == null && ontology.getRdfPath() != null) { - log.debug("load rdf model from path {}", ontology.getRdfPath()); - this.dataset.setDefaultModel(RDFDataMgr.loadModel(ontology.getRdfPath())); - } - try (QueryExecution execution = QueryExecutionDatasetBuilder.create() - .model(this.dataset.getDefaultModel()) - .query(statement) - .timeout(jenaConfig.getConnectionTimeout(), TimeUnit.MILLISECONDS) - .build()) { - final Iterator<QuerySolution> resultSet = execution.execSelect(); - while (resultSet.hasNext()) { - final QuerySolution solution = resultSet.next(); - final RDFNode description = solution.get("description"); - final EntityDto entity = EntityDto.builder() - .uri(solution.get("o").toString()) - .label(label) - .description(description != null ? description.asLiteral().getLexicalForm() : null) - .build(); - results.add(entity); - } - } catch (QueryParseException | IllegalArgumentException | RiotException e) { - log.error("Failed to parse query: {}", e.getMessage()); - throw new MalformedException("Failed to parse query: " + e.getMessage(), e); - } - return results; - } - - @Override - public List<EntityDto> findByUri(String uri) throws MalformedException, OntologyNotFoundException { - /* find */ - final Ontology ontology = ontologyService.find(uri); - final List<Ontology> ontologies = ontologyService.findAll(); - final String statement = ontologyMapper.ontologyToFindByUriQuery(ontologies, ontology, uri); - log.trace("execute sparql query:\n{}", statement); - try (QueryExecution execution = QueryExecutionDatasetBuilder.create() - .model(this.dataset.getDefaultModel()) - .query(statement) - .timeout(jenaConfig.getConnectionTimeout(), TimeUnit.MILLISECONDS) - .build()) { - final Iterator<QuerySolution> resultSet = execution.execSelect(); - final List<EntityDto> results = new LinkedList<>(); - while (resultSet.hasNext()) { - final QuerySolution solution = resultSet.next(); - final RDFNode label = solution.get("label"); - final RDFNode description = solution.get("description"); - final EntityDto entity = EntityDto.builder() - .uri(uri) - .label(label != null ? label.asLiteral().getLexicalForm() : null) - .description(description != null ? description.asLiteral().getLexicalForm() : null) - .build(); - results.add(entity); - } - return results; - } catch (QueryParseException | IllegalArgumentException | RiotException e) { - log.error("Failed to parse query: {}", e.getMessage()); - throw new MalformedException("Failed to parse query: " + e.getMessage(), e); - } - } - - @Override - public EntityDto findOneByUri(String uri) throws MalformedException, SemanticEntityNotFoundException, - OntologyNotFoundException { - /* find */ - final List<EntityDto> results = findByUri(uri); - if (results.size() != 1) { - log.error("None or multiple entities found for uri {}", uri); - throw new SemanticEntityNotFoundException("None or multiple entities found for uri " + uri); - } - return results.get(0); - } - - @Override - @Transactional(readOnly = true) - public List<EntityDto> suggestByTable(Table table) throws MalformedException { - final List<EntityDto> suggestions = new LinkedList<>(); - for (Ontology ontology : ontologyService.findAllProcessable()) { - suggestions.addAll(findByLabel(ontology, table.getName(), 3)); - } - return suggestions; - } - - @Override - @Transactional(readOnly = true) - public List<TableColumnEntityDto> suggestByColumn(TableColumn tableColumn) throws MalformedException { - final List<TableColumnEntityDto> suggestions = new LinkedList<>(); - for (Ontology ontology : ontologyService.findAllProcessable()) { - suggestions.addAll(findByLabel(ontology, tableColumn.getName(), 3) - .stream() - .map(e -> TableColumnEntityDto.builder() - .databaseId(tableColumn.getTable().getDatabase().getId()) - .tableId(tableColumn.getTable().getId()) - .columnId(tableColumn.getId()) - .label(e.getLabel()) - .uri(e.getUri()) - .description(e.getDescription()) - .build()) - .toList()); - } - return suggestions; - } - -} diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java index 7ca855974e..8572372516 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -6,6 +6,7 @@ import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnStatisticDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; +import at.tuwien.api.semantics.EntityDto; import at.tuwien.config.RabbitConfig; import at.tuwien.entities.container.image.ContainerImageDate; import at.tuwien.entities.database.Database; @@ -36,7 +37,6 @@ public class TableServiceImpl implements TableService { private final UserService userService; private final UnitService unitService; private final RabbitConfig rabbitConfig; - private final EntityService entityService; private final ConceptService conceptService; private final MetadataMapper metadataMapper; private final DatabaseService databaseService; @@ -46,13 +46,12 @@ public class TableServiceImpl implements TableService { @Autowired public TableServiceImpl(UserService userService, UnitService unitService, RabbitConfig rabbitConfig, - EntityService entityService, ConceptService conceptService, MetadataMapper metadataMapper, + ConceptService conceptService, MetadataMapper metadataMapper, DatabaseService databaseService, DataServiceGateway dataServiceGateway, DatabaseRepository databaseRepository, SearchServiceGateway searchServiceGateway) { this.userService = userService; this.unitService = unitService; this.rabbitConfig = rabbitConfig; - this.entityService = entityService; this.conceptService = conceptService; this.metadataMapper = metadataMapper; this.databaseService = databaseService; @@ -128,23 +127,31 @@ public class TableServiceImpl implements TableService { column.setTable(table); if (c.getUnitUri() != null) { log.trace("column {} has assigned unit uri: {}", column.getInternalName(), c.getUnitUri()); - TableColumnUnit unit; try { - unit = unitService.find(c.getUnitUri()); + column.setUnit(unitService.find(c.getUnitUri())); + log.debug("found unit by uri: {}", c.getUnitUri()); } catch (UnitNotFoundException e) { - unit = unitService.create(metadataMapper.entityDtoToTableColumnUnit(entityService.findOneByUri(c.getUnitUri()))); + final TableColumnUnit unit = metadataMapper.entityDtoToTableColumnUnit(EntityDto.builder() + .uri(c.getUnitUri()) + .label(c.getUnitLabel()) + .build()); + column.setUnit(unitService.create(unit)); + log.trace("created unit in metadata database: {}", unit); } - column.setUnit(unit); } if (c.getConceptUri() != null) { log.trace("column {} has assigned concept uri: {}", column.getInternalName(), c.getConceptUri()); - TableColumnConcept concept; try { - concept = conceptService.find(c.getConceptUri()); + column.setConcept(conceptService.find(c.getConceptUri())); + log.debug("found concept by uri: {}", c.getConceptUri()); } catch (ConceptNotFoundException e) { - concept = conceptService.create(metadataMapper.entityDtoToTableColumnConcept(entityService.findOneByUri(c.getConceptUri()))); + final TableColumnConcept concept = metadataMapper.entityDtoToTableColumnConcept(EntityDto.builder() + .uri(c.getConceptUri()) + .label(c.getConceptLabel()) + .build()); + column.setConcept(conceptService.create(concept)); + log.trace("created concept in metadata database: {}", concept); } - column.setConcept(concept); } if (List.of(TableColumnType.TIME, TableColumnType.TIMESTAMP, TableColumnType.DATE, TableColumnType.DATETIME).contains(column.getColumnType())) { final Optional<ContainerImageDate> optional = database.getContainer() @@ -218,24 +225,32 @@ public class TableServiceImpl implements TableService { SemanticEntityNotFoundException { /* assign */ if (data.getUnitUri() != null) { - TableColumnUnit unit; try { - unit = unitService.find(data.getUnitUri()); + column.setUnit(unitService.find(data.getUnitUri())); + log.debug("found unit by uri: {}", data.getUnitUri()); } catch (UnitNotFoundException e) { - unit = metadataMapper.entityDtoToTableColumnUnit(entityService.findOneByUri(data.getUnitUri())); + final TableColumnUnit unit = metadataMapper.entityDtoToTableColumnUnit(EntityDto.builder() + .uri(data.getUnitUri()) + .label(data.getUnitLabel()) + .build()); + log.trace("create unit in metadata database: {}", unit); + column.setUnit(unit); } - column.setUnit(unit); } else { column.setUnit(null); } if (data.getConceptUri() != null) { - TableColumnConcept concept; try { - concept = conceptService.find(data.getConceptUri()); + conceptService.find(data.getConceptUri()); + log.debug("found concept by uri: {}", data.getConceptUri()); } catch (ConceptNotFoundException e) { - concept = metadataMapper.entityDtoToTableColumnConcept(entityService.findOneByUri(data.getConceptUri())); + final TableColumnConcept concept = metadataMapper.entityDtoToTableColumnConcept(EntityDto.builder() + .uri(data.getConceptUri()) + .label(data.getConceptLabel()) + .build()); + log.trace("create concept in metadata database: {}", concept); + column.setConcept(concept); } - column.setConcept(concept); } else { column.setConcept(null); } diff --git a/dbrepo-ui/components/table/TableSchema.vue b/dbrepo-ui/components/table/TableSchema.vue index 845039b136..8539962de5 100644 --- a/dbrepo-ui/components/table/TableSchema.vue +++ b/dbrepo-ui/components/table/TableSchema.vue @@ -149,11 +149,12 @@ cols="1"> <v-select v-if="c.concepts" - v-model="c.concept_uri" + v-model="c.concept" persistent-hint + :items="c.concepts" :item-title="item => `${item.name} (${item.ontology})`" item-value="uri" - :items="c.concepts" + return-object :label="$t('pages.table.subpages.schema.concept.label')" :hint="$t('pages.table.subpages.schema.concept.hint')" :id="'object' + c.name" @@ -169,11 +170,12 @@ cols="1"> <v-select v-if="c.units" - v-model="c.unit_uri" + v-model="c.unit" persistent-hint + :items="c.units" :item-title="item => `${item.name} (${item.ontology})`" item-value="uri" - :items="c.units" + return-object :label="$t('pages.table.subpages.schema.unit.label')" :hint="$t('pages.table.subpages.schema.unit.hint')" :id="'unit' + c.name" @@ -423,9 +425,9 @@ export default { name, type, concepts: [], - concept_uri: null, + concept: null, units: [], - unit_uri: null, + unit: null, null_allowed, primary_key, dfid: null, diff --git a/dbrepo-ui/composables/table-service.ts b/dbrepo-ui/composables/table-service.ts index d26fbce900..52959d33c0 100644 --- a/dbrepo-ui/composables/table-service.ts +++ b/dbrepo-ui/composables/table-service.ts @@ -187,22 +187,6 @@ export const useTableService = (): any => { }); } - async function suggest(databaseId: number, tableId: number, columnId: number): Promise<TableColumnEntityDto[]> { - const axios = useAxiosInstance() - console.debug('suggest semantic entities for table column with id', columnId, 'of table with id', tableId, 'of database with id', databaseId) - return new Promise<TableColumnEntityDto[]>((resolve, reject) => { - axios.get<TableColumnEntityDto[]>(`/api/database/${databaseId}/table/${tableId}/column/${columnId}/suggest`) - .then((response) => { - console.info('Suggested semantic entities for table column with id', columnId, 'of table with id', tableId, 'of database with id', databaseId) - resolve(response.data) - }) - .catch((error) => { - console.error('Failed to suggest semantic entities', error) - reject(axiosErrorToApiError(error)) - }) - }) - } - function prepareColumns(columns: InternalColumnDto[]): ColumnCreateDto[] { return columns.map((c: InternalColumnDto) => { const column: ColumnCreateDto = { @@ -215,8 +199,10 @@ export const useTableService = (): any => { sets: c.sets_values ? c.sets_values.split(',') : [], index_length: c.index_length, null_allowed: c.null_allowed, - concept_uri: c.concept_uri ? c.concept_uri : null, - unit_uri: c.unit_uri ? c.unit_uri : null + concept_uri: c.concept?.uri ? c.concept.uri : null, + concept_label: c.concept?.name ? c.concept.name : null, + unit_uri: c.unit?.uri ? c.unit.uri : null, + unit_label: c.unit?.name ? c.unit.name : null } return column }) @@ -271,7 +257,6 @@ export const useTableService = (): any => { remove, removeTuple, history, - suggest, prepareColumns, prepareConstraints, isOwner, diff --git a/dbrepo-ui/dto/index.ts b/dbrepo-ui/dto/index.ts index 4aff532930..e6cb7ffbe3 100644 --- a/dbrepo-ui/dto/index.ts +++ b/dbrepo-ui/dto/index.ts @@ -639,11 +639,20 @@ interface ColumnCreateDto { enums: string[]; sets: string[]; unit_uri: string | null; + unit_label: string | null; concept_uri: string | null; + concept_label: string | null; index_length: number; null_allowed: boolean; } +interface EntityDto { + name: string | null; + score: number; + uri: string; + ontology: string; +} + interface InternalColumnDto { name: string; type: string; @@ -652,6 +661,8 @@ interface InternalColumnDto { dfid: number; enums: string[]; sets: string[]; + unit: EntityDto | null; + concept: EntityDto | null; primary_key: boolean; index_length: number; null_allowed: boolean; -- GitLab