翻译者:Yaming Fu
原文链接:https://iiif.io/api/discovery/1.0/

image.png

此文档状态

此版本:1.0.0
最新稳定版本1.0.0
上一版本0.9.2

编辑
Michael Appleby IIIF 发现 API 1.0 - 图2, 耶鲁大学
Tom Crane IIIF 发现 API 1.0 - 图3, Digirati
Robert Sanderson IIIF 发现 API 1.0 - 图4, 耶鲁大学
Jon Stroop IIIF 发现 API 1.0 - 图5, 普林斯顿大学图书馆
Simeon Warner IIIF 发现 API 1.0 - 图6, 康奈尔大学
版权所有 © 2012-2021 编辑和贡献者。由 IIIF 联盟根据 CC-BY 许可发布,请参阅免责声明

目录

  1. 简介

1.1.目标和范围
1.2.术语

  1. IIIF 资源发现概述

2.1. IIIF 资源及其变化
2.1.1.级别 0:资源引用
2.1.2.级别 1:资源更改
2.1.3.级别 2:资源创建、更改、删除和移动
2.1.4.聚合活动
2.1.5.状态刷新活动
2.2.更改页面
2.3.页面集合
2.4.收藏登记处

  1. 活动流详情

3.1.有序集合
3.2.有序集合页面
3.3.活动
3.4.关联数据上下文和扩展
3.4.1. @上下文
3.4.2.扩展
3.5.活动流处理算法
3.5.1.收集算法
3.5.2.页面算法
3.5.3.资源处理:索引
3.5.4.处理多个流

  1. 网络注意事项

4.1.媒体类型
4.2.访问受限内容的活动
4.3.可协商资源
附录
A. 致谢
B. 变更日志

1. 介绍

通过 IIIF(发音为“Triple-Eye-Eff”)图像展示 API 提供的资源只有在可被找到时才有用。用户不能直接与分散的、去中心化的生态系统交互,而是必须依赖于收集和处理可用内容的服务,通过提供一个用户界面,使他们通过搜索、浏览或其他范式来浏览该内容。一旦用户发现了内容,他们就可以在他们选择的应用程序中观看它。这种方法还支持机器对机器的接口,其中软件代理可以通过 与API 交互来发现相同的内容并检索它以进行进一步的分析或处理。

该规范利用现有技术、规范和工具来促进易于实现的服务的广泛采用。该服务描述了对 IIIF 内容资源的更改以及获得的这些资源的位置。内容提供者可以实施此 API 以实现全球或专题搜索引擎和门户应用程序的协作开发,最终实现通过现有 IIIF API 提供的内容让用户轻松查找和互动的目标。

1.1 目标和范围

IIIF发现API 的目标是提供一个机器到机器的 API,用以提供发现并随后使用 IIIF 资源所需的信息。目标受众是可以利用内容和 API 的其他 IIIF 感知系统。虽然这项工作可能会直接或间接使 IIIF 社区之外的其他人受益,但 API 的目标是指定一个可互操作的解决方案,以最好和最容易地满足参与组织社区内的发现需求。

IIIF 资源的发现需要一致且易于理解的模式,以便内容提供者发布指向其可用内容的链接列表。这提供给处理列表的发现系统的一个基本的实施方案,查找已添加或更改的资源。

这个过程可以通过允许内容提供者发布有关其内容如何变化的描述来优化,使消费系统能够只检索自上次检索以来已修改的资源。这些更改可能包括内容被删除的时间或变得不可用情况。最后,为了快速同步,从发布者推送到一组订阅者的通知系统可以减少不断轮询多个源以查看是否有任何变化所需的工作量。

超出此 API 范围的工作包括推荐或创建任何描述性元数据格式,以及推荐或创建元数据搜索 API 或协议。 IIIF 社区中代表的不同领域已经拥有满足这些情况的成功标准。同样超出此 API 范围的是内容传输的优化,例如,关于在系统之间传输任何源媒体或数据的建议。

变更通知 该规范不包括用于将更改通知推送到远程系统的订阅机制。仅支持对必须处理的更改集进行定期轮询。在轮询模式的实施经验证明它是有价值的之后,可能会在未来版本中添加一个订阅/通知模式。

1.2 术语

该规范使用以下术语:

  • HTTP(S):HTTP 或 HTTPS URI 方案和互联网协议。

本文档中的术语数组(array), JSON对象(JSON object), 数字(number), 和字符串(string)将按照 Javascript 对象表示法 (JSON) 规范的定义进行解释。

本文档中的关键词must必须, must not禁止, required必须, shall必须, shall not禁止, should推荐, should not不推荐, recommended推荐, may可选, 以及 optional可选的解释参见 RFC 2119

2. IIIF资源发现概述

为了发现 IIIF 资源,发布它们的系统中这些资源的状态需要简洁且简单地传达给消费系统。然后,消费系统可以使用该信息来检索和处理相关资源,并提供支持发现和使用的平台。这种交流通过 IIIF 发现 API 进行,该 API 使用 W3C 活动流规范来描述和序列化对资源的变更。这些变更的概念模型以及发布者和用户之间的交互是基于可被 ResourceSync 框架识别的内容。无需了解这些标准中的任何一个即可使用或实施本文档中完整规定的 IIIF 发现 API。

活动用于通过记录每个更改(按其发生顺序)来描述发布系统的状态。所述更改是 IIIF 展示 API 资源的创建、修改和删除。一个了解发布系统中发生的所有更改的消费应用程序对可用资源集是完全了解的。IIIF 集合Manifests 是已发布内容及有关该内容的描述性元数据的主要访问点,但是,描述其他资源变化的活动,如 IIIF 图像 API 端点或有关所表示对象的描述性元数据,也可以以这种方式发布。由于预期用途是通知消费系统,而不是显示信息,因此发现 API 不包括旨在呈现给最终用户的任何内容。

