Skip to content

Commit

Permalink
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/metadata.md
@@ -0,0 +1,102 @@
<!---
Copyright © 2015-2019 the contributors (see Contributors.md).
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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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 <http://www.gnu.org/licenses/>.
-->

# 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: <http://ns.dasch.swiss/repository#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@base <http://ns.dasch.swiss/repository#> .
<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:

```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"
}
```
32 changes: 7 additions & 25 deletions docs/05-internals/design/api-v2/json-ld.md
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:

```scala
/**
*
* 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](https://tools.ietf.org/html/rfc7231#section-5.3.2), and converts JSON-LD
responses into [Turtle](https://www.w3.org/TR/turtle/)
or [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/) as appropriate.
[HTTP content negotiation](https://tools.ietf.org/html/rfc7231#section-5.3.2). 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(
"@maven//:com_typesafe_akka_akka_stream_2_12",
"@maven//:com_typesafe_play_twirl_api_2_12",
"@maven//:com_typesafe_scala_logging_scala_logging_2_12",
"@maven//:org_apache_jena_apache_jena_libs",
"@maven//:commons_io_commons_io",
"@maven//:commons_validator_commons_validator",
"@maven//:io_spray_spray_json_2_12",
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,
append(logo).
append(ontologies.toSet).
append(status).
append(selfjoin).hashCode()
append(selfjoin).toHashCode
}
}

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.