From 7b95d66e1adf6a3003700758494a4725fabf956d Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 13 Dec 2021 15:49:27 +0100 Subject: [PATCH] refactor(projectMetadataV2): remove projectMetadataV2 implementation (#1962) --- Makefile | 27 -- docs/03-apis/api-v2/metadata.md | 88 ---- mkdocs.yml | 1 - test_data/metadataE2EV2/metadata-flat.jsonld | 389 ----------------- test_data/metadataE2EV2/metadata.ttl | 394 ------------------ .../knora/webapi/app/ApplicationActor.scala | 1 - .../webapi/messages/StringFormatter.scala | 9 - .../metadatamessages/MetadataMessagesV2.scala | 101 ----- .../webapi/responders/ResponderManager.scala | 13 - .../responders/v2/MetadataResponderV2.scala | 96 ----- .../webapi/routing/v2/MetadataRouteV2.scala | 121 ------ .../scala/org/knora/webapi/e2e/v2/BUILD.bazel | 19 - .../e2e/v2/MetadataRouteV2E2ESpec.scala | 117 ------ .../v2/responder/metadatamessages/BUILD.bazel | 22 - .../MetadataMessagesV2Spec.scala | 49 --- .../knora/webapi/responders/v2/BUILD.bazel | 19 - .../v2/MetadataResponderV2Spec.scala | 193 --------- 17 files changed, 1659 deletions(-) delete mode 100644 docs/03-apis/api-v2/metadata.md delete mode 100644 test_data/metadataE2EV2/metadata-flat.jsonld delete mode 100644 test_data/metadataE2EV2/metadata.ttl delete mode 100644 webapi/src/main/scala/org/knora/webapi/messages/v2/responder/metadatamessages/MetadataMessagesV2.scala delete mode 100644 webapi/src/main/scala/org/knora/webapi/responders/v2/MetadataResponderV2.scala delete mode 100644 webapi/src/main/scala/org/knora/webapi/routing/v2/MetadataRouteV2.scala delete mode 100644 webapi/src/test/scala/org/knora/webapi/e2e/v2/MetadataRouteV2E2ESpec.scala delete mode 100644 webapi/src/test/scala/org/knora/webapi/messages/v2/responder/metadatamessages/BUILD.bazel delete mode 100644 webapi/src/test/scala/org/knora/webapi/messages/v2/responder/metadatamessages/MetadataMessagesV2Spec.scala delete mode 100644 webapi/src/test/scala/org/knora/webapi/responders/v2/MetadataResponderV2Spec.scala diff --git a/Makefile b/Makefile index 6a433c36ff..b0d753dc05 100644 --- a/Makefile +++ b/Makefile @@ -108,9 +108,6 @@ stack-up: docker-build env-file ## starts the knora-stack: fuseki, sipi, redis, docker-compose -f docker-compose.yml up -d $(CURRENT_DIR)/webapi/scripts/wait-for-knora.sh -.PHONY: stack-up-with-metadata -stack-up-with-metadata: stack-up metadata ## starts stack and adds metadata - .PHONY: stack-up-fast stack-up-fast: docker-build-knora-api-image env-file ## starts the knora-stack by skipping rebuilding most of the images (only api image is rebuilt). docker-compose -f docker-compose.yml up -d @@ -313,30 +310,6 @@ init-db-test-from-prod: db_prod_dump.trig init-db-test-empty ## init local datab @curl -X POST -H "Content-Type: application/sparql-update" -d "DROP ALL" -u "admin:test" "http://localhost:3030/knora-test" @curl -X POST -H "Content-Type: application/trig" --data-binary "@${CURRENT_DIR}/db_prod_dump.trig" -u "admin:test" "http://localhost:3030/knora-test" -.PHONY: metadata -metadata: metadata-standard metadata-minimal metadata-maximal ## add three example metadata sets - -.PHONY: metadata-standard -metadata-standard: ## add pseudo-realistic metadata set to anything project - @echo $@ - @mkdir -p .tmp - @curl https://raw.githubusercontent.com/dasch-swiss/dsp-ontologies/main/example/example-metadata.ttl -o .tmp/metadata.ttl -s - @curl -X PUT -u root@example.com:test -H "Content-Type: text/turtle" -T ".tmp/metadata.ttl" "localhost:3333/v2/metadata/http%3A%2F%2Frdfh.ch%2Fprojects%2F0001" -s -o /dev/null - -.PHONY: metadata-minimal -metadata-minimal: ## add minimal metadata set to images project - @echo $@ - @mkdir -p .tmp - @curl https://raw.githubusercontent.com/dasch-swiss/dsp-ontologies/main/example/example-metadata-minimal.ttl -o .tmp/metadata.ttl -s - @curl -X PUT -u root@example.com:test -H "Content-Type: text/turtle" -T ".tmp/metadata.ttl" "localhost:3333/v2/metadata/http%3A%2F%2Frdfh.ch%2Fprojects%2F00FF" -s -o /dev/null - -.PHONY: metadata-maximal -metadata-maximal: ## add maximal metadata set to dokubib project - @echo $@ - @mkdir -p .tmp - @curl https://raw.githubusercontent.com/dasch-swiss/dsp-ontologies/main/example/example-metadata-maximal.ttl -o .tmp/metadata.ttl -s - @curl -X PUT -u root@example.com:test -H "Content-Type: text/turtle" -T ".tmp/metadata.ttl" "localhost:3333/v2/metadata/http%3A%2F%2Frdfh.ch%2Fprojects%2F0804" -s -o /dev/null - ################################# ## Other ################################# diff --git a/docs/03-apis/api-v2/metadata.md b/docs/03-apis/api-v2/metadata.md deleted file mode 100644 index 0aca7ba387..0000000000 --- a/docs/03-apis/api-v2/metadata.md +++ /dev/null @@ -1,88 +0,0 @@ - - -# Metadata Endpoint - -## Endpoint Overview - -The metadata of a project contains information about its scope, content, contributors, funding, etc. modeled according to -to the [dsp-ontologies](https://github.com/dasch-swiss/dsp-ontologies) data model. Metadata information must be available for -any [DaSCH](http://dasch.swiss/) project so that researchers can go through the projects and get an idea about every project. - -## Creating and Updating Project Metadata - -Project metadata must correspond to the [dsp-ontologies](https://github.com/dasch-swiss/dsp-ontologies). - -To create or update project metadata for a project, submit it in a `PUT` request, specifying the project -IRI in the URL path: - -``` -PUT http://host/v2/metadata/PROJECT_IRI -``` - -Currently, all the metadata for a project must be submitted in a single request. The submitted metadata -replaces any metadata that has already been stored for the project. Only an administrator of the project, -or a system administrator, can create or update project metadata. - -The metadata can be submitted in **Turtle**, **JSON-LD**, or **RDF/XML** format. The request must -include a `Content-Type` header with one of the following values: - -| Format | MIME Type | -|---------|-----------------------| -| JSON-LD | `application/ld+json` | -| Turtle | `text/turtle` | -| RDF/XML | `application/rdf+xml` | - -An example request in Turtle format: - -```turtle -@prefix dsp-repo: . -@prefix rdf: . -@base . - - rdf:type dsp-repo:Project . - dsp-repo:hasName "Bernoulli-Euler Online (BEOL)" . - dsp-repo:hasKeywords "mathematics" . - dsp-repo:hasKeywords "science" . - dsp-repo:hasKeywords "history of science" . - dsp-repo:hasKeywords "history of mathematics" . - dsp-repo:hasCategories "mathematics" . - dsp-repo:hasStartDate "2016.07" . - dsp-repo:hasEndDate "2020.01" . - dsp-repo:hasFunder "Schweizerischer Nationalfonds (SNSF)" . -``` - -After successful creation of the metadata graph, the API returns HTTP 200 with a confirmation message. - -## Retrieving Project Metadata - -Any user can retrieve the metadata information for a project by providing its IRI in a `GET` request: - -``` -GET http://host/v2/metadata/PROJECT_IRI -``` - -The metadata can be returned in any of the formats listed in the previous section. By default, JSON-LD -is returned. To request another format, specify it in the `Accept` header of the request. - -An example response in JSON-LD format: - -```json -{ - "http://ns.dasch.swiss/repository#hasName": "Bernoulli-Euler Online (BEOL)", - "http://ns.dasch.swiss/repository#hasFunder": "Schweizerischer Nationalfonds (SNSF)", - "http://ns.dasch.swiss/repository#hasKeywords": [ - "science", - "mathematics", - "history of science", - "history of mathematics" - ], - "http://ns.dasch.swiss/repository#hasEndDate": "2020.01", - "http://ns.dasch.swiss/repository#hasCategories": "mathematics", - "@type": "http://ns.dasch.swiss/repository#Project", - "http://ns.dasch.swiss/repository#hasStartDate": "2016.07", - "@id": "http://ns.dasch.swiss/beol" -} -``` diff --git a/mkdocs.yml b/mkdocs.yml index 118b8251a1..2002604894 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -39,7 +39,6 @@ nav: - Introduction: 03-apis/api-v2/introduction.md - Authentication: 03-apis/api-v2/authentication.md - Knora IRIs: 03-apis/api-v2/knora-iris.md - - Metadata: 03-apis/api-v2/metadata.md - Reading and Searching Resources: 03-apis/api-v2/reading-and-searching-resources.md - Reading the User's Permissions on Resources and Values: 03-apis/api-v2/reading-user-permissions.md - Getting Lists: 03-apis/api-v2/getting-lists.md diff --git a/test_data/metadataE2EV2/metadata-flat.jsonld b/test_data/metadataE2EV2/metadata-flat.jsonld deleted file mode 100644 index f6da3fac1f..0000000000 --- a/test_data/metadataE2EV2/metadata-flat.jsonld +++ /dev/null @@ -1,389 +0,0 @@ -{ - "@graph": [ - { - "http://ns.dasch.swiss/repository#hasAddress": { - "https://schema.org/postalCode": "40000", - "https://schema.org/streetAddress": "University of Toronto Street", - "@type": "https://schema.org/PostalAddress", - "https://schema.org/addressLocality": "Toronto" - }, - "http://ns.dasch.swiss/repository#hasName": "University of Toronto", - "http://ns.dasch.swiss/repository#hasEmail": { - "@id": "http://ns.dasch.swiss/info@universityoftoronto.ca" - }, - "@type": "http://ns.dasch.swiss/repository#Organization", - "http://ns.dasch.swiss/repository#hasURL": { - "@type": "https://schema.org/URL", - "https://schema.org/url": "http://www.utoronto.ca/" - }, - "@id": "http://ns.dasch.swiss/test-funder" - }, - { - "http://ns.dasch.swiss/repository#hasName": "Prof. test test, Prof. test Harbtestrecht", - "http://ns.dasch.swiss/repository#hasNumber": "0123456789", - "http://ns.dasch.swiss/repository#hasFunder": { - "@id": "http://ns.dasch.swiss/test-funder" - }, - "@type": "http://ns.dasch.swiss/repository#Grant", - "http://ns.dasch.swiss/repository#hasURL": { - "@type": "https://schema.org/URL", - "https://schema.org/url": "http://p3.snf.ch/testproject" - }, - "@id": "http://ns.dasch.swiss/test-grant" - }, - { - "http://ns.dasch.swiss/repository#hasFamilyName": "Berry", - "http://ns.dasch.swiss/repository#hasGivenName": "Lauren", - "http://ns.dasch.swiss/repository#hasAddress": { - "https://schema.org/postalCode": "4000", - "https://schema.org/streetAddress": "Teststrasse", - "@type": "https://schema.org/PostalAddress", - "https://schema.org/addressLocality": "Basel" - }, - "http://ns.dasch.swiss/repository#hasJobTitle": "Dr.", - "http://ns.dasch.swiss/repository#hasRole": "Contributor", - "http://ns.dasch.swiss/repository#hasEmail": { - "@id": "http://ns.dasch.swiss/lauren.berry@unibas.ch" - }, - "@type": "http://ns.dasch.swiss/repository#Person", - "http://ns.dasch.swiss/repository#isMemberOf": { - "@id": "http://ns.dasch.swiss/test-dasch" - }, - "@id": "http://ns.dasch.swiss/test-berry" - }, - { - "http://ns.dasch.swiss/repository#hasAbstract": "Dies ist ein Testprojekt.", - "http://ns.dasch.swiss/repository#hasLanguage": [ - "DE", - "EN", - "FR" - ], - "http://ns.dasch.swiss/repository#hasDateModified": { - "@value": "2020-04-26", - "@type": "http://www.w3.org/2001/XMLSchema#date" - }, - "http://ns.dasch.swiss/repository#hasQualifiedAttribution": [ - { - "@type": "http://www.w3.org/ns/prov#Attribution", - "http://www.w3.org/ns/prov#agent": { - "@id": "http://ns.dasch.swiss/test-jones" - }, - "http://ns.dasch.swiss/repository#hasRole": "editor" - }, - { - "@type": "http://www.w3.org/ns/prov#Attribution", - "http://www.w3.org/ns/prov#agent": { - "@id": "http://ns.dasch.swiss/test-abraham" - }, - "http://ns.dasch.swiss/repository#hasRole": "editor" - }, - { - "@type": "http://www.w3.org/ns/prov#Attribution", - "http://www.w3.org/ns/prov#agent": { - "@id": "http://ns.dasch.swiss/test-berry" - }, - "http://ns.dasch.swiss/repository#hasRole": "contributor" - }, - { - "@type": "http://www.w3.org/ns/prov#Attribution", - "http://www.w3.org/ns/prov#agent": { - "@id": "http://ns.dasch.swiss/test-coleman" - }, - "http://ns.dasch.swiss/repository#hasRole": "editor" - }, - { - "@type": "http://www.w3.org/ns/prov#Attribution", - "http://www.w3.org/ns/prov#agent": { - "@id": "http://ns.dasch.swiss/test-hart" - }, - "http://ns.dasch.swiss/repository#hasRole": "contributor" - } - ], - "http://ns.dasch.swiss/repository#hasStatus": "ongoing", - "@type": "http://ns.dasch.swiss/repository#Dataset", - "http://ns.dasch.swiss/repository#hasDatePublished": { - "@value": "2002-09-24", - "@type": "http://www.w3.org/2001/XMLSchema#date" - }, - "http://ns.dasch.swiss/repository#hasDateCreated": { - "@value": "2001-09-26", - "@type": "http://www.w3.org/2001/XMLSchema#date" - }, - "@id": "http://ns.dasch.swiss/test-dataset", - "http://ns.dasch.swiss/repository#hasDocumentation": "Work in progress", - "http://ns.dasch.swiss/repository#hasAlternativeTitle": "test", - "http://ns.dasch.swiss/repository#hasConditionsOfAccess": "Open Access", - "http://ns.dasch.swiss/repository#hasTypeOfData": [ - "image", - "text" - ], - "http://ns.dasch.swiss/repository#hasTitle": "Testprojekt", - "http://ns.dasch.swiss/repository#isPartOf": { - "@id": "http://ns.dasch.swiss/test-project" - }, - "http://ns.dasch.swiss/repository#hasHowToCite": "Testprojekt (test), 2002, https://test.dasch.swiss", - "http://ns.dasch.swiss/repository#hasLicense": { - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://creativecommons.org/licenses/by/3.0" - }, - "http://ns.dasch.swiss/repository#sameAs": { - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://test.dasch.swiss/" - }, - "http://ns.dasch.swiss/repository#hasDistribution": { - "@type": "https://schema.org/DataDownload", - "https://schema.org/url": "https://test.dasch.swiss" - } - }, - { - "http://ns.dasch.swiss/repository#hasFamilyName": "Jones", - "http://ns.dasch.swiss/repository#hasGivenName": "Benjamin", - "http://ns.dasch.swiss/repository#hasAddress": { - "https://schema.org/postalCode": "4000", - "https://schema.org/streetAddress": "Teststrasse", - "@type": "https://schema.org/PostalAddress", - "https://schema.org/addressLocality": "Basel" - }, - "http://ns.dasch.swiss/repository#hasJobTitle": "Dr. des.", - "http://ns.dasch.swiss/repository#hasRole": "Editor", - "http://ns.dasch.swiss/repository#hasEmail": { - "@id": "http://ns.dasch.swiss/benjamin.jones@test.ch" - }, - "@type": "http://ns.dasch.swiss/repository#Person", - "http://ns.dasch.swiss/repository#isMemberOf": { - "@id": "http://ns.dasch.swiss/test-dasch" - }, - "@id": "http://ns.dasch.swiss/test-jones" - }, - { - "http://ns.dasch.swiss/repository#hasFamilyName": "Coleman", - "http://ns.dasch.swiss/repository#hasGivenName": "James", - "http://ns.dasch.swiss/repository#hasAddress": { - "https://schema.org/postalCode": "4000", - "https://schema.org/streetAddress": "Teststrasse", - "@type": "https://schema.org/PostalAddress", - "https://schema.org/addressLocality": "Basel" - }, - "http://ns.dasch.swiss/repository#hasJobTitle": "Dr. des.", - "http://ns.dasch.swiss/repository#hasRole": "Contributor", - "http://ns.dasch.swiss/repository#hasEmail": { - "@id": "http://ns.dasch.swiss/james.coleman@dasch.swiss" - }, - "@type": "http://ns.dasch.swiss/repository#Person", - "http://ns.dasch.swiss/repository#isMemberOf": { - "@id": "http://ns.dasch.swiss/test-dasch" - }, - "@id": "http://ns.dasch.swiss/test-coleman" - }, - { - "http://ns.dasch.swiss/repository#hasAddress": { - "https://schema.org/postalCode": "4000", - "https://schema.org/streetAddress": "Teststrasse", - "@type": "https://schema.org/PostalAddress", - "https://schema.org/addressLocality": "Basel" - }, - "http://ns.dasch.swiss/repository#hasName": "TEST", - "http://ns.dasch.swiss/repository#hasEmail": { - "@id": "http://ns.dasch.swiss/info@dasch.swiss" - }, - "@type": "http://ns.dasch.swiss/repository#Organization", - "http://ns.dasch.swiss/repository#hasURL": { - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://test.swiss" - }, - "@id": "http://ns.dasch.swiss/test-dasch" - }, - { - "http://ns.dasch.swiss/repository#hasPublication": "testpublication", - "http://ns.dasch.swiss/repository#hasFunder": { - "@id": "http://ns.dasch.swiss/test-funder" - }, - "http://ns.dasch.swiss/repository#hasDiscipline": { - "https://schema.org/propertyID": { - "https://schema.org/propertyID": "SKOS UNESCO Nomenclature", - "@type": "https://schema.org/PropertyValue" - }, - "@type": "https://schema.org/URL", - "https://schema.org/url": "http://skos.um.es/unesco6/11" - }, - "http://ns.dasch.swiss/repository#hasGrant": { - "@id": "http://ns.dasch.swiss/test-grant" - }, - "http://ns.dasch.swiss/repository#hasTemporalCoverage": { - "https://schema.org/propertyID": { - "https://schema.org/propertyID": "Chronontology Dainst", - "@type": "https://schema.org/PropertyValue" - }, - "@type": "https://schema.org/URL", - "https://schema.org/url": "http://chronontology.dainst.org/period/Ef9SyESSafJ1" - }, - "http://ns.dasch.swiss/repository#hasDataManagementPlan": { - "http://ns.dasch.swiss/repository#isAvailable": true, - "http://ns.dasch.swiss/repository#hasURL": { - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://snf.ch" - }, - "@type": "http://ns.dasch.swiss/repository#DataManagementPlan" - }, - "http://ns.dasch.swiss/repository#hasStartDate": { - "@value": "2000-07-26", - "@type": "http://www.w3.org/2001/XMLSchema#date" - }, - "http://ns.dasch.swiss/repository#hasURL": { - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://test.dasch.swiss/" - }, - "@id": "http://ns.dasch.swiss/test-project", - "http://ns.dasch.swiss/repository#hasContactPoint": { - "@id": "http://ns.dasch.swiss/test-abraham" - }, - "http://ns.dasch.swiss/repository#hasShortcode": "0000", - "http://ns.dasch.swiss/repository#hasName": "Testprojektname (test)", - "http://ns.dasch.swiss/repository#hasSpatialCoverage": [ - { - "@type": "https://schema.org/Place", - "https://schema.org/url": { - "https://schema.org/propertyID": { - "https://schema.org/propertyID": "Geonames", - "@type": "https://schema.org/PropertyValue" - }, - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://www.geonames.org/3175395/italian-republic.html" - } - }, - { - "@type": "https://schema.org/Place", - "https://schema.org/url": { - "https://schema.org/propertyID": { - "https://schema.org/propertyID": "Geonames", - "@type": "https://schema.org/PropertyValue" - }, - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://www.geonames.org/6255148/europe.html" - } - }, - { - "@type": "https://schema.org/Place", - "https://schema.org/url": { - "https://schema.org/propertyID": { - "https://schema.org/propertyID": "Geonames", - "@type": "https://schema.org/PropertyValue" - }, - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://www.geonames.org/2921044/federal-republic-of-germany.html" - } - }, - { - "@type": "https://schema.org/Place", - "https://schema.org/url": { - "https://schema.org/propertyID": { - "https://schema.org/propertyID": "Geonames", - "@type": "https://schema.org/PropertyValue" - }, - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://www.geonames.org/6269131/england.html" - } - }, - { - "@type": "https://schema.org/Place", - "https://schema.org/url": { - "https://schema.org/propertyID": { - "https://schema.org/propertyID": "Geonames", - "@type": "https://schema.org/PropertyValue" - }, - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://www.geonames.org/2658434/switzerland.html" - } - }, - { - "@type": "https://schema.org/Place", - "https://schema.org/url": { - "https://schema.org/propertyID": { - "https://schema.org/propertyID": "Geonames", - "@type": "https://schema.org/PropertyValue" - }, - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://www.geonames.org/3017382/republic-of-france.html" - } - }, - { - "@type": "https://schema.org/Place", - "https://schema.org/url": { - "https://schema.org/propertyID": { - "https://schema.org/propertyID": "Geonames", - "@type": "https://schema.org/PropertyValue" - }, - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://www.geonames.org/2017370/russian-federation.html" - } - } - ], - "http://ns.dasch.swiss/repository#hasKeywords": [ - "history of mathematics", - "history of science", - "mathematics", - "science" - ], - "http://ns.dasch.swiss/repository#hasEndDate": { - "@value": "2001-01-26", - "@type": "http://www.w3.org/2001/XMLSchema#date" - }, - "http://ns.dasch.swiss/repository#hasDescription": "Dies ist ein Testprojekt...alle Properties wurden verwendet, um diese zu testen", - "@type": "http://ns.dasch.swiss/repository#Project", - "http://ns.dasch.swiss/repository#hasAlternateName": "test" - }, - { - "http://ns.dasch.swiss/repository#hasFamilyName": "Hart", - "http://ns.dasch.swiss/repository#hasGivenName": "Leonhard", - "http://ns.dasch.swiss/repository#hasAddress": { - "https://schema.org/postalCode": "4000", - "https://schema.org/streetAddress": "Teststrasse", - "@type": "https://schema.org/PostalAddress", - "https://schema.org/addressLocality": "Basel" - }, - "http://ns.dasch.swiss/repository#hasJobTitle": "Prof.", - "http://ns.dasch.swiss/repository#hasRole": "Editor", - "http://ns.dasch.swiss/repository#hasEmail": { - "@id": "http://ns.dasch.swiss/leonhard.hart@test.ch" - }, - "@type": "http://ns.dasch.swiss/repository#Person", - "http://ns.dasch.swiss/repository#isMemberOf": { - "@id": "http://ns.dasch.swiss/test-dasch" - }, - "@id": "http://ns.dasch.swiss/test-hart" - }, - { - "@id": "http://ns.dasch.swiss/test-plan", - "http://ns.dasch.swiss/repository#isAvailable": false, - "http://ns.dasch.swiss/repository#hasURL": { - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://snf.ch" - }, - "@type": "http://ns.dasch.swiss/repository#DataManagementPlan" - }, - { - "http://ns.dasch.swiss/repository#hasFamilyName": "Abraham", - "http://ns.dasch.swiss/repository#hasGivenName": "Stewart", - "http://ns.dasch.swiss/repository#hasAddress": { - "https://schema.org/postalCode": "4000", - "https://schema.org/streetAddress": "Teststrasse", - "@type": "https://schema.org/PostalAddress", - "https://schema.org/addressLocality": "Basel" - }, - "http://ns.dasch.swiss/repository#hasJobTitle": "Dr.", - "http://ns.dasch.swiss/repository#hasRole": "Editor", - "@type": "http://ns.dasch.swiss/repository#Person", - "http://ns.dasch.swiss/repository#isMemberOf": { - "@id": "http://ns.dasch.swiss/test-dasch" - }, - "@id": "http://ns.dasch.swiss/test-abraham", - "http://ns.dasch.swiss/repository#hasEmail": { - "@id": "http://ns.dasch.swiss/stewart.abraham@test.ch" - }, - "http://ns.dasch.swiss/repository#sameAs": { - "@type": "https://schema.org/URL", - "https://schema.org/url": "https://orcid.org/0000-0002-1825-0097" - } - } - ] -} diff --git a/test_data/metadataE2EV2/metadata.ttl b/test_data/metadataE2EV2/metadata.ttl deleted file mode 100644 index 9220b9ceb2..0000000000 --- a/test_data/metadataE2EV2/metadata.ttl +++ /dev/null @@ -1,394 +0,0 @@ - - a ; - - "test" ; - - ; - - [ a ; - - [ a ; - "https://snf.ch" - ] ; - - true - ] ; - - "Dies ist ein Testprojekt...alle Properties wurden verwendet, um diese zu testen" ; - - [ a ; - - [ a ; - - "SKOS UNESCO Nomenclature" - ] ; - "http://skos.um.es/unesco6/11" - ] ; - - "2001-01-26"^^ ; - - ; - - ; - - "mathematics" , "history of science" , "history of mathematics" , "science" ; - - "Testprojektname (test)" ; - - "testpublication" ; - - "0000" ; - - [ a ; - [ a ; - - [ a ; - - "Geonames" - ] ; - "https://www.geonames.org/6255148/europe.html" - ] - ] ; - - [ a ; - [ a ; - - [ a ; - - "Geonames" - ] ; - "https://www.geonames.org/3175395/italian-republic.html" - ] - ] ; - - [ a ; - [ a ; - - [ a ; - - "Geonames" - ] ; - "https://www.geonames.org/3017382/republic-of-france.html" - ] - ] ; - - [ a ; - [ a ; - - [ a ; - - "Geonames" - ] ; - "https://www.geonames.org/2921044/federal-republic-of-germany.html" - ] - ] ; - - [ a ; - [ a ; - - [ a ; - - "Geonames" - ] ; - "https://www.geonames.org/6269131/england.html" - ] - ] ; - - [ a ; - [ a ; - - [ a ; - - "Geonames" - ] ; - "https://www.geonames.org/2658434/switzerland.html" - ] - ] ; - - [ a ; - [ a ; - - [ a ; - - "Geonames" - ] ; - "https://www.geonames.org/2017370/russian-federation.html" - ] - ] ; - - "2000-07-26"^^ ; - - [ a ; - - [ a ; - - "Chronontology Dainst" - ] ; - "http://chronontology.dainst.org/period/Ef9SyESSafJ1" - ] ; - - [ a ; - "https://test.dasch.swiss/" - ] . - - - a ; - - [ a ; - - "Basel" ; - - "4000" ; - - "Teststrasse" - ] ; - - ; - - "Abraham" ; - - "Stewart" ; - - "Dr." ; - - "Editor" ; - - ; - - [ a ; - "https://orcid.org/0000-0002-1825-0097" - ] . - - - a ; - - [ a ; - - "Toronto" ; - - "40000" ; - - "University of Toronto Street" - ] ; - - ; - - "University of Toronto" ; - - [ a ; - "http://www.utoronto.ca/" - ] . - - - a ; - - ; - - "Prof. test test, Prof. test Harbtestrecht" ; - - "0123456789" ; - - [ a ; - "http://p3.snf.ch/testproject" - ] . - - - a ; - - [ a ; - "https://snf.ch" - ] ; - - false . - - - a ; - - [ a ; - - "Basel" ; - - "4000" ; - - "Teststrasse" - ] ; - - ; - - "Coleman" ; - - "James" ; - - "Dr. des." ; - - "Contributor" ; - - . - - - a ; - - [ a ; - - "Basel" ; - - "4000" ; - - "Teststrasse" - ] ; - - ; - - "TEST" ; - - [ a ; - "https://test.swiss" - ] . - - - a ; - - [ a ; - - "Basel" ; - - "4000" ; - - "Teststrasse" - ] ; - - ; - - "Hart" ; - - "Leonhard" ; - - "Prof." ; - - "Editor" ; - - . - - - a ; - - [ a ; - - "Basel" ; - - "4000" ; - - "Teststrasse" - ] ; - - ; - - "Berry" ; - - "Lauren" ; - - "Dr." ; - - "Contributor" ; - - . - - - a ; - - [ a ; - - "Basel" ; - - "4000" ; - - "Teststrasse" - ] ; - - ; - - "Jones" ; - - "Benjamin" ; - - "Dr. des." ; - - "Editor" ; - - . - - - a ; - - "Dies ist ein Testprojekt." ; - - "test" ; - - "Open Access" ; - - "2001-09-26"^^ ; - - "2020-04-26"^^ ; - - "2002-09-24"^^ ; - - [ a ; - "https://test.dasch.swiss" - ] ; - - "Work in progress" ; - - "Testprojekt (test), 2002, https://test.dasch.swiss" ; - - "FR" , "EN" , "DE" ; - - [ a ; - "https://creativecommons.org/licenses/by/3.0" - ] ; - - [ a ; - - "editor" ; - - - ] ; - - [ a ; - - "contributor" ; - - - ] ; - - [ a ; - - "contributor" ; - - - ] ; - - [ a ; - - "editor" ; - - - ] ; - - [ a ; - - "editor" ; - - - ] ; - - "ongoing" ; - - "Testprojekt" ; - - "text" , "image" ; - - ; - - [ a ; - "https://test.dasch.swiss/" - ] . diff --git a/webapi/src/main/scala/org/knora/webapi/app/ApplicationActor.scala b/webapi/src/main/scala/org/knora/webapi/app/ApplicationActor.scala index fda62d3ca4..1ec2feca98 100644 --- a/webapi/src/main/scala/org/knora/webapi/app/ApplicationActor.scala +++ b/webapi/src/main/scala/org/knora/webapi/app/ApplicationActor.scala @@ -444,7 +444,6 @@ class ApplicationActor extends Actor with Stash with LazyLogging with AroundDire new ValuesRouteV2(routeData).knoraApiPath ~ new StandoffRouteV2(routeData).knoraApiPath ~ new ListsRouteV2(routeData).knoraApiPath ~ - new MetadataRouteV2(routeData).knoraApiPath ~ new AuthenticationRouteV2(routeData).knoraApiPath ~ new GroupsRouteADM(routeData).knoraApiPath ~ new ListsRouteADM(routeData).knoraApiPath ~ diff --git a/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala b/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala index 5e860fb5ff..c813bfa58c 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala @@ -2404,15 +2404,6 @@ class StringFormatter private ( def projectDataNamedGraphV2(project: ProjectADM): IRI = OntologyConstants.NamedGraphs.DataNamedGraphStart + "/" + project.shortcode + "/" + project.shortname - /** - * Given the [[ProjectADM]] calculates the project's metadata named graph. - * - * @param project the project's [[ProjectADM]]. - * @return the IRI of the project's metadata named graph. - */ - def projectMetadataNamedGraphV2(project: ProjectADM): IRI = - OntologyConstants.NamedGraphs.DataNamedGraphStart + "/" + project.shortcode + "/" + project.shortname + "/metadata" - /** * Check that the supplied IRI represents a valid project IRI. * diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/metadatamessages/MetadataMessagesV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/metadatamessages/MetadataMessagesV2.scala deleted file mode 100644 index 8656ce0f44..0000000000 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/metadatamessages/MetadataMessagesV2.scala +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.knora.webapi.messages.v2.responder.metadatamessages - -import java.util.UUID - -import org.knora.webapi.IRI -import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} -import org.knora.webapi.feature.FeatureFactoryConfig -import org.knora.webapi.messages.OntologyConstants -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM -import org.knora.webapi.messages.admin.responder.usersmessages.UserADM -import org.knora.webapi.messages.util.rdf.RdfModel -import org.knora.webapi.messages.v2.responder._ - -/** - * An abstract trait for messages that can be sent to `ResourcesResponderV2`. - */ -sealed trait MetadataResponderRequestV2 extends KnoraRequestV2 { - - /** - * The user that made the request. - */ - def requestingUser: UserADM -} - -/** - * Requests metadata about a project. A successful response will be a [[MetadataGetResponseV2]]. - * - * @param projectADM the project for which metadata is requested. - * @param featureFactoryConfig the feature factory configuration. - * @param requestingUser the user making the request. - */ -case class MetadataGetRequestV2( - projectADM: ProjectADM, - featureFactoryConfig: FeatureFactoryConfig, - requestingUser: UserADM -) extends MetadataResponderRequestV2 { - val projectIri: IRI = projectADM.id - - // Ensure that the project isn't the system project or the shared ontologies project. - if ( - projectIri == OntologyConstants.KnoraAdmin.SystemProject || projectIri == OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject - ) { - throw BadRequestException(s"Metadata cannot be requested from project <$projectIri>") - } -} - -/** - * Represents metadata about a project. - * - * @param turtle project metadata in Turtle format. - */ -case class MetadataGetResponseV2(turtle: String) extends KnoraTurtleResponseV2 - -/** - * A request to create or update metadata about a project. If metadata already exists - * for the project, it will be replaced by the metadata in this message. A successful response - * will be a [[SuccessResponseV2]]. - * - * @param rdfModel the project metadata to be stored. - * @param projectADM the project. - * @param featureFactoryConfig the feature factory configuration. - * @param requestingUser the user making the request. - * @param apiRequestID the API request ID. - */ -case class MetadataPutRequestV2( - rdfModel: RdfModel, - projectADM: ProjectADM, - featureFactoryConfig: FeatureFactoryConfig, - requestingUser: UserADM, - apiRequestID: UUID -) extends KnoraRdfModelRequestV2 - with MetadataResponderRequestV2 { - - /** - * The project IRI. - */ - val projectIri: IRI = projectADM.id - - // Check if the requesting user is allowed to create project metadata. - if (!requestingUser.permissions.isSystemAdmin && !requestingUser.permissions.isProjectAdmin(projectIri)) { - // Not a system or project admin, so not allowed. - throw ForbiddenException("Project metadata can only be updated by a system or project admin") - } - - // Ensure that the project isn't the system project or the shared ontologies project. - if ( - projectIri == OntologyConstants.KnoraAdmin.SystemProject || projectIri == OntologyConstants.KnoraAdmin.DefaultSharedOntologiesProject - ) { - throw BadRequestException(s"Metadata cannot be created in project <$projectIri>") - } - - // Don't allow named graphs. - if (rdfModel.getContexts.nonEmpty) { - throw BadRequestException("A project metadata request cannot contain named graphs") - } -} diff --git a/webapi/src/main/scala/org/knora/webapi/responders/ResponderManager.scala b/webapi/src/main/scala/org/knora/webapi/responders/ResponderManager.scala index e7a9207796..0607977a72 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/ResponderManager.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/ResponderManager.scala @@ -26,7 +26,6 @@ import org.knora.webapi.messages.v1.responder.standoffmessages.StandoffResponder import org.knora.webapi.messages.v1.responder.usermessages.UsersResponderRequestV1 import org.knora.webapi.messages.v1.responder.valuemessages.ValuesResponderRequestV1 import org.knora.webapi.messages.v2.responder.listsmessages.ListsResponderRequestV2 -import org.knora.webapi.messages.v2.responder.metadatamessages.MetadataResponderRequestV2 import org.knora.webapi.messages.v2.responder.ontologymessages.OntologiesResponderRequestV2 import org.knora.webapi.messages.v2.responder.resourcemessages.ResourcesResponderRequestV2 import org.knora.webapi.messages.v2.responder.searchmessages.SearchResponderRequestV2 @@ -218,16 +217,6 @@ class ResponderManager(appActor: ActorRef, responderData: ResponderData) extends */ protected val listsResponderV2: ListsResponderV2 = makeDefaultListsResponderV2 - /** - * Constructs the default [[MetadataResponderV2]]. - */ - protected final def makeDefaultMetadataResponderV2: MetadataResponderV2 = new MetadataResponderV2(responderData) - - /** - * Subclasses can override this member to substitute a custom implementation instead of the default metadata responder. - */ - protected val metadataResponderV2: MetadataResponderV2 = makeDefaultMetadataResponderV2 - // // Admin responders // @@ -342,8 +331,6 @@ class ResponderManager(appActor: ActorRef, responderData: ResponderData) extends future2Message(sender(), standoffResponderV2 receive standoffResponderRequestV2, log) case listsResponderRequestV2: ListsResponderRequestV2 => future2Message(sender(), listsResponderV2 receive listsResponderRequestV2, log) - case metadataResponderRequestV2: MetadataResponderRequestV2 => - future2Message(sender(), metadataResponderV2 receive metadataResponderRequestV2, log) // Knora Admin message case groupsResponderRequestADM: GroupsResponderRequestADM => diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/MetadataResponderV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/MetadataResponderV2.scala deleted file mode 100644 index 1a3a5cd325..0000000000 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/MetadataResponderV2.scala +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.knora.webapi.responders.v2 - -import akka.pattern._ -import org.knora.webapi.IRI -import org.knora.webapi.exceptions.AssertionException -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM -import org.knora.webapi.messages.store.triplestoremessages._ -import org.knora.webapi.messages.util.ResponderData -import org.knora.webapi.messages.util.rdf.{RdfFeatureFactory, RdfFormatUtil, RdfModel, Turtle} -import org.knora.webapi.messages.v2.responder.SuccessResponseV2 -import org.knora.webapi.messages.v2.responder.metadatamessages._ -import org.knora.webapi.responders.Responder.handleUnexpectedMessage -import org.knora.webapi.responders.{IriLocker, Responder} - -import scala.concurrent.Future - -/** - * Responds to requests dealing with project metadata. - */ -class MetadataResponderV2(responderData: ResponderData) extends Responder(responderData) { - - /** - * Receives a message of type [[MetadataResponderRequestV2]], and returns an appropriate response message. - */ - def receive(msg: MetadataResponderRequestV2) = msg match { - case getRequest: MetadataGetRequestV2 => getProjectMetadata(projectADM = getRequest.projectADM) - case putRequest: MetadataPutRequestV2 => putProjectMetadata(putRequest) - case other => handleUnexpectedMessage(other, log, this.getClass.getName) - } - - /** - * GET metadata graph of a project. - * - * @param projectADM the project whose metadata is requested. - * @return a [[MetadataGetResponseV2]]. - */ - private def getProjectMetadata(projectADM: ProjectADM): Future[MetadataGetResponseV2] = { - val graphIri: IRI = stringFormatter.projectMetadataNamedGraphV2(projectADM) - - for { - metadataGraph <- (storeManager ? NamedGraphDataRequest(graphIri)).mapTo[NamedGraphDataResponse] - } yield MetadataGetResponseV2(metadataGraph.turtle) - - } - - /** - * PUT metadata graph of a project. Every time a new metdata information is given for a project, it overwrites the - * previous metadata graph. - * - * @param request the request to put the metadata graph into the triplestore. - * @return a [[SuccessResponseV2]]. - */ - private def putProjectMetadata(request: MetadataPutRequestV2): Future[SuccessResponseV2] = { - val metadataGraphIRI: IRI = stringFormatter.projectMetadataNamedGraphV2(request.projectADM) - val graphContent: String = request.toTurtle(request.featureFactoryConfig) - - def makeTaskFuture: Future[SuccessResponseV2] = - for { - // Create the project metadata graph. - _ <- (storeManager ? - InsertGraphDataContentRequest( - graphContent = graphContent, - graphName = metadataGraphIRI - )).mapTo[InsertGraphDataContentResponse] - - // Check if the created metadata graph has the same content as the one in the request. - createdMetadata: MetadataGetResponseV2 <- getProjectMetadata(request.projectADM) - - rdfFormatUtil: RdfFormatUtil = RdfFeatureFactory.getRdfFormatUtil(request.featureFactoryConfig) - - savedModel: RdfModel = rdfFormatUtil.parseToRdfModel( - rdfStr = createdMetadata.turtle, - rdfFormat = Turtle - ) - - _ = if (!savedModel.isIsomorphicWith(request.rdfModel)) { - throw AssertionException("Project metadata was stored, but is not correct. Please report this a bug.") - } - } yield SuccessResponseV2(s"Project metadata was stored for project <${request.projectIri}>.") - - for { - // Create the metadata graph holding an update lock on the graph IRI so that no other client can - // create or update the same graph simultaneously. - taskResult <- IriLocker.runWithIriLock( - request.apiRequestID, - metadataGraphIRI, - () => makeTaskFuture - ) - } yield taskResult - } -} diff --git a/webapi/src/main/scala/org/knora/webapi/routing/v2/MetadataRouteV2.scala b/webapi/src/main/scala/org/knora/webapi/routing/v2/MetadataRouteV2.scala deleted file mode 100644 index 1d14835f32..0000000000 --- a/webapi/src/main/scala/org/knora/webapi/routing/v2/MetadataRouteV2.scala +++ /dev/null @@ -1,121 +0,0 @@ -package org.knora.webapi.routing.v2 - -import java.util.UUID - -import akka.http.scaladsl.server.Directives._ -import akka.http.scaladsl.server.{PathMatcher, Route} -import org.knora.webapi.feature.FeatureFactoryConfig -import org.knora.webapi.messages.util.rdf.RdfModel -import org.knora.webapi.messages.v2.responder.metadatamessages.{MetadataGetRequestV2, MetadataPutRequestV2} -import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilV2} -import org.knora.webapi.{ApiV2Complex, InternalSchema} - -import scala.concurrent.Future - -object MetadataRouteV2 { - val MetadataBasePath: PathMatcher[Unit] = PathMatcher("v2" / "metadata") -} - -/** - * Provides a routing function for API v2 routes that deal with metadata. - */ -class MetadataRouteV2(routeData: KnoraRouteData) extends KnoraRoute(routeData) with Authenticator { - - import MetadataRouteV2._ - - /** - * Returns the route. - */ - override def makeRoute(featureFactoryConfig: FeatureFactoryConfig): Route = - getMetadata(featureFactoryConfig) ~ - setMetadata(featureFactoryConfig) - - /** - * Route to get metadata. - */ - private def getMetadata(featureFactoryConfig: FeatureFactoryConfig): Route = path(MetadataBasePath / Segment) { - projectIri => - get { requestContext => - // Make the request message. - val requestMessageFuture: Future[MetadataGetRequestV2] = for { - requestingUser <- getUserADM( - requestContext = requestContext, - featureFactoryConfig = featureFactoryConfig - ) - - project <- getProjectADM( - projectIri = projectIri, - featureFactoryConfig = featureFactoryConfig, - requestingUser = requestingUser - ) - } yield MetadataGetRequestV2( - projectADM = project, - featureFactoryConfig = featureFactoryConfig, - requestingUser = requestingUser - ) - - // Send it to the responder. - RouteUtilV2.runRdfRouteWithFuture( - requestMessageF = requestMessageFuture, - requestContext = requestContext, - featureFactoryConfig = featureFactoryConfig, - settings = settings, - responderManager = responderManager, - log = log, - targetSchema = InternalSchema, - schemaOptions = RouteUtilV2.getSchemaOptions(requestContext) - ) - } - } - - /** - * Route to set a project's metadata, replacing any existing metadata for the project. - */ - private def setMetadata(featureFactoryConfig: FeatureFactoryConfig): Route = path(MetadataBasePath / Segment) { - projectIri => - put { - entity(as[String]) { entityStr => requestContext => - { - // Parse the request to a Jena Graph. - val requestModel: RdfModel = RouteUtilV2.requestToRdfModel( - entityStr = entityStr, - requestContext = requestContext, - featureFactoryConfig = featureFactoryConfig - ) - - // Make the request message. - val requestMessageFuture: Future[MetadataPutRequestV2] = for { - requestingUser <- getUserADM( - requestContext = requestContext, - featureFactoryConfig = featureFactoryConfig - ) - - project <- getProjectADM( - projectIri = projectIri, - featureFactoryConfig = featureFactoryConfig, - requestingUser = requestingUser - ) - } yield MetadataPutRequestV2( - rdfModel = requestModel, - projectADM = project, - featureFactoryConfig = featureFactoryConfig, - requestingUser = requestingUser, - apiRequestID = UUID.randomUUID - ) - - // Send it to the responder. - RouteUtilV2.runRdfRouteWithFuture( - requestMessageF = requestMessageFuture, - requestContext = requestContext, - featureFactoryConfig = featureFactoryConfig, - settings = settings, - responderManager = responderManager, - log = log, - targetSchema = ApiV2Complex, - schemaOptions = RouteUtilV2.getSchemaOptions(requestContext) - ) - } - } - } - } -} diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/v2/BUILD.bazel b/webapi/src/test/scala/org/knora/webapi/e2e/v2/BUILD.bazel index b17a37911f..8797dbd5cb 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/v2/BUILD.bazel +++ b/webapi/src/test/scala/org/knora/webapi/e2e/v2/BUILD.bazel @@ -209,22 +209,3 @@ scala_test( "@maven//:com_typesafe_play_twirl_api_2_13", ] + BASE_TEST_DEPENDENCIES, ) - -scala_test( - name = "MetadataRouteV2E2ESpec", - size = "small", # 60s - srcs = [ - "MetadataRouteV2E2ESpec.scala", - ], - data = [ - "//knora-ontologies", - "//test_data", - ], - jvm_flags = ["-Dconfig.resource=fuseki.conf"], - # unused_dependency_checker_mode = "warn", - deps = ALL_WEBAPI_MAIN_DEPENDENCIES + [ - "//webapi:main_library", - "//webapi:test_library", - "@maven//:org_apache_jena_apache_jena_libs", - ] + BASE_TEST_DEPENDENCIES_WITH_JSON, -) diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/v2/MetadataRouteV2E2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/v2/MetadataRouteV2E2ESpec.scala deleted file mode 100644 index 461a99b928..0000000000 --- a/webapi/src/test/scala/org/knora/webapi/e2e/v2/MetadataRouteV2E2ESpec.scala +++ /dev/null @@ -1,117 +0,0 @@ -package org.knora.webapi.e2e.v2 - -import java.net.URLEncoder -import java.nio.file.Paths - -import akka.http.scaladsl.model.headers.{BasicHttpCredentials, RawHeader} -import akka.http.scaladsl.model.{HttpEntity, HttpResponse, StatusCodes} -import org.knora.webapi._ -import org.knora.webapi.messages.util.rdf._ -import org.knora.webapi.routing.RouteUtilV2 -import org.knora.webapi.sharedtestdata.SharedTestDataADM -import org.knora.webapi.util.FileUtil - -class MetadataRouteV2E2ESpec extends E2ESpec { - private val rdfModelFactory: RdfModelFactory = RdfFeatureFactory.getRdfModelFactory(defaultFeatureFactoryConfig) - private val rdfFormatUtil: RdfFormatUtil = RdfFeatureFactory.getRdfFormatUtil(defaultFeatureFactoryConfig) - - private val beolUserEmail = SharedTestDataADM.beolUser.email - private val beolProjectIRI: IRI = SharedTestDataADM.BEOL_PROJECT_IRI - private val password = SharedTestDataADM.testPass - - private val metadataAsTurtle: String = FileUtil.readTextFile(Paths.get("test_data/metadataE2EV2/metadata.ttl")) - private val metadataAsFlatJsonLD: String = - FileUtil.readTextFile(Paths.get("test_data/metadataE2EV2/metadata-flat.jsonld")) - - private val expectedRdfModel: RdfModel = rdfFormatUtil.parseToRdfModel( - rdfStr = metadataAsTurtle, - rdfFormat = Turtle - ) - - "The metadata v2 endpoint" should { - "perform a put request for the metadata of beol project given as Turtle" in { - val request = Put( - s"$baseApiUrl/v2/metadata/${URLEncoder.encode(beolProjectIRI, "UTF-8")}", - HttpEntity(RdfMediaTypes.`text/turtle`, metadataAsTurtle) - ) ~> - addCredentials(BasicHttpCredentials(beolUserEmail, password)) - - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status.isSuccess()) - val responseString = responseToString(response) - assert(responseString.contains(s"Project metadata was stored for project <$beolProjectIRI>.")) - } - - "perform a put request for the metadata of beol project given as JSON-LD" in { - val request = Put( - s"$baseApiUrl/v2/metadata/${URLEncoder.encode(beolProjectIRI, "UTF-8")}", - HttpEntity(RdfMediaTypes.`application/json`, metadataAsFlatJsonLD) - ) ~> - addCredentials(BasicHttpCredentials(beolUserEmail, password)) - - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status.isSuccess()) - val responseString = responseToString(response) - assert(responseString.contains(s"Project metadata was stored for project <$beolProjectIRI>.")) - } - - "get the created metadata graph as JSON-LD" in { - val request = Get(s"$baseApiUrl/v2/metadata/${URLEncoder.encode(beolProjectIRI, "UTF-8")}") - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status.isSuccess()) - val responseJSONLD: JsonLDDocument = responseToJsonLDDocument(response) - val responseModel: RdfModel = responseJSONLD.toRdfModel(rdfModelFactory) - assert(responseModel == expectedRdfModel) - } - - "get the created metadata graph as flat JSON-LD" in { - val expectedFlatJsonLDDocument: JsonLDDocument = JsonLDUtil.parseJsonLD(metadataAsFlatJsonLD) - - val request = Get(s"$baseApiUrl/v2/metadata/${URLEncoder.encode(beolProjectIRI, "UTF-8")}") - .addHeader(RawHeader(RouteUtilV2.JSON_LD_RENDERING_HEADER, RouteUtilV2.JSON_LD_RENDERING_FLAT)) - - val response: HttpResponse = singleAwaitingRequest(request) - val responseJSONLD: JsonLDDocument = responseToJsonLDDocument(response) - assert(response.status.isSuccess()) - assert(responseJSONLD == expectedFlatJsonLDDocument) - } - - "get the created metadata graph as Turtle" in { - val turtleType = RdfMediaTypes.`text/turtle`.toString() - val header = RawHeader("Accept", turtleType) - val request = Get(s"$baseApiUrl/v2/metadata/${URLEncoder.encode(beolProjectIRI, "UTF-8")}") ~> addHeader(header) - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status.isSuccess()) - response.entity.contentType.mediaType.value should be(turtleType) - val responseStr = responseToString(response) - val responseModel: RdfModel = parseTurtle(responseStr) - assert(responseModel == expectedRdfModel) - } - - "not return metadata for an invalid project IRI" in { - val request = Get(s"$baseApiUrl/v2/metadata/invalid-projectIRI") - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status.isFailure()) - } - - "not create metadata for an invalid project IRI" in { - val request = - Put(s"$baseApiUrl/v2/metadata/invalid-projectIRI", HttpEntity(RdfMediaTypes.`text/turtle`, metadataAsTurtle)) ~> - addCredentials(BasicHttpCredentials(beolUserEmail, password)) - - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status.isFailure()) - } - - "return HTTP 404 if nonexistent metadata is requested" in { - val turtleType = RdfMediaTypes.`text/turtle`.toString() - val header = RawHeader("Accept", turtleType) - val request = Get( - s"$baseApiUrl/v2/metadata/${URLEncoder.encode(SharedTestDataADM.INCUNABULA_PROJECT_IRI, "UTF-8")}" - ) ~> addHeader(header) - val response: HttpResponse = singleAwaitingRequest(request) - assert(response.status == StatusCodes.NotFound) - } - - } -} diff --git a/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/metadatamessages/BUILD.bazel b/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/metadatamessages/BUILD.bazel deleted file mode 100644 index 217cb21ef7..0000000000 --- a/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/metadatamessages/BUILD.bazel +++ /dev/null @@ -1,22 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("@io_bazel_rules_scala//scala:scala.bzl", "scala_test") -load("//third_party:dependencies.bzl", "ALL_WEBAPI_MAIN_DEPENDENCIES", "BASE_TEST_DEPENDENCIES") - -scala_test( - name = "MetadataMessagesV2Spec", - size = "small", # 60s - srcs = [ - "MetadataMessagesV2Spec.scala", - ], - data = [ - "//knora-ontologies", - "//test_data", - ], - jvm_flags = ["-Dconfig.resource=fuseki.conf"], - # unused_dependency_checker_mode = "warn", - deps = ALL_WEBAPI_MAIN_DEPENDENCIES + [ - "//webapi:main_library", - "//webapi:test_library", - ] + BASE_TEST_DEPENDENCIES, -) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/metadatamessages/MetadataMessagesV2Spec.scala b/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/metadatamessages/MetadataMessagesV2Spec.scala deleted file mode 100644 index fbbb3e1ff0..0000000000 --- a/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/metadatamessages/MetadataMessagesV2Spec.scala +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.knora.webapi.messages.v2.responder.metadatamessages - -import java.util.UUID - -import org.knora.webapi.CoreSpec -import org.knora.webapi.exceptions.ForbiddenException -import org.knora.webapi.messages.util.rdf.{RdfFeatureFactory, RdfFormatUtil, RdfModel, Turtle} -import org.knora.webapi.sharedtestdata.SharedTestDataADM - -/** - * Tests [[MetadataPutRequestV2]]. - */ -class MetadataMessagesV2Spec extends CoreSpec() { - private val rdfFormatUtil: RdfFormatUtil = RdfFeatureFactory.getRdfFormatUtil(defaultFeatureFactoryConfig) - - private val graphDataContent: String = - """ - @prefix dsp-repo: . - @prefix rdf: . - - dsp-repo:anything dsp-repo:hasDescription "A project to test Knora functionalities" . - dsp-repo:anything dsp-repo:hasShortcode "0001" . - """ - - // Parse the request to an RdfModel. - private val requestModel: RdfModel = rdfFormatUtil.parseToRdfModel( - rdfStr = graphDataContent, - rdfFormat = Turtle - ) - - "MetadataPutRequestV2" should { - "return ForbiddenException if the requesting user is not the project admin or a system admin" in { - assertThrows[ForbiddenException]( - MetadataPutRequestV2( - rdfModel = requestModel, - projectADM = SharedTestDataADM.anythingProject, - featureFactoryConfig = defaultFeatureFactoryConfig, - requestingUser = SharedTestDataADM.anythingUser2, - apiRequestID = UUID.randomUUID() - ) - ) - } - } -} diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/BUILD.bazel b/webapi/src/test/scala/org/knora/webapi/responders/v2/BUILD.bazel index 8813d965fc..08c902f17e 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/v2/BUILD.bazel +++ b/webapi/src/test/scala/org/knora/webapi/responders/v2/BUILD.bazel @@ -126,22 +126,3 @@ scala_test( "@maven//:com_typesafe_play_twirl_api_2_13", ] + BASE_TEST_DEPENDENCIES, ) - -scala_test( - name = "MetadataResponderV2Spec", - size = "medium", - srcs = [ - "MetadataResponderV2Spec.scala", - ], - data = [ - "//knora-ontologies", - "//test_data", - ], - jvm_flags = ["-Dconfig.resource=fuseki.conf"], - # unused_dependency_checker_mode = "warn", - deps = ALL_WEBAPI_MAIN_DEPENDENCIES + [ - "//webapi:main_library", - "//webapi:test_library", - "@maven//:org_apache_jena_apache_jena_libs", - ] + BASE_TEST_DEPENDENCIES, -) diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/MetadataResponderV2Spec.scala b/webapi/src/test/scala/org/knora/webapi/responders/v2/MetadataResponderV2Spec.scala deleted file mode 100644 index 4433db056a..0000000000 --- a/webapi/src/test/scala/org/knora/webapi/responders/v2/MetadataResponderV2Spec.scala +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.knora.webapi.responders.v2 - -import java.util.UUID - -import akka.testkit.ImplicitSender -import org.knora.webapi.CoreSpec -import org.knora.webapi.messages.StringFormatter -import org.knora.webapi.messages.util.rdf._ -import org.knora.webapi.messages.v2.responder.SuccessResponseV2 -import org.knora.webapi.messages.v2.responder.metadatamessages._ -import org.knora.webapi.sharedtestdata.SharedTestDataADM - -import scala.concurrent.duration._ - -/** - * Tests [[MetadataResponderV2]]. - */ -class MetadataResponderV2Spec extends CoreSpec() with ImplicitSender { - private implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance - private val rdfFormatUtil: RdfFormatUtil = RdfFeatureFactory.getRdfFormatUtil(defaultFeatureFactoryConfig) - - // The default timeout for receiving reply messages from actors. - private val timeout = 10.seconds - - private val metadataContent = - s"""@base . - |@prefix dsp-repo: . - |@prefix prov: . - |@prefix rdf: . - |@prefix schema: . - |@prefix xsd: . - | - |<082D-dataset-001> a ; - | "Smart technologies transform farming today. Think of autonomous tractors and weeding robots, animals and underground infrastructures with inbuilt sensors, and drones or satellites offering image analysis from the air. There are many opportunities arising from this evolution in terms of increased productivity, profitability, and sustainability. Critical issues, in turn, include techno-dependency, vulnerability and privacy. This project contributes empirical evidence to the discussion of the opportunities and risks associated with smart farming. It starts from the assumption that smart farming – i.e. the management of agricultural practices and processes through techniques of data gathering, transfer and analysis – is never neutral, but shaped by all kinds of decisions and judgements built into the systems from their very elaboration. The project thus studies ‘what lies behind’ novel smart-farming solutions, looking at where, by whom and how they are produced and subsequently diffused as exemplars to follow. It does so through the investigation of two high-profile initiatives in Switzerland: Swiss Future Farm: An experimental and demonstration farm, set up on Agroscope’s test site in Tänikon (TG) as a joint public–private initiative, to be inaugurated on 21 September 2018. AgroFly’s (now with Aero41) sprayer-drone project (Sierre, VS): The first authorized drone system in Europe for the automated application of pesticides. Test sites are distributed in Switzerland and beyond. This project claims that specific initiatives, anchored in specific sites of experimentation, play a fundamental role in assembling the actor networks that carry forward the evolutions around smart farming. Grounded in Actor Network Theory, the project unpacks the chain of mediations through which relevant actors, ideas and things connect and interact in the co-production of the studied initiatives, and investigates the relationships and mechanisms that tie them to each other and to other sites and initiatives. There are four interrelated research objectives that run through this investigation, relating to the collaborative, expertise-related, discursive, and spatial dimensions of learning and exemplification: to analyse the practices of collaboration through which novel smart-farming solutions are developed and stabilized for more normalized use through the studied sites of experimentation. to examine what and how specific forms of expertise become authorized to act in the different stages and chains of mediation associated with the studied sites. to investigate what and how specific discourses, expectations and beliefs surrounding smart technologies crystallize in and emerge from the studied initiatives. to explore the forces and mechanisms through which the studied sites are tied to other places and projects in the circuits of learning and exemplification that shape the field of smart farming. To pursue these objectives, the project follows three methodological pathways: textual analysis of literature and reports, non-participant observation, and semi-structured interviews. This approach is exploratory in ambition and scope and leads to further, follow-up research proposals on Big Data in agriculture. On these grounds, the project studies, informs and debates innovation in the agricultural sector. It highlights the factors that favour or hinder technology innovation, diffusion and adaptation, and fosters greater understanding about the desirability or non-desirability of this. User beneficiaries include farmers and farming associations, technology "^^xsd:string ; - | "Restricted"^^xsd:string ; - | "Klauser FR and Pauschinger D (2020) Big Data in Agriculture: The Making of Smart Farms, SNF Project Data Set."^^xsd:string ; - | "English"^^xsd:string, - | "French"^^xsd:string, - | "German"^^xsd:string ; - | [ a schema:URL ; - | schema:propertyID [ a schema:PropertyValue ; - | schema:propertyID "creativecommons.org" ] ; - | schema:url "https://creativecommons.org/licenses/" ] ; - | [ a prov:Attribution ; - | "Senior Research Fellow"^^xsd:string ; - | prov:agent <082D-person-002> ], - | [ a prov:Attribution ; - | "PI"^^xsd:string ; - | prov:agent <082D-person-001> ] ; - | "Finished"^^xsd:string ; - | "Dataset of Big Data in Agriculture: The Making of Smart Farms"^^xsd:string ; - | "Text"^^xsd:string ; - | <082D-project> . - | - | a ; - | true . - | - |<082D-grant-001> a ; - | <082D-organization-001> ; - | "Digital Lives"^^xsd:string ; - | "FN 10DL1A_183037"^^xsd:string ; - | [ a schema:URL ; - | schema:propertyID [ a schema:PropertyValue ; - | schema:propertyID "snf.ch" ] ; - | schema:url "http://www.snf.ch/de/foerderung/projekte/digital-lives/Seiten/default.aspx" ] . - | - |<082D-person-002> a ; - | [ a schema:PostalAddress ; - | schema:addressLocality "Neuchâtel"^^xsd:string ; - | schema:postalCode "2000"^^xsd:string ; - | schema:streetAddress "Espace Tilo-Frey 1"^^xsd:string ] ; - | "dennis.pauschinger@unine.ch" ; - | "Pauschinger"^^xsd:string ; - | ( "Dennis"^^xsd:string ) ; - | "Postdoc "^^xsd:string ; - | <082D-organization-002> . - | - |<082D-project> a ; - | <082D-person-001> ; - | ; - | \"\"\"Smart technologies transform farming today. Think of autonomous tractors and weeding robots, animals and underground infrastructures with inbuilt sensors, and drones or satellites offering image analysis from the air. There are many opportunities arising from this evolution in terms of increased productivity, profitability, and sustainability. Critical issues, in turn, include techno-dependency, vulnerability and privacy. - |This project contributes empirical evidence to the discussion of the opportunities and risks associated with smart farming. It starts from the assumption that smart farming – i.e. the management of agricultural practices and processes through techniques of data gathering, transfer and analysis – is never neutral, but shaped by all kinds of decisions and judgements built into the systems from their very elaboration. The project thus studies ‘what lies behind’ novel smart-farming solutions, looking at where, by whom and how they are produced and subsequently diffused as exemplars to follow. It does so through the investigation of two high-profile initiatives in Switzerland: - |Swiss Future Farm: An experimental and demonstration farm, set up on Agroscope’s test site in Tänikon (TG) as a joint public–private initiative, to be inaugurated on 21 September 2018. - |AgroFly’s (now with Aero41) sprayer-drone project (Sierre, VS): The first authorized drone system in Europe for the automated application of pesticides. Test sites are distributed in Switzerland and beyond. - |This project claims that specific initiatives, anchored in specific sites of experimentation, play a fundamental role in assembling the actor networks that carry forward the evolutions around smart farming. Grounded in Actor Network Theory, the project unpacks the chain of mediations through which relevant actors, ideas and things connect and interact in the co-production of the studied initiatives, and investigates the relationships and mechanisms that tie them to each other and to other sites and initiatives. There are four interrelated research objectives that run through this investigation, relating to the collaborative, expertise-related, discursive, and spatial dimensions of learning and exemplification: - |to analyse the practices of collaboration through which novel smart-farming solutions are developed and stabilized for more normalized use through the studied sites of experimentation. - |to examine what and how specific forms of expertise become authorized to act in the different stages and chains of mediation associated with the studied sites. - |to investigate what and how specific discourses, expectations and beliefs surrounding smart technologies crystallize in and emerge from the studied initiatives. - |to explore the forces and mechanisms through which the studied sites are tied to other places and projects in the circuits of learning and exemplification that shape the field of smart farming. - |To pursue these objectives, the project follows three methodological pathways: textual analysis of literature and reports, non-participant observation, and semi-structured interviews. This approach is exploratory in ambition and scope and leads to further, follow-up research proposals on Big Data in agriculture. On these grounds, the project studies, informs and debates innovation in the agricultural sector. It highlights the factors that favour or hinder technology innovation, diffusion and adaptation, and fosters greater understanding about the desirability or non-desirability of this. User beneficiaries include farmers and farming associations, technology \"\"\"^^xsd:string ; - | [ a schema:URL ; - | schema:propertyID [ a schema:PropertyValue ; - | schema:propertyID "SKOS UNESCO Nomenclature" ] ; - | schema:url "http://skos.um.es/unesco6/540305" ] ; - | "2020-06-30"^^xsd:date ; - | <082D-organization-001> ; - | <082D-grant-001> ; - | "Agriculture"^^xsd:string ; - | "Big Data in Agriculture: The Making of Smart Famrs"^^xsd:string ; - | "Klauser, FR.: Surveillance Farms: Towards a Research Agenda on Big Data in Agriculture, Surveillance & Society, 16(3), 370-378, https://doi.org/10.24908/ss.v16i3.12594, 2020. "^^xsd:string, - | "Pauschinger, D. and Klauser, F.: Räume des Experimentierens: Die Einführung von Sprühdrohnen in der digitalen Landwirtschaft, Geogr. Helv., 75, 325–336, https://doi.org/10.5194/gh-75-325-2020, 2020. "^^xsd:string ; - | "082D"^^xsd:string ; - | [ a schema:Place ; - | schema:url [ a schema:URL ; - | schema:propertyID [ a schema:PropertyValue ; - | schema:propertyID "Geonames" ; - | schema:url "https://www.geonames.org/2658434/switzerland.html" ] ] ] ; - | "2018-12-01"^^xsd:date ; - | [ a schema:URL ; - | schema:propertyID [ a schema:PropertyValue ; - | schema:propertyID "dainst.org" ] ; - | schema:url "https://chronontology.dainst.org/period/8bGPuf5syqCD" ] ; - | [ a schema:URL ; - | schema:propertyID [ a schema:PropertyValue ; - | schema:propertyID "dasch.swiss" ] ; - | schema:url "https://test.dasch.swiss" ] . - | - |<082D-organization-001> a ; - | "Swiss National Science Foundation"^^xsd:string . - | - |<082D-organization-002> a ; - | [ a schema:PostalAddress ; - | schema:addressLocality "Neuchâtel"^^xsd:string ; - | schema:postalCode "2000"^^xsd:string ; - | schema:streetAddress "Espace Tilo-Frey 1"^^xsd:string ] ; - | "Secretariat.Geographie@unine.ch " ; - | "Université de Neuchâtel, Faculté des lettres et sciences humaines"^^xsd:string ; - | [ a schema:URL ; - | schema:propertyID [ a schema:PropertyValue ; - | schema:propertyID "unine.ch" ] ; - | schema:url "http://www.unine.ch/geographie/home.html" ] . - | - |<082D-person-001> a ; - | [ a schema:PostalAddress ; - | schema:addressLocality "Neuchâtel"^^xsd:string ; - | schema:postalCode "2000"^^xsd:string ; - | schema:streetAddress "Espace Tilo-Frey 1"^^xsd:string ] ; - | "francisco.klauser@unine.ch" ; - | "Klauser"^^xsd:string ; - | ( "Francisco R."^^xsd:string ) ; - | "Full professor of political geography"^^xsd:string ; - | <082D-organization-002> ; - | [ a schema:URL ; - | schema:propertyID [ a schema:PropertyValue ; - | schema:propertyID "orcid.org" ] ; - | schema:url "https://orcid.org/0000-0003-3383-3570." ] . - | - |""".stripMargin - - // Parse the request to an RdfModel. - private val requestModel: RdfModel = rdfFormatUtil.parseToRdfModel( - rdfStr = metadataContent, - rdfFormat = Turtle - ) - - "The metadata responder v2" should { - - "save a metadata graph in the triplestore" in { - responderManager ! MetadataPutRequestV2( - rdfModel = requestModel, - projectADM = SharedTestDataADM.beolProject, - featureFactoryConfig = defaultFeatureFactoryConfig, - requestingUser = SharedTestDataADM.beolUser, - apiRequestID = UUID.randomUUID - ) - - val response = expectMsgType[SuccessResponseV2](timeout) - assert(response.message.contains(s"<${SharedTestDataADM.beolProject.id}>")) - } - - "get the metadata graph of a project" in { - responderManager ! MetadataGetRequestV2( - projectADM = SharedTestDataADM.beolProject, - featureFactoryConfig = defaultFeatureFactoryConfig, - requestingUser = SharedTestDataADM.beolUser - ) - - val response = expectMsgType[MetadataGetResponseV2](timeout) - - val receivedModel: RdfModel = rdfFormatUtil.parseToRdfModel( - rdfStr = response.turtle, - rdfFormat = Turtle - ) - - assert(receivedModel.isIsomorphicWith(requestModel)) - } - } -}