展示 API 不包括描述性元数据字段,并且有意省去了实现高级或字段搜索所需的语义。相反,展示 API 使用 seeAlso 属性链接到外部文档,使被呈现的内容具有更丰富且有领域独特性的信息。例如,博物馆对象可能参考seeAlso 到 CIDOC-CRM 或 LIDO 描述,而书目资源可以引用都柏林核心或 MODS 描述。应尽可能使用这些外部描述来提供匹配更精确算法的访问界面。

该规范描述了三个级别的一致性,它们在发布信息的功能和精度方面相互建立。 更改集在页面中发布,然后按发布者聚合到一个集合中。 为减少进入障碍,已注意允许仅使用 Web 服务器上的静态文件实施所有级别的可能性,而不需要动态访问数据库。

2.1. IIIF 资源及其变化

对 IIIF 资源的更改有三个级别的一致性可被描述。级别 0 是一个可用资源的列表。级别 1 增加了时间戳,并以由远及近的时间排序,允许消费应用程序在列表中按倒序工作,并在遇到从之前运行中已经看到的变化后停止处理。级别 2 增加了有关活动类型的信息,从而能够明确描述资源的创建和删除。

下面的子节首先描述了如何构建每个级别的更改描述,然后在下一节中描述了如何将其嵌入到有序列表中。

2.1.1. 级别 0:资源引用

提供指向 IIIF 资源的最低有效链接集所需的核心信息是这些资源的 URIs。 结果列表中资源的顺序并不重要,但每个资源推荐只出现一次。 这是任何有效互操作性的最低级别。

这种最低级别 0 API 方法与 级别1 和 级别2 兼容,而后者带来显著优势,使用户能够更好地优化其交互。

如果资源列表中引用资源后被删除,则应重新发布整个列表,而不提及已删除的资源。用户也可能会遇到过期的资源 URIs,不再解决 IIIF Manifest 或集合,也不再引用 IIIF 资源类型的活动。

0 级活动示例:

  1. {
  2. "type": "Update",
  3. "object": {
  4. "id": "https://example.org/iiif/1/manifest",
  5. "type": "Manifest"
  6. }
  7. }

2.1.2. 级别 1:资源更改

在处理大量资源列表时,仅使用自上次处理列表以来已更改的资源是有益的。这通过在 EndTime 属性中添加时间戳进行管理,该时间戳表示资源上次修改或最初创建的时间。列表必须按顺序排列,以便最近的活动持续进行。接着,用户将按相反顺序处理活动列表,从最后到第一,并在他们遇到已经处理的活动时停止。

1 级活动示例:

  1. {
  2. "type": "Update",
  3. "object": {
  4. "id": "https://example.org/iiif/1/manifest",
  5. "type": "Manifest"
  6. },
  7. "endTime": "2017-09-20T00:00:00Z"
  8. }

2.1.3. 级别 2: 资源创建、更改、删除和移动

在最详细的级别上,已发生的所有活动可以被记录在一个日志中,每个 IIIF 资源可能具有多个活动。使用增加的类型—“创建”、”删除”和”移动”,可以明确地描述创建、删除和移动活动,从而实现同步过程以删除、添加或更新资源。

完整的更改历史记录不是必须的,有时甚至是不合需要的。如果资源有许多乃至频繁的更改,执行时可选省略任意数量的单个更改,但推荐始终将最新的更改包含在列表中。对列表的发布者视为微不足道的更改也可选被省略,例如不影响用户可见内容的那些更改。

级别 2 活动示例:

  1. {
  2. "type": "Create",
  3. "object": {
  4. "id": "https://example.org/iiif/1/manifest",
  5. "type": "Manifest"
  6. },
  7. "endTime": "2017-09-20T00:00:00Z"
  8. }

2.1.4. 聚合活动

活动可以在被引用的资源创建、修改、删除或移动以外的时间添加或删除。这一模式有几种情况,但它们都超出了内容所有者正常发布流的范例,因此不太可能影响大多数发布的执行。它们确实会影响消费应用程序,这种影响记录在了 3.5 活动流处理算法

第一个使用案例是当第三方聚合器添加从不同机构收获的活动,过滤这些活动或对象,并将它们聚合到复合流中。例如,一个有关恐龙的聚合器会只针对那些与恐龙有关的表示物过滤几个自然历史博物馆流。

其次,资源在不被创建或删除时可能会变得可用或不可用。这种情况可能会因为其权限发生了变化而发生,例如创建后的禁锢期,或者资源在数据清理或迁移过程中进行编辑时被暂时地删除。

每当遇到”添加”活动时,它在语义上类似于”创建”活动,因为这是第一次在流中提及资源。因此,除非有”添加”活动,之前出现的同一资源则没有”创建”。同理,在”移除”或”删除”之后,资源将不被引用。

添加Add活动示例:

  1. {
  2. "type": "Add",
  3. "summary": "Added newly discovered manifest to stream",
  4. "object": {
  5. "id": "https://example.org/iiif/1/manifest",
  6. "type": "Manifest"
  7. },
  8. "target": {
  9. "id": "https://example.org/activity/aggregated-changes",
  10. "type": "OrderedCollection"
  11. },
  12. "endTime": "2019-11-22T00:00:00Z"
  13. }

