Some use cases require a role to be associated with a body or target resource, for example distinguishing between a body that's a comment or justification for a second body which is an edit to be made to the target resource. The distinction between tagging a resource, either with a string or a URI, and describing it is also a common pattern for a single annotation. The Web Annotation Data Model [[annotation-model]] can currently only support the inference of a single role from the Motivation associated with the Annotation, or from the specific structures added to accomodate tagging. This proposal takes the results of discussion within the Working Group and lays out concrete options, based on general consensus from the weekly teleconferences.
The following are the requirements and desiderata for the change to the model.
The model ...
id and type instead of @id and @type in JSON-LD to make javascript dot notation viableThe following summarizes the changes proposed to fulfill the above requirements, with examples and further description below.
oa:hasRole, with a JSON-LD mapping of role, and associated with instances of SpecificResourceoa:text to replace rdf:value when used with EmbeddedContent, with a JSON-LD mapping of textTag and SemanticTag classes in favor of SpecificResource with rolescontent as the key in the JSON-LD for the relationship between the SpecificResource and the full resource (currently source)
SpecificResource for annotation bodies
oa:hasSource to oa:hasContentoa:motivatedBy completelyhasRole on EmbeddedContent for bodies, with a new subclassEmbeddedContent and SpecificResource, either in the model or the JSON-LD context (suggestions reqeusted)Options that were considered and discarded from consideration include:
SpecificResourceoa:hasBody, because the extensibility with graceful degradation is impossible without RDF inferencing (to know that edit:hasReplacement is a sub property of oa:hasBody)
The SpecificResource construction allows annotation specific information about a resource (either body or target) to be added in a single, consistent location. As this construction already exists, and role is an annotation specific feature, it is appropriate to associate oa:hasRole with the SpecificResource. This allows the same resource to have different roles in different annotations, for example a page used as a semantic tag and as a comment.
The examples below demonstrate the use of oa:text as a replacement for rdf:value when used with EmbeddedContent. This makes the type of body clearer without an explicit type, plus rdf:value is a bit of a stretch in terms of semantics. Other names for the predicate are possible and can be discussed once the pattern is established. They also demonstrate the use of content as the mapping for oa:hasSource, but does not rename it in the ontology.
The newly OPTIONAL types are omitted from the examples below to demonstrate that their inclusion is unnecessary. The examples demonstrate the removal of Tag and SemanticTag classes, as they would be redundant with the role of tagging.
Associating the commenting role with a body that has a URI.
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"id": "http://example.org/target1"},
"body": {
"role": "commenting",
"content": "http://example.org/body1"
}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget <http://example.org/target1> ;
oa:hasBody [
oa:hasRole oa:commenting ;
oa:hasSource <http://example.org/body1>
]
Associating the commenting role with textual content carried in the annotation.
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"id": "http://example.org/target1"},
"body": {
"role": "commenting",
"content": {"text": "I love this thing"}
}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget <http://example.org/target1> ;
oa:hasBody [
oa:hasRole oa:commenting ;
oa:hasSource [ oa:text "I love this thing" ]
]
Associating the tagging role with textual content carried in the annotation.
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"id": "http://example.org/target1"},
"body": {
"role": "tagging",
"content": {"text": "tag"}
}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget <http://example.org/target1> ;
oa:hasBody [
oa:hasRole oa:tagging ;
oa:hasSource [ oa:text "tag" ]
]
Associating the tagging role with each of multiple tags in the same annotation.
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"id": "http://example.org/target1"},
"body": [
{
"role": "tagging",
"content": {"text": "tag"}
},
{
"role": "tagging",
"content": {"text": "another"}
}
]
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget <http://example.org/target1> ;
oa:hasBody [
oa:hasRole oa:tagging ;
oa:hasSource [ oa:text "tag" ]
], [
oa:hasRole oa:tagging ;
oa:hasSource [ oa:text "another" ]
]
Associating the tagging role with a URI, often called a semantic tag as it avoids the ambiguity of plain text strings.
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"id": "http://example.org/target1"},
"body": {
"role": "tagging",
"content": "http://example.org/tag1"
}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget <http://example.org/target1> ;
oa:hasBody [
oa:hasRole oa:tagging ;
oa:hasSource <http://example.org/tag1>
]
An annotation with multiple bodies with different roles. It associates a URI as a tag, and some textual content as a comment, with the same target resource
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"id": "http://example.org/target1"},
"body": [{
"role": "tagging",
"content": "http://example.org/tag1"
},
{
"role": "commenting",
"content": {
"text": "I love this thing",
"format": "text/html",
"language": "en"
}
}
]
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget <http://example.org/target1> ;
oa:hasBody [
oa:hasRole oa:tagging ;
oa:hasSource <http://example.org/tag1>
],
[
oa:hasRole oa:commenting ;
oa:hasSource [
oa:text "I love this thing" ;
dc:format "text/html" ;
dc:language "en"
]
]
An annotation with multiple bodies with different roles. It associates a comment and an edit with a specific segment of a resource.
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {
"selector": {
"type": "TextQuoteSelector",
"prefix": "This is before a ",
"exact": "misteak",
"suffix": " and this is after it."
},
"content": {"id": "http://example.com/target.html"}
},
"body": [
{
"role": "commenting",
"content": {
"text": "There is a <b>typo</b> here, it should be 'mistake'.",
"format": "text/html",
"language": "en"
}
},
{
"role": "editing",
"content": {
"text": "mistake",
"format": "text/plain",
"language": "en"
}
}
]
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget [
oa:hasSelector [
a oa:TextQuoteSelector ;
oa:prefix "This is before a " ;
oa:exact "misteak" ;
oa:suffix " and this is after it."
]
];
oa:hasBody [
oa:hasRole oa:commenting ;
oa:hasSource [
oa:text "There is a <b>typo</b> here, it should be 'mistake'." ;
dc:format "text/html" ;
dc:language "en"
]
],
[
oa:hasRole oa:editing ;
oa:hasSource [
oa:text "mistake" ;
dc:format "text/plain" ;
dc:language "en"
]
]
A simple highlight is the role of the target in the annotation. The annotation is highlighting the target. There may be no body at all in this case.
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {
"role": "highlighting",
"content": "http://example.org/book1#para1"
}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget [
oa:hasRole oa:highlighting ;
oa:hasSource ]
A hypothetical example of the use of roles with targets, rather than bodies. This annotation has a single comment about two distinct paragraphs in a text, and the role of each in the annotation is different: one is being compared to the other and it matters which is which. A hypothetical literature set of motivations is used to demonstrate the extensibility of the framework.
{
"@context": ["http://www.w3.org/ns/anno.jsonld", "http://example.org/lit/context.json"],
"id": "http://example.org/anno1",
"type": "Annotation",
"body": {
"role": "lit:comparing",
"content": { "text": "The first passage is a clear derivative of the second" }
},
"target": [{
"role": "lit:antecedent",
"content": "http://example.org/book1#para1"
},
{
"role": "lit:subsequent",
"content": "http://example.org/book1#para6"
}
]
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasBody [
oa:hasRole lit:comparing ;
oa:hasSource [ oa:text "The first passage is a clear derivative of the second" ] ;
oa:hasTarget [
oa:hasRole lit:antedent ;
oa:hasSelector [
a oa:FragmentSelector ;
rdf:value "para1" ] ;
oa:hasSource ],
[
oa:hasRole lit:subsequent ;
oa:hasSelector [
a oa:FragmentSelector ;
rdf:value "para6" ] ;
oa:hasSource ]
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"id": "http://example.com/target1"},
"body": {
"role": "commenting",
"content": {
"type": "Choice",
"members": [
"http://example.org/comment-en",
"http://example.org/comment-fr"
]
}
}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget ;
oa:hasBody [
oa:hasRole oa:commenting ;
oa:hasSource [
a oa:Choice ;
oa:members (
<http://example.org/comment-en>
<http://example.org/comment-fr>
)
]
]
A further proposal was to make the use of SpecificResource required for body when it was not a plain literal. Thus, there would be only two cases to deal with in JSON: the body is a string and treated as a plain text comment; the body is an object, which is a SpecificResource and may have either an EmbeddedContent or external resource as its source/content.
This change would make the following illegal:
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"id": "http://example.org/target1"},
"body": {"id": "http://example.org/tag1"}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget <http://example.org/target1> ;
oa:hasBody <http://example.org/tag1> .
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"id": "http://example.org/target1"},
"body": {"content": "http://example.org/tag1"}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget <http://example.org/target1> ;
oa:hasBody [ oa:hasSource <http://example.org/tag1> ]
If the Body MUST be a SpecificResource (or literal) and the argument in favor of this is that it's more consistent to always use the same pattern, then as targets may also be SpecificResources, the implication is that targets MUST be SpecificResources too. The use of selectors and states are more common with Targets than bodies, however roles would be significantly less common.
This change would make the following illegal:
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"id": "http://example.org/target1"},
"body": {"id": "http://example.org/tag1"}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget <http://example.org/target1> ;
oa:hasBody <http://example.org/tag1> .
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"content": "http://example.org/target1"},
"body": {"content": "http://example.org/tag1"}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget [ oa:hasSource <http://example.org/target1> ] ;
oa:hasBody [ oa:hasSource <http://example.org/tag1> ]
An extended proposal would also allow hasRole to be included directly on an embedded textual body. This proposal is incompatible with the proposals to require SpecificResource for Body, Target, or both. Given the proposal to remove unnecessary types, this also makes the determination of the class of the body more difficult as there are multiple similar options.
At the ontology level, there would be a subClass of EmbeddedContent (which is used for embedding stylesheets, SVG content and potentially further representations) that would be used explicitly for this purpose. That class is not represented in the examples below, as it would not appear in the serialization.
Along with the SpecificResource construction needed for when the body has a URI, the proposal would also allow the following as a valid construction:
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"content": "http://example.org/target1"},
"body": {
"role": "commenting",
"text": "I love this"
}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget [ oa:hasSource <http://example.org/target1> ] ;
oa:hasBody [
oa:hasRole oa:commenting ;
oa:text "I love this"
]
Source is a somewhat arcane name and has no real relationship to the web architecture or anything else. If content is more intuitive as a key in JSON, then oa:hasContent would be more intuitive as a predicate in the ontology.
This change would make the following illegal. Note that it only affects the Turtle serialization:
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget [ oa:hasSource <http://example.org/target1> ] ;
oa:hasBody [ oa:hasSource <http://example.org/tag1> ]
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget [ oa:hasContent <http://example.org/target1> ] ;
oa:hasBody [ oa:hasContent <http://example.org/tag1> ]
Once per-body roles are taken up, especially if SpecificResource is required, then the motivation on the Annotation is only minimally useful in the model. It becomes a hint as to the purpose of the annotation as a whole, which clients are unlikely to know a priori, nor be able to have the user specify it as they would then need to understand the available motivations. Clients would be unlikely to take any action based on the annotation's motivation, and developers might be confused by differing motivations and roles.
Instead, with the ability to have a role on the target, the top contenders for annotation level motivations (bookmarking and highlighting, as they might have no body at all), would be roles on the Target SpecificResource, as above.
This change would make the following illegal:
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"motivation": "commenting",
"target": {"id": "http://example.org/target1"},
"body": {
"content": {"text": "I love this"}
}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasMotivation oa:commenting ;
oa:hasTarget <http://example.org/target1> ;
oa:hasBody [
oa:hasSource [ oa:text "I love this" ]
]
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"content": "http://example.org/target1"},
"body": {
"role": "commenting",
"content": {"text": "I love this"}
}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget [ oa:hasSource <http://example.org/target1> ] ;
oa:hasBody [
oa:hasRole oa:commenting ;
oa:hasSource [ oa:text "I love this" ]
]
Instead of using the role nomenclature, we could stick with using motivatedBy for Specific Resources rather than on the Annotation.
This would change the above examples to look like:
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/anno1",
"type": "Annotation",
"target": {"content": "http://example.org/target1"},
"body": {
"motivation": "commenting",
"content": {"text": "I love this"}
}
}
<http://example.org/anno1> a oa:Annotation ;
oa:hasTarget [ oa:hasSource <http://example.org/target1> ] ;
oa:hasBody [
oa:motivatedBy oa:commenting ;
oa:hasSource [ oa:text "I love this" ]
]