TheScienceMuseum / collectionsonline

Science Museum Group Collection Online
https://collection.sciencemuseumgroup.org.uk
MIT License
46 stars 3 forks source link

Create RDF view #887

Closed jamieu closed 9 months ago

jamieu commented 7 years ago

Create 'RDF' view for objects/people/docs based on Content Negotiation (as per JSON).

Accept: application/rdf+xml

RDF view only needs to be very basic to start as long as we have access to the underlying JS object/JSON to add more fields/predicates later.

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <rdf:Description rdf:about="http://collection.sciencemuseum.org.uk/objects/co8405056">
  </rdf:Description>
</rdf:RDF>
Cleop commented 7 years ago

4 hour time estimate for initial set up only, to be continued by @jamieu

jamieu commented 6 years ago

This issue is (now) related more to handling multiple XML and JSON serialisations via their own routes, regardless of Accept-Header (or how to make the Accept-Header work for multiple JSON serialisations).

The issue is want to support IIIF which is serialised as JSON-LD and also the BBC's RES format which is serialised as RDF/Turtle.

Because we are already using JSON for our own 'base' API format, we can't rely solely on the Accepts-Header to tell the application which JSON format/serialisation to return.

It's fine for us to continue to use the Accepts-Header to return our JSON API format. But we need more granularity when presenting specific JSON or XML formats/serialisations. Even if we could rely on the more esoteric extensions to the Accepts-Headers (ie. rdf+xml) it's possible safer to prefix these formats on their own routes ie. /iiif/ and /res/.

Although need to investigate if that will cause issues re. correctly supporting linked-data URIs. The W3 spec seems to suggest that you should stick to Content Negotiation (header or file extension) https://www.w3.org/TR/cooluris/ but if we do that I am not sure how we deal with different JSON serialisations for example.

These are the two key formats we want to supoort in the short term.

res_data_guide.pdf

It would also be good to refactor the getValue() functions, so that the can be used by any view (HTML, JSON, RES, IIIF etc.)

jamieu commented 6 years ago

BBC RES (in RDF Turtle) format

https://bbcarchdev.github.io/inside-acropolis/#res-intro

(or optional RDF/XML)

@base <http://ialm.int/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix bibo: <http://purl.org/ontology/bibo/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

</books/9781899066100#id>
    a bibo:Book ;
    dct:title "Acronyms and Synonyms in Medical Imaging"@en ;
    dct:issued "1997"^^xsd:gYear ;
    dct:creator _:allison, _:strickland ;
    dct:publisher [
        a foaf:Organization ;
        foaf:name "CRC Press"
    ] .

_:strickland
    a foaf:Person ;
    foaf:name "Nicola Strickland" .

_:allison
    a foaf:Person ;
    foaf:name "David J. Allison" .

IIIF (in JSON-LD) format

http://iiif.io/api/presentation/2.1/#manifest http://iiif.io/api/presentation/2.1/#sequence http://iiif.io/api/presentation/2.1/#canvas

{
  // Metadata about this manifest file
  "@context": "http://iiif.io/api/presentation/2/context.json",
  "@id": "http://example.org/iiif/book1/manifest",
  "@type": "sc:Manifest",

  // Descriptive metadata about the object/work
  "label": "Book 1",
  "metadata": [
    {"label": "Author", "value": "Anne Author"},
    {"label": "Published", "value": [
        {"@value": "Paris, circa 1400", "@language": "en"},
        {"@value": "Paris, environ 1400", "@language": "fr"}
      ]
    },
    {"label": "Notes", "value": ["Text of note 1", "Text of note 2"]},
    {"label": "Source",
     "value": "<span>From: <a href=\"http://example.org/db/1.html\">Some Collection</a></span>"}
  ],
  "description": "A longer description of this example book. It should give some real information.",
  "thumbnail": {
    "@id": "http://example.org/images/book1-page1/full/80,100/0/default.jpg",
    "service": {
      "@context": "http://iiif.io/api/image/2/context.json",
      "@id": "http://example.org/images/book1-page1",
      "profile": "http://iiif.io/api/image/2/level1.json"
    }
  },

  // Presentation Information
  "viewingDirection": "right-to-left",
  "viewingHint": "paged",
  "navDate": "1856-01-01T00:00:00Z",

  // Rights Information
  "license": "http://rightsstatements.org/vocab/NoC-NC/1.0/",
  "attribution": "Provided by Example Organization",

  "logo": {
    "@id": "http://example.org/logos/institution1.jpg",
    "service": {
        "@context": "http://iiif.io/api/image/2/context.json",
        "@id": "http://example.org/service/inst1",
        "profile": "http://iiif.io/api/image/2/level2.json"
    }
  },

  // Links
  "related":{
    "@id": "http://example.org/videos/video-book1.mpg",
    "format": "video/mpeg"
  },
  "service": {
    "@context": "http://example.org/ns/jsonld/context.json",
    "@id": "http://example.org/service/example",
    "profile": "http://example.org/docs/example-service.html"
  },
  "seeAlso": {
    "@id": "http://example.org/library/catalog/book1.xml",
    "format": "text/xml",
    "profile": "http://example.org/profiles/bibliographic"
  },
  "rendering": {
    "@id": "http://example.org/iiif/book1.pdf",
    "label": "Download as PDF",
    "format": "application/pdf"
  },
  "within": "http://example.org/collections/books/",

  // List of sequences
  "sequences": [
      {
        "@id": "http://example.org/iiif/book1/sequence/normal",
        "@type": "sc:Sequence",
        "label": "Current Page Order"
        // sequence's page order should be included here, see below...
      }
      // Any additional sequences can be referenced here...
  ]
}
{
  // Metadata about this sequence
  "@context": "http://iiif.io/api/presentation/2/context.json",
  "@id": "http://example.org/iiif/book1/sequence/normal",
  "@type": "sc:Sequence",
  "label": "Current Page Order",

  "viewingDirection": "left-to-right",
  "viewingHint": "paged",
  "startCanvas": "http://example.org/iiif/book1/canvas/p2",

  // The order of the canvases
  "canvases": [
    {
      "@id": "http://example.org/iiif/book1/canvas/p1",
      "@type": "sc:Canvas",
      "label": "p. 1"
      // ...
    },
    {
      "@id": "http://example.org/iiif/book1/canvas/p2",
      "@type": "sc:Canvas",
      "label": "p. 2"
      // ...
    },
    {
      "@id": "http://example.org/iiif/book1/canvas/p3",
      "@type": "sc:Canvas",
      "label": "p. 3"
      // ...
    }
  ]
}
{
  // Metadata about this canvas
  "@context": "http://iiif.io/api/presentation/2/context.json",
  "@id": "http://example.org/iiif/book1/canvas/p1",
  "@type": "sc:Canvas",
  "label": "p. 1",
  "height": 1000,
  "width": 750,
  "thumbnail" : {
    "@id" : "http://example.org/iiif/book1/canvas/p1/thumb.jpg",
    "@type": "dctypes:Image",
    "height": 200,
    "width": 150
  },
  "images": [
    {
      "@type": "oa:Annotation"
      // Link from Image to canvas should be included here, as below
    }
  ],
  "otherContent": [
    {
      // Reference to list of other Content resources, _not included directly_
      "@id": "http://example.org/iiif/book1/list/p1",
      "@type": "sc:AnnotationList"
    }
  ]
}