移除Remove活动示例:

  1. {
  2. "type": "Remove",
  3. "summary": "Removed manifest from stream due to being out of scope",
  4. "object": {
  5. "id": "https://example.org/iiif/1/manifest",
  6. "type": "Manifest"
  7. },
  8. "origin": {
  9. "id": "https://example.org/activity/aggregated-changes",
  10. "type": "OrderedCollection"
  11. },
  12. "endTime": "2017-11-23T00:00:00Z"
  13. }

2.1.5. 状态刷新活动

有时,发布系统会对其记录进行全面刷新,并重新发布每个资源的活动。当这种情况发生时,在资源刷新Refresh活动之前立即包括更新Update活动是一个很好的做法。这可以使得消费应用程序从这一刻停止寻找新的资源,因为所有可用资源已被找到。需要注意的是,刷新Refresh使用开始时间startTime而不是结束时间endTime作为发生日期,以确保它被定位在排序流中的资源活动之前。

已处理过流的消费应用程序应在此时刻之后向后读取,以便处理任何删除活动,但无需处理其他活动类型。以前未处理流的应用程序只需在遇到刷新Refresh活动时停止即可。

  1. {
  2. "type": "Refresh",
  3. "summary": "System refresh initiated",
  4. "startTime": "2020-06-21T00:00:00Z"
  5. }

2.2. 更改页面

活动一起收集到页面中,这些页面一起构成了发布系统所检测到的整个更改集。 页面引用该集合中的上一页和下一页,以及它们所属的整个集合。页面中的活动按照最近的活动最后出现的顺序列出。

随后将页面收集到有序集合中,如下一节所述。

  1. {
  2. "@context": "http://iiif.io/api/discovery/1/context.json",
  3. "id": "https://example.org/activity/page-1",
  4. "type": "OrderedCollectionPage",
  5. "partOf": {
  6. "id": "https://example.org/activity/all-changes",
  7. "type": "OrderedCollection"
  8. },
  9. "prev": {
  10. "id": "https://example.org/activity/page-0",
  11. "type": "OrderedCollectionPage"
  12. },
  13. "next": {
  14. "id": "https://example.org/activity/page-2",
  15. "type": "OrderedCollectionPage"
  16. },
  17. "orderedItems": [
  18. {
  19. "type": "Update",
  20. "object": {
  21. "id": "https://example.org/iiif/9/manifest",
  22. "type": "Manifest"
  23. },
  24. "endTime": "2018-03-10T10:00:00Z"
  25. },
  26. {
  27. "type": "Update",
  28. "object": {
  29. "id": "https://example.org/iiif/2/manifest",
  30. "type": "Manifest"
  31. },
  32. "endTime": "2018-03-11T16:30:00Z"
  33. }
  34. ]
  35. }

2.3. 页面集合

由于活动数量可能太多以至于无法在单个页面中有效表示,因此它们被收集到集合中作为初始切入点。集合引用了第一页和最后一页的 URI,其中第一页包含最久远的活动,最后一页包含最新的活动。

  1. {
  2. "@context": "http://iiif.io/api/discovery/1/context.json",
  3. "id": "https://example.org/activity/all-changes",
  4. "type": "OrderedCollection",
  5. "totalItems": 21456,
  6. "first": {
  7. "id": "https://example.org/activity/page-0",
  8. "type": "OrderedCollectionPage"
  9. },
  10. "last": {
  11. "id": "https://example.org/activity/page-214",
  12. "type": "OrderedCollectionPage"
  13. }
  14. }

2.4. 收藏登记处

为了发现收藏的URIs,并通过它们发现 IIIF 资源的URIs,IIIF 联盟管理一个收藏登记处。此登记处本身就是发现 API 的一个实施,但 IIIF 资源不是演示 API 资源,而是其他发现 API 资源。这可能包括展示集合或其他收藏的登记册。该登记处描述了其管理方式以及如何检索或提交内容。登记处还可以参考其发现 IIIF 内容的方法。

3. 活动流详情

W3C 活动流规范定义了“表示潜在和已完成活动的模型”,并且与为 IIIF API 建立的设计模式兼容。 它是根据 JSON-LD 定义的,可以与现有的 IIIF API 无缝集成。 该模型可用于表示内容发布者执行的创建、更新和删除(或以其他方式取消发布)IIIF 资源的活动。

本节对本规范使用的属性和类型进行了总结,由活动流定义。 这旨在通过收集相关信息来简化实施工作。

除了本规范中描述的那些属性之外,没有代码需要处理的消费应用程序必须被忽略。 其他被活动流定义的属性可选被使用,例如 origin instrument,但目前没有任何用例可以保证将它们包含在本规范中。

3.1. 有序集合

管理活动列表的最顶层资源是一个有序集合,又细分为有序集合页面。 集合不直接包含任何活动,而是引用了列表的第一页和最后一页。

集合的整体顺序是从最早的活动作为第一页的第一个条目,到最新的活动作为最后一页的最后一个条目。 因此,消费应用程序推荐从最后开始,向后遍历列表,并在它们到达上次处理列表时间之前的时间戳时停止。

内容提供者必须在集合的 id 属性中列出的 HTTP(S) URI 上发布一个有序集合。

id
有序集合的标识符。

有序集合必须有一个 id 属性。 该值必须是字符串,并且必须是 HTTP(S) URI。 有序集合的 JSON 表示必须在 URI 中可用。

  1. { "id": "https://example.org/activity/all-changes" }

type
有序集合的类别。

有序集合必须具有type属性。 该值必须OrderedCollection

  1. { "type": "OrderedCollection" }

first
此集合的第一个有序集合页面的链接。

