Skip to content


Browse files Browse the repository at this point in the history
feat(api-v2): Add metadata routes (DSP-662) (#1734)
  • Loading branch information
Benjamin Geer committed Oct 26, 2020
1 parent 9bd749d commit bf48968
Show file tree
Hide file tree
Showing 46 changed files with 2,544 additions and 726 deletions.
102 changes: 102 additions & 0 deletions docs/03-apis/api-v2/
@@ -0,0 +1,102 @@
Copyright © 2015-2019 the contributors (see
This file is part of Knora.
Knora is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Knora is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public
License along with Knora. If not, see <>.

# 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]( data model. Metadata information must be available for
any [DaSCH]( 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](

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:

@prefix dsp-repo: <> .
@prefix rdf: <> .
@base <> .
<beol> rdf:type dsp-repo:Project .
<beol> dsp-repo:hasName "Bernoulli-Euler Online (BEOL)" .
<beol> dsp-repo:hasKeywords "mathematics" .
<beol> dsp-repo:hasKeywords "science" .
<beol> dsp-repo:hasKeywords "history of science" .
<beol> dsp-repo:hasKeywords "history of mathematics" .
<beol> dsp-repo:hasCategories "mathematics" .
<beol> dsp-repo:hasStartDate "2016.07" .
<beol> dsp-repo:hasEndDate "2020.01" .
<beol> 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:

"": "Bernoulli-Euler Online (BEOL)",
"": "Schweizerischer Nationalfonds (SNSF)",
"": [
"history of science",
"history of mathematics"
"": "2020.01",
"": "mathematics",
"@type": "",
"": "2016.07",
"@id": ""
32 changes: 7 additions & 25 deletions docs/05-internals/design/api-v2/
Expand Up @@ -129,28 +129,8 @@ otherwise `None`.
## Returning a JSON-LD Response

Each API response is represented by a message class that extends
`KnoraResponseV2`, which has a method `toJsonLDDocument` that specifies
the target ontology schema:

* A trait for Knora API V2 response messages. Any response can be converted into JSON-LD.
trait KnoraResponseV2 {

* Converts the response to a data structure that can be used to generate JSON-LD.
* @param targetSchema the Knora API schema to be used in the JSON-LD document.
* @return a [[JsonLDDocument]] representing the response.
def toJsonLDDocument(targetSchema: ApiV2Schema, settings: KnoraSettingsImpl, schemaOptions: Set[SchemaOption]): JsonLDDocument

The implementation of this method constructs a `JsonLDDocument`,
`KnoraJsonLDResponseV2`, which has a method `toJsonLDDocument` that specifies
the target ontology schema. The implementation of this method constructs a `JsonLDDocument`,
in which all object keys are full IRIs (no prefixes are used), but in which
the JSON-LD context also specifies the prefixes that will be used when the
document is returned to the client. The function `JsonLDUtil.makeContext`
Expand Down Expand Up @@ -239,6 +219,8 @@ RouteUtilV2.runRdfRouteWithFuture(
## Generating Other RDF Formats

`RouteUtilV2.runRdfRouteWithFuture` implements
[HTTP content negotiation](, and converts JSON-LD
responses into [Turtle](
or [RDF/XML]( as appropriate.
[HTTP content negotiation]( After
determining the client's preferred format, it asks the `KnoraResponseV2` to convert
itself into that format. `KnoraResponseV2` has an abstract `format` method, whose implementations
select the most efficient conversion between the response message's internal
representation (which could be JSON-LD or Turtle) and the requested format.
Expand Up @@ -419,6 +419,7 @@ 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 ~
Expand Down
Expand Up @@ -171,6 +171,13 @@ case class GravsearchException(message: String) extends RequestRejectedException
case class InvalidJsonLDException(msg: String, cause: Throwable = null) extends RequestRejectedException(msg, cause)

* An exception indication that the RDF submitted to the API v2 was invalid.
* @param msg a description of the error.
* @param cause the cause for the error
case class InvalidRdfException(msg: String, cause: Throwable = null) extends RequestRejectedException(msg, cause)

* An abstract class for exceptions indicating that something went wrong and it's not the client's fault.
Expand Down
Expand Up @@ -26,6 +26,7 @@ scala_library(
Expand Down
Expand Up @@ -2417,6 +2417,16 @@ class StringFormatter private(val maybeSettings: Option[KnoraSettingsImpl] = Non
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"

* Given the project IRI, checks if it is in a valid format.
Expand Down
Expand Up @@ -420,7 +420,7 @@ case class ProjectADM(id: IRI,

Expand Down
Expand Up @@ -270,7 +270,20 @@ case class SparqlExtendedConstructResponse(statements: Map[SubjectV2, SparqlExte
* @param graphIri the IRI of the named graph.
* @param outputFile the destination file.
case class GraphFileRequest(graphIri: IRI, outputFile: File) extends TriplestoreRequest
case class NamedGraphFileRequest(graphIri: IRI, outputFile: File) extends TriplestoreRequest

* Requests a named graph, which will be returned as Turtle. A successful response
* will be a [[NamedGraphDataResponse]].
* @param graphIri the IRI of the named graph.
case class NamedGraphDataRequest(graphIri: IRI) extends TriplestoreRequest

* A graph of triples in Turtle format.
case class NamedGraphDataResponse(turtle: String)

* Represents a SPARQL Update operation to be performed.
Expand All @@ -284,7 +297,6 @@ case class SparqlUpdateRequest(sparql: String) extends TriplestoreRequest
case class SparqlUpdateResponse()

* Represents a SPARQL ASK query to be sent to the triplestore. A successful response will be a
* [[SparqlAskResponse]].
Expand Down Expand Up @@ -336,6 +348,19 @@ case class InsertRepositoryContent(rdfDataObjects: Seq[RdfDataObject]) extends T
case class InsertTriplestoreContentACK()

* Inserts raw RDF data into the repository.
* @param graphContent contains graph data as turtle.
* @param graphName the name of the graph.
case class InsertGraphDataContentRequest(graphContent: String, graphName: String) extends TriplestoreRequest

* Sent as a response to [[InsertGraphDataContentRequest]] if the request was processed successfully.
case class InsertGraphDataContentResponse()

* Initialize the repository. This will initiate the (re)creation of the repository and adding data to it.
Expand Down

0 comments on commit bf48968

Please sign in to comment.