glenrobson / SimpleAnnotationServer

A simple IIIF and Mirador compatible Annotation Server

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Resources in Annotations in dynamic AnnotationLists have non-unique blank node identifiers

bencomp opened this issue · comments

When I perform a IIIF Content Search, the Annotations that are returned all share the same blank node ID _:b2 for the resource.

When I request the list of all annotations the other parts of annotations share blank node IDs _:b0, _:b1, _:b3 and _:b4 for all first targets, choice selector, default selector and alternative selector respectively.

"@type" : "sc:AnnotationList",
  "resources" : [ {
    "@id" : "https://iiif.universiteitleiden.nl/anno//annotation/1538394902757",
    "@type" : "oa:Annotation",
    "dcterms:created" : "2018-10-01T13:55:02",
    "resource" : [ {
      "@id" : "_:b2",
      "@type" : "dctypes:Text",
      "http://dev.llgc.org.uk/sas/full_text" : "Nice!",
      "format" : "text/html",
      "chars" : "<p>Nice!</p>"
    } ],
    "on" : [ {
      "@id" : "_:b0",
      "@type" : "oa:SpecificResource",
      "within" : {
        "@id" : "https://purl.stanford.edu/rd447dz7630/iiif/manifest",
        "@type" : "sc:Manifest"
      },
      "selector" : {
        "@id" : "_:b1",
        "@type" : "oa:Choice",
        "default" : {
          "@id" : "_:b3",
          "@type" : "oa:FragmentSelector",
          "value" : "xywh=2092,2778,1028,850"
        },
        "item" : {
          "@id" : "_:b4",
          "@type" : "oa:SvgSelector",
          "value" : "snip"
        }
      },
      "full" : "https://purl.stanford.edu/rd447dz7630/iiif/canvas/rd447dz7630_10"
    } ],
    "motivation" : [ "oa:commenting" ],
    "@context" : "http://iiif.io/api/presentation/2/context.json"
  }, {
    "@id" : "https://iiif.universiteitleiden.nl/anno/annotation/1539265909096",
    "@type" : "oa:Annotation",
    "dcterms:created" : "2018-10-11T15:51:49",
    "dcterms:modified" : "2018-10-12T16:23:42",
    "resource" : [ {
      "@id" : "_:b2",
      "@type" : "dctypes:Text",
      "http://dev.llgc.org.uk/sas/full_text" : "snip",
      "format" : "text/html",
      "chars" : "snip"
    } ],
    "on" : [ {
      "@id" : "_:b0",
      "@type" : "oa:SpecificResource",
      "within" : {
        "@id" : "https://iiif.universiteitleiden.nl/manifests/external/louvre/e-7852.json",
        "@type" : "sc:Manifest"
      },
      "selector" : {
        "@id" : "_:b1",
        "@type" : "oa:Choice",
        "default" : {
          "@id" : "_:b3",
          "@type" : "oa:FragmentSelector",
          "value" : "xywh=1557,446,627,144"
        },
        "item" : {
          "@id" : "_:b4",
          "@type" : "oa:SvgSelector",
          "value" : "snip"
        }
      },
      "full" : "https://iiif.universiteitleiden.nl/manifests/external/louvre/e-7852/canvas/p1"
    } ],
    "motivation" : [ "oa:commenting" ],
    "@context" : "http://iiif.io/api/presentation/2/context.json"
  },
...

I guess that it doesn't really matter for applications treating annotations as JSON objects, but RDF tools like the OpenLink Structured Data Sniffer see the data in a completely different way.

Can these @ids be made unique in the context of the annotation list/search result?

Ah thats a good point. As the annotations are separate graphs in Jena they are unique within the graph but when combined are no longer unique. As an alternative to making them unique, would it cause you a problem if I removed any blank nodes before generating the annotation list?

No, it wouldn't :) that sounds perfect.

It looks like I found a solution to remove (or at least suppress) blank node identifiers from the JSON-LD: when generating JSON-LD from the RDF models, in AnnotationUtils.frame(), you can set an additional option to prune the blank node identifiers.

tOptions.setPruneBlankNodeIdentifiers(true);

This does not deal with annotations having blank nodes internally or properly working with blank nodes in different annotations, but it prevents the problem of non-unique blank node identifiers appearing in the JSON-LD output.

I will open a PR.