有序集合推荐有first属性。 该值必须是一个 JSON 对象,具有 id 和 type 属性。 id 属性的值必须是字符串,并且必须是集合中项目第一页的 HTTP(S) URI。 type 属性的值必须是字符串 OrderedCollectionPage

  1. {
  2. "first": {
  3. "id": "https://example.org/activity/page-0",
  4. "type": "OrderedCollectionPage"
  5. }
  6. }

last
指向此集合的最后一个有序集合页面的链接。 由于客户端处理算法从最近到最晚倒叙工作,因此必须包含last推荐包含first

有序集合必须有一个 last 属性。 该值必须是一个 JSON 对象,具有 id 和 type 属性。 id 属性的值必须是字符串,并且必须是集合中最后一页项目的 HTTP(S) URI。 type 属性的值必须是字符串 OrderedCollectionPage

  1. {
  2. "last": {
  3. "id": "https://example.org/activity/page-1234",
  4. "type": "OrderedCollectionPage"
  5. }
  6. }

totalItems
整个有序集合中的活动总数。

有序集合可选 totalItems 属性。 该值必须是非负整数。

  1. { "totalItems": 21456 }

seeAlso
此属性用于引用一个或多个文档,这些文档在语义上描述了在有序集合内的活动中正在处理的资源集,而不是从集合内引用的任何特定资源。这将允许有序集合引用例如数据集的 DCAT 描述。对于聚合来自多个源的活动和/或对象的有序集合,引用的描述文件应该描述完整的聚合而不是单个源。

有序集合可选一个 seeAlso 属性。该值必须是一个或多个 JSON 对象的数组,具有 id 和 type 属性。 id 属性的值必须是字符串,并且必须是数据集描述的 HTTP(S) URI。 type 属性的值必须是字符串 Dataset。请注意,任何旨在供软件使用的资源都被标记为Dataset,包括单个文件。 JSON 对象与展示API 具有相同的结构,因此推荐具有以下属性:

  • format,其值必须是字符串,并且必须是引用的描述文档的MIME媒体类型
  • label,其值必须是 JSON 对象,遵循展示 API 中描述的语言映射模式
  • profile,其值必须是一个字符串,其中包含来自登记处简介文件或 URI 的值
    1. {
    2. "seeAlso": [
    3. {
    4. "id": "https://example.org/dataset/all-dcat.jsonld",
    5. "type": "Dataset",
    6. "label": { "en": [ "DCAT description of Collection" ] },
    7. "format": "application/ld+json",
    8. "profile": "http://www.w3.org/ns/dcat#"
    9. }
    10. ]
    11. }
    partOf
    此属性用于引用更大型的有序集合,该有序集合作为一部分包含其中。 这允许发布者拥有一系列主题或时间序活动,例如,绘画与雕塑的主题创建不同活动集,或者区别现代内容与档案内容。

有序集合可选一个 partOf 属性。 该值必须是一个或多个 JSON 对象的数组,具有 id 和 type 属性。 id 属性的值必须是字符串,并且必须是更大集合的 HTTP(S) URI。 type 属性的值必须是字符串 OrderedCollection

  1. {
  2. "partOf": [
  3. {
  4. "id": "https://example.org/aggregated-changes",
  5. "type": "OrderedCollection"
  6. }
  7. ]
  8. }

rights
标识适用于使用有序集合的许可或权利声明的字符串。 该值必须从一组知识共享许可 URI、RightsStatements.org 权利声明 URI 或通过扩展机制添加的内容中提取。 包含此属性是提供信息的,例如可用于显示代表权利声明的图标。

该值必须是字符串。 如果该值来自知识共享或 RightsStatements.org,则该字符串必须是该规范定义的 URI。

  1. { "rights": "http://creativecommons.org/licenses/by/4.0/" }

完整的有序集合示例

  1. {
  2. "@context": "http://iiif.io/api/discovery/1/context.json",
  3. "id": "https://example.org/activity/all-changes",
  4. "type": "OrderedCollection",
  5. "totalItems": 21456,
  6. "rights": "http://creativecommons.org/licenses/by/4.0/",
  7. "seeAlso": [
  8. {
  9. "id": "https://example.org/dataset/all-dcat.jsonld",
  10. "type": "Dataset",
  11. "label": { "en": [ "DCAT description of Collection" ] },
  12. "format": "application/ld+json",
  13. "profile": "http://www.w3.org/ns/dcat#"
  14. }
  15. ],
  16. "partOf": [
  17. {
  18. "id": "https://example.org/aggregated-changes",
  19. "type": "OrderedCollection"
  20. }
  21. ],
  22. "first": {
  23. "id": "https://example.org/activity/page-0",
  24. "type": "OrderedCollectionPage"
  25. },
  26. "last": {
  27. "id": "https://example.org/activity/page-214",
  28. "type": "OrderedCollectionPage"
  29. }
  30. }

3.2. 有序集合页面

活动列表通过同时遵循pre(或next)关系从页到页,以及在页面内部的orderedItems 属性中进行排序。 每个页面的条目数由实施者决定,且客户端无法在请求时进行修改。 页面不需要与任何其他页面具有相同数量的条目。

内容提供者必须在页面的 id 属性中给出的 HTTP(S) URI 上发布至少一个有序集合页面。

id
集合页面的标识符。

有序集合页面必须具有 id 属性。 该值必须是字符串,并且必须是 HTTP(S) URI。 有序集合页面的 JSON 表示必须在 URI 中可用。

  1. { "id": "https://example.org/activity/page-0" }

type
有序集合页面的类别。

有序集合必须具有type属性。 该值必须OrderedCollectionPage

  1. { "type": "OrderedCollectionPage" }

partOf
此页面所属的有序集合。

有序集合页面推荐使用一个 partOf 属性。 该值必须是一个 JSON 对象,具有 id 和 type 属性。 id 属性的值必须是字符串,并且必须是此页面所属的有序集合的 HTTP(S) URI。 type 属性的值必须是字符串 OrderedCollection

  1. {
  2. "partOf": {
  3. "id": "https://example.org/activity/all-changes",
  4. "type": "OrderedCollection"
  5. }
  6. }

startIndex
此页面的orderedItems 列表中第一项的位置,相对于集合中所有页面的整体排序。 整个列表中的第一个条目的 startIndex 为 0。如果第一页有 20 个条目,则第二页上的第一个条目将因此是 20。

有序集合页面可选一个 startIndex 属性。 该值必须是非负整数。

  1. { "startIndex": 20 }

next
对页面列表中下一页的引用。

有序集合页面推荐使用一个 next 属性,除非它们是集合中的最后一页。 该值必须是一个 JSON 对象,具有 id 和 type 属性。 id 属性的值必须是字符串,并且必须是以下有序集合页面的 HTTP(S) URI。 type 属性的值必须是字符串 OrderedCollectionPage

  1. {
  2. "next": {
  3. "id": "https://example.org/activity/page-2",
  4. "type": "OrderedCollectionPage"
  5. }
  6. }

prev
对页面列表中上一页的引用。

有序集合页面必须具有 prev 属性,除非它们是集合中的第一页。 该值必须是一个 JSON 对象,具有 id 和 type 属性。 id 属性的值必须是字符串,并且必须是前一个有序集合页面的 HTTP(S) URI。 type 属性的值必须是字符串 OrderedCollectionPage

  1. {
  2. "prev": {
  3. "id": "https://example.org/activity/page-1",
  4. "type": "OrderedCollectionPage"
  5. }
  6. }

oderedItems
作为此页面的一部分列出的活动。 如果活动具有 endTime 属性,则它们必须在数组中从最早的日期时间到最近的日期时间进行排序,与页面在有序集合中的排序方式相同。

有序集合页面必须有一个orderedItems 属性。 该值必须是一个数组,至少包含一项。 每一项必须是一个 JSON 对象,符合一个活动的要求。

  1. {
  2. "orderedItems": [
  3. {
  4. "type": "Update",
  5. "object": {
  6. "id": "https://example.org/iiif/1/manifest",
  7. "type": "Manifest"
  8. },
  9. "endTime": "2018-03-10T10:00:00Z"
  10. }
  11. ]
  12. }

完整的有序集合页面示例

  1. {
  2. "@context": "http://iiif.io/api/discovery/1/context.json",
  3. "id": "https://example.org/activity/page-1",
  4. "type": "OrderedCollectionPage",
  5. "startIndex": 20,
  6. "partOf": {
  7. "id": "https://example.org/activity/all-changes",
  8. "type": "OrderedCollection"
  9. },
  10. "prev": {
  11. "id": "https://example.org/activity/page-0",
  12. "type": "OrderedCollectionPage"
  13. },
  14. "next": {
  15. "id": "https://example.org/activity/page-2",
  16. "type": "OrderedCollectionPage"
  17. },
  18. "orderedItems": [
  19. {
  20. "type": "Update",
  21. "object": {
  22. "id": "https://example.org/iiif/1/manifest",
  23. "type": "Manifest"
  24. },
  25. "endTime": "2018-03-10T10:00:00Z"
  26. }
  27. ]
  28. }

3.3. 活动

活动是描述内容提供者系统中发生变化的方式。

内容提供者可以与有序集合页面分别发布活动,如果是这样,它们必须位于活动的 id 属性给出的 HTTP(S) URI中。

id
活动的标识符。

活动可选一个 id 属性。 该值必须是字符串,并且必须是 HTTP(S) URI。 活动的 JSON 表示可以在 URI 处可用。

  1. { "id": "https://example.org/activity/1" }

type
活动的类型。

本规范使用下表中描述的类型。

类型 定义
Create创建 资源的初始创建。 每个资源最多应该有一个以它是对象的创建活动,但是如果资源的URI在一个删除活动之后被重用,那么可以不止一个创建活动。
Update更新 对资源的任何更改。 在不区分创建和修改的系统中,所有更改都可以具有更新类型。
Delete删除 删除资源,或将其从网络上取消发布。 每个资源最多应该有一个以它是对象的删除活动,但如果随后重新发布然后再次删除,则可以有多个。
Move移动 在具有相同内容的新 URI 上重新发布资源。 每个资源可以有零个或多个以它是对象或目标的移动活动。
Add添加 在任何上述类型的活动之外,将对象添加到流中,例如第三方聚合器从新发现的流中添加资源。每个资源最多应该有一个以其作为对象的添加活动,但是如果在移除活动之后重新添加资源,那么可以不止一个。如果同时存在创建或更新活动,则不推荐添加活动。
Remove移除 在任何上述类型的活动之外从流中移除对象,例如第三方聚合器从流中移除不再被认为在范围内的资源。每个资源最多推荐使用一个以其作为对象的移除活动,但是如果资源被重新添加然后重新删除,那么可选不止一个。 如果同时存在删除活动,则不推荐移除活动。
Refresh刷新 刷新所有资源状态的活动的开始。它没有对象或目标。

活动必须具有 type 属性。 该值必须是注册的活动类型,并且推荐为创建、更新或删除之一。

  1. { "type": "Update" }

object
受活动影响的 IIIF 资源。在实施中需要对是否有单独的活动列表、每个对象类型一个列表,还是包含所有对象类型的单个列表做出决定。

在移动活动的情况下,对象属性包含其被移动来源的 id 和 type。新位置将位于 target 属性中,如下所述。

活动必须具有 object 属性。该值必须是一个 JSON 对象,具有 id 和 type 属性。 id 必须是 HTTP(S) URI。type 推荐为在 IIIF 展示API 中定义的一个类,并且应该是 Collection 或 Manifest 之一。因此,type 可以是任何类,包括那些未由 IIIF展示API 定义的类,并且消费应用程序应该验证该 type 是否适合其使用。

该对象可以具有如上面为 OrderedCollection 定义的 seeAlso 属性,以引用描述对象资源的文档。 seeAlso 属性中引用的文档也可以在 IIIF展示API 的实例中与 seeAlso 属性一起引用。 seeAlso 属性中引用的文档类型应作为 Dataset 给出,表示它是数据而不是人类可读的文档。

对象可以具有 canonical 属性,其值必须是包含 URI 的字符串。此 URI 标识资源,而不管对象的 id 属性中给出的 URI 是什么,这可能特定于格式、API 版本或发布平台。使用此属性允许跨表示对齐更改,而无需依赖 seeAlso 链接或仅具有单个表示。

该对象可以具有提供者属性,如 IIIF 展示API 所定义。特别是,属性的值必须是一个JSON对象数组,每个对象都必须分别有id、type和label属性,携带提供者的URI,字符串“代理”,以及在一个语言映射对象的提供者名称。

  1. {
  2. "object": {
  3. "id": "http://example.org/iiif/v3/1/manifest",
  4. "type": "Manifest",
  5. "canonical": "https://example.org/iiif/1",
  6. "seeAlso": [
  7. {
  8. "id": "https://example.org/dataset/single-item.jsonld",
  9. "type": "Dataset",
  10. "label": { "en": [ "Object Description in Schema.Org" ] },
  11. "format": "application/ld+json",
  12. "profile": "https://schema.org/"
  13. }
  14. ],
  15. "provider": [
  16. {
  17. "id": "https://example.org/about",
  18. "type": "Agent",
  19. "label": { "en": [ "Example Organization" ] }
  20. }
  21. ]
  22. }
  23. }

target
IIIF 资源受移动活动影响后的新位置。

移动活动必须具有target属性。 该值必须是一个 JSON 对象,具有 id 和 type 属性。 id 必须是 HTTP(S) URI,并且必须与对象属性的 id 中给出的 URI 不同。 类型应该是在 IIIF 展示 API 中定义的类,并且应该与对象属性的类型相同。 其他可用于描述对象的属性,如 seeAlso 和 canonical,也可用于描述目标。

  1. {
  2. "target": {
  3. "id": "http://example.org/a/manifest",
  4. "type": "Manifest",
  5. "seeAlso": [
  6. {
  7. "id": "https://example.org/single-item-a.jsonld",
  8. "type": "Dataset",
  9. "format": "application/ld+json"
  10. }
  11. ]
  12. }
  13. }

endTime
活动完成的时间。 endTime 的值在线发实施者决定,可以是发布 IIIF 资源的时间戳,也可以是管理系统中修改数据的时间戳(如果它们不同的话),但必须保持一致地应用。 object 中给定的已更改资源必须在 endTime 中给定的时间戳或之前在其 URI 处可用。 endTime 的值应该早于活动作为其有序集合的一部分发布的时间。

活动推荐具有 endTime 属性。 该值必须是以 UTC 表示的日期时间,格式为 xsd:dateTime

  1. { "endTime": "2017-09-21T00:00:00Z" }

startTime
活动开始的时间。

活动可选 startTime 属性。 该值必须是以 UTC 表示的日期时间,格式为 xsd:dateTime

  1. { "startTime": "2017-09-20T23:58:00Z" }

summary
活动的简短文字描述。 这主要用于调试目的或解释性消息,因此没有对内容统一性的要求。 该领域的目标受众是管理聚合服务并查看数据的人,而不是 IIIF 资源的最终用户。 不建议出现此字段,因为在大多数情况下它永远不会被看到。

活动可选summary属性。 该值必须是字符串。

  1. { "summary": "admin updated the manifest, fixing reported bug #15." }

actor
执行活动的组织、人员或软件代理。

活动可选actor 属性。 该值必须是一个 JSON 对象,具有 id 和 type 属性。 id 应该是一个 HTTP(S) URI。 类型必须是应用程序、组织或人员之一。

  1. {
  2. "actor": {
  3. "id": "https://example.org/person/admin1",
  4. "type": "Person"
  5. }
  6. }

完整活动示例
因此,一个完整的示例活动将类似于以下示例。 请注意,它没有 @context 属性,因为它始终嵌入在 CollectionPage 中。 另请注意,这是一个包含所有可能字段的完整示例; 大多数实现不需要也不需要暴露这个级别的数据。

  1. {
  2. "@context": "http://iiif.io/api/discovery/1/context.json",
  3. "id": "https://example.org/activity/1",
  4. "type": "Update",
  5. "summary": "admin updated the manifest, fixing reported bug #15.",
  6. "object": {
  7. "id": "https://example.org/iiif/1/manifest",
  8. "type": "Manifest",
  9. "canonical": "https://example.org/iiif/1",
  10. "seeAlso": [
  11. {
  12. "id": "https://example.org/dataset/single-item.jsonld",
  13. "type": "Dataset",
  14. "format": "application/ld+json"
  15. }
  16. ]
  17. },
  18. "endTime": "2017-09-21T00:00:00Z",
  19. "startTime": "2017-09-20T23:58:00Z",
  20. "actor": {
  21. "id": "https://example.org/person/admin1",
  22. "type": "Person"
  23. }
  24. }

3.4. 关联数据上下文和扩展

3.4.1. @上下文

响应中的顶级资源必须具有 @上下文属性,并且它推荐显示为 JSON 表示的第一个键/值对。 此属性允许关联数据处理器将文档解释为图形。 该属性的值必须是 IIIF 发现上下文文档的 URI,[http://iiif.io/api/discovery/1/context.json](http://iiif.io/api/discovery/1/context.json),或一个字符串数组,其中 IIIF 发现上下文文档的 URI 是数组中的最后一项。

  1. {
  2. "@context": "http://iiif.io/api/discovery/1/context.json"
  3. }

3.4.2. 扩展

如果在本规范或活动流规范中定义的类型或属性之外需要任何其他类型或属性,则这些类型或属性应该映射到一个或多个附加上下文文档中的 RDF 术语。 这些扩展上下文应该添加到顶级@context 属性中,并且必须在 Discovery 上下文的 URI 之前。 必须使用 JSON-LD 1.1 功能仅在特定属性内定义术语,称为作用域上下文必须用于最小化跨扩展冲突。 用于广泛使用的扩展应该扩展注册处中注册。

  1. {
  2. "@context": [
  3. "http://example.org/extension/context.json",
  4. "http://iiif.io/api/discovery/1/context.json"
  5. ]
  6. }

3.5. 活动流处理算法

处理算法的目的是告知开发者实现消费应用程序如何最好地利用可用信息。 该规范不要求消费应用程序对信息进行任何特定处理,但将资源索引视为第 3.5.3 节中的常见用例。

任何其他算法与下面指定的算法的实现获得相同的结果也将被认为是符合要求的。 这些算法是作为建议(推荐)而不是严格要求提供的,以免过度限制使用或抑制新想法和实验。

为了同时处理多个流,需要完成额外的处理工作以确保正确的结果,因为相同的活动可能会在多个流中表示。 这在第 3.5.4 节中描述。

3.5.1. 收集算法

给定活动流集合(Collection)的 URI 作为输入,符合标准的处理器应该

  1. 初始化:
    1. processedItems 为一个空数组
    2. lastCrawl 作为上次执行算法的时间戳,如果这是第一次处理流,则为 null
    3. onlyDelete False
  2. 通过 HTTP(S) 检索集合的表示
  3. 验证检索到的表示至少包含处理所需的特征
  4. collection.last.id (pageN) 处找到最后一页的 URI
  5. 将page算法的结果应用到pageN

3.5.2.页面算法

给定活动流集合页面 CollectionPage(页面)的 URI、已处理项目列表 (processedItems)、上次抓取日期 (lastCrawl) 和处理函数 (process()) 作为输入,符合标准的处理器应该

  1. 通过 HTTP(S) 检索页面的表示
  2. 验证检索到的表示是否至少包含处理所需的特征
  3. page.orderedItems (项目) 处找到页面的更新集
  4. 以相反的顺序,遍历项目中的活动(activity):

a. 如果 activity.endTime 在 lastCrawl 之前,则终止;
b. 如果activity.type为Refresh,则如果lastCrawl不为null,则设置onlyDelete为True,否则如果lastCrawl为null,则终止;
c. 如果 activity.object.id 处更新的资源的 URI 在 processingItems 中,则继续;
d. 如果 activity.object.type 中更新资源的类不是处理器已知的类,则继续;
e. 否则,如果activity.type是Delete,或者是Remove,activity.origin.id是当前流的URI,则在activity.object.id处找到资源的URI并处理它的删除;
f. 否则,如果 onlyDelete 为 True,则继续;
g. 否则,如果activity.type为Update或Create,或者为Add,activity.target.id为当前流的URI,则在activity.object.id(object)处找到资源的URI,并处理其包含;
h. 否则,如果activity.type为Move,则在activity.object处找到被移动资源的原始URI并处理其移除,在activity.target处找到被移动资源的新URI并处理其包含。
i. 将已处理资源的 URI 添加到 processingItems

  1. 最后,在 collection.prev.id (pageN1) 处找到上一页的 URI
  2. 如果有前一页,则将页面算法的结果应用到 pageN1

3.5.3. 资源处理:索引

虽然有许多可用的算法来处理发现的资源和活动,但发现API 的一个核心用例是维护资源的最新索引。

在这种情况下,消费应用程序的目标是找到可能用于构建索引的准确的、机器可读的描述信息,因此应用程序(推荐)使用 IIIF展示API seeAlso 属性来检索此类描述(如果可用)。 对于不同类型的资源以及不同的领域,所引用的描述性资源会有不同的格式和语义。 如果没有这样的描述,或者没有可以处理的描述,即便有其表现意图,Manifest 和其他 IIIF 资源中的数据可能会被用作最后的手段。

3.5.4. 处理多个流

为了同时处理多个流,应遵循处理页面的步骤,但将某一种更改贯彻于所有流中,按活动的时间戳排序。对此的一个推动因素是,当活动被广泛聚合时,相同的活动可能会出现在多个流中。例如,相同的更新可能发生在十个一起处理的三个流中,并且应该只处理一次。

处理超出每个资源最近的活动的实现应该将具有相同的:类型(type),项目id (object.id) 和 结束时间(endTime)的两个活动视为相同的活动,而不管任何其他属性。通过这种方式,即使不同的流保持不同程度的描述和信息,或者某些实现在其 URI 处具有或没有可用的活动,也可以检测到重复的活动。

下面的算法没有考虑任何围绕内存或处理的优化或约束。根据每个排序,一个更复杂的算法可能会处理页面,以保持活动的交错缓冲区已满,而不是在开始处理活动之前检索和处理所有内容。由于这个原因,它没有像上面的处理算法那样详细地描述。

给定一个集合 URI 的数组(集合)作为输入,

  1. 如上所述初始化全局值 processingItems 和 lastCrawl。
  2. 让 allActivities 为一个空数组。
  3. 对于集合中的每个集合:
    1. 检索并验证集合的表示。
    2. 虽然有些页面的活动在 lastCrawl 之后具有时间戳:
      1. 检索并验证页面的表示,并将匹配的活动添加到 allActivities
  4. 按 activity.endTime 对 allActivities 进行降序排序,如上所述删除任何重复项。
  5. 对于 allActivities 中的每个活动,应用页面算法对活动的处理。

4. 网络注意事项

4.1. 媒体类型

如上所述,此 API 的所有响应的基本格式都是 JSON。

如果服务器收到带有 以Accept 为开头的请求,它应该按照内容协商的规则进行响应。 请注意,请求的 Accept 标头中提供的内容类型可选包括参数,例如配置文件(profile)或字符集(charset)。

如果请求不包含 Accept 标头,则响应的 HTTP内容类型(Content-Type) 标头的值应为 application/ld+json (JSON-LD),并提供作为上下文文档的配置文件参数[http://iiif.io/api/discovery/1/context.json](http://iiif.io/api/discovery/1/context.json)

  1. Content-Type:
  2. application/ld+json;profile="http://iiif.io/api/discovery/1/context.json"

如果无法生成上述 Content-Type 标头值,则该值应改为 application/json(常规 JSON),不带配置文件参数。

  1. Content-Type: application/json

HTTP 服务器推荐遵循 CORS 要求,以使基于浏览器的客户端能够检索响应。 Apache HTTP Server 实施说明中提供了启用 CORS 和条件 Content-Type 标头的方法。 响应应该由服务器压缩,因为对于非常重复的数据结构有显着的性能提升。

4.2. 访问受限内容的活动

有关具有访问限制的内容的活动可选择被发布。客户端禁止假设他们能够访问作为活动对象的每个资源,并且禁止假设它在不可访问时已被删除。 例如,内容可能受到拒绝访问的身份验证系统的保护(最终用户可能能够提供正确的凭据来获得访问权限),或者可能存在临时网络中断而阻止检索内容(网络将被最终恢复)。

内容也可能从可用变为受访问限制保护,或者在先前受保护后变为可用。 对于这些情况,没有更具体的活动类型,发布者相应地发布定期更新或删除活动。

4.3. 可协商资源

某些 HTTP(S) URI 能够以相同内容的不同表示形式响应具有不同标头的请求,例如相同的 URI 能够基于 Accept 标头返回 IIIF展示API 的第 2 版和第 3 版.这称为“内容协商”,此类资源称为“可协商资源”。可以协商的表示被称为“变体”。

发现API 不支持可协商资源,仅支持变体。这意味着每个可用的表示都有一个活动条目,并且每个表示都必须有自己的 URI,即使是通过它可协商的资源访问。在针对不同版本的 IIIF展示API 进行协商的情况下,格式属性可用于包含资源的完整媒体类型,其中特定于版本的上下文文档在配置文件参数中给出。如果有额外的描述性资源可用,每个这样的资源将描述所有的变体,因此每个活动的 seeAlso 属性将引用相同的描述,允许变体连接在一起。

相同的可协商资源的两种变体可表示如下。

  1. {
  2. "orderedItems": [
  3. {
  4. "type": "Update",
  5. "object": {
  6. "id": "https://example.org/iiif/1/manifest/v2",
  7. "type": "Manifest",
  8. "seeAlso": "https://example.org/iiif/1/metadata.xml",
  9. "format": "application/ld+json;profile=\"https://iiif.io/api/presentation/2/context.json\""
  10. },
  11. "endTime": "2018-03-10T10:00:00Z"
  12. },
  13. {
  14. "type": "Update",
  15. "object": {
  16. "id": "https://example.org/iiif/1/manifest/v3",
  17. "type": "Manifest",
  18. "seeAlso": "https://example.org/iiif/1/metadata.xml",
  19. "format": "application/ld+json;profile=\"https://iiif.io/api/presentation/3/context.json\""
  20. },
  21. "endTime": "2018-03-10T10:00:00Z"
  22. }
  23. ]
  24. }

附录

A. 致谢

非常感谢 IIIF 社区的成员不断参与、创新想法和反馈。

该规范主要归功于由Antoine Isaac (欧洲数字文化遗产平台), Matthew McGrattan (Digirati) and Robert Sanderson (耶鲁大学)担任主席的IIIF发现技术规范小组的工作。IIIF社区感谢他们的领导和小组成员的不懈努力。

B. 变更日志

日期 说明
2021-06-22 Version 1.0 (Zooming Heatwave)
2021-04-28 Version 0.9.2 (unnamed)
2020-09-29 Version 0.9.1 (unnamed)
2020-06-04 Version 0.9 (unnamed)
2019-11-01 Version 0.4 (unnamed)
2019-03-20 Version 0.3 (unnamed)
2018-11-12 Version 0.2 (unnamed)
2018-05-04 Version 0.1 (unnamed)