在本系列中,目前为止您已经了解大量概念信息:
在本系列的最后一期中,我将介绍如何结合这些想法,让信息能够在各种可互操作的工具之间共享。
“ OSLC 和 Linked Data Platform ” 介绍了 OSLC 项目,包括它的状态、目标、原则和 3.0 版所基于的基本框架。正如我在这一期文章中所提到的,该项目正处在过渡阶段。3.0 版明显背离了 2.0 系列规范的设计方式。尽管仍然可以在各个版本之间实现兼容性,但新规范为您提供了更有益的起点来学习 OSLC。但是因为 3.0 规范尚未完成,所以暂时缺少支持 3.0 的工具。
本系列介绍、探讨和应用全球标准,解决开发人员、架构师和数据管理员每天所面临的大规模数据集成难题。本系列介绍的一些跨平台的、独立于语言和应用程序的技术,支持在数据库、文档、电子表格、服务 API 中进行信息集成。您将了解的数据模型和工具可以让您的工作变得更轻松,并对您的组织产生实质性的影响。
该项目的治理模型也已改变 — 从 IBM 领导的计划转变为由 OASIS 小组带头的计划。随着新工作组收拾残局并不断取得进步,这一变化放大了稳定状态之间的感觉。在此期间,几乎所有现有的文档(入门手册、教程、示例应用程序和实现指南)都针对的是 OSLC 2.0 设计。今年夏季有一场活动来支持各种 OSLC 网站上表明的这种情况,但仍有许多工作要做。不熟悉该社区的人仍然很容易迷失方向。
尽管提出了所有这些告诫,我仍看好该项目的未来。我想它能够以已取得的成功为基础,朝简化并增强 OSLC 感知技术的集成机会的新方向发展。在本文中,我将通过一些动手示例,提供一种参与 OSLC 领域的简化方法,并大略讲讲该项目正开始采取的新方向。
“ Eclipse Lyo 代码库包含对各种 OSLC 规范和 Linked Data Platform 的支持。 ”
Eclipse Lyo 项目 是为了 OSLC 系统的开源参考实现而建立的。尽管任何人可以使用任何堆栈构建符合 OSLC/LDP 的容器,但 Lyo 为对基于 Java™ 的工具集感兴趣的人提供了一个可重用的基础。
首先,安装 git 和 Apache Maven 。还需要安装一个 Java 版本。接下来,从 Lyo 项目的存储库中签出它:
> git clone http://git.eclipse.org/gitroot/lyo/org.eclipse.lyo.rio.git Cloning into 'org.eclipse.lyo.rio'... remote: Counting objects: 3519, done. remote: Total 3519 (delta 0), reused 0 (delta 0) Receiving objects: 100% (3519/3519), 1.36 MiB | 152.00 KiB/s, done. Resolving deltas: 100% (1285/1285), done. Checking connectivity... done.
如果不想下载示例应用程序的代码来在本地运行,可以使用一个在IBM Bluemix 云服务上运行的方便的 实例 。请记住,这是一个简单、开放的概念证明服务,仅用于教学用途。不要通过过多的请求或不当的内容来滥用它!
Lyo 代码库包含对各种 OSLC 规范和 LDP 的支持。它是一项正在进行的工作,但已足以用来演示这里的想法。
一个未包含在该项目中的示例应用程序演示了这些想法的基础。在运行该应用程序之前,您可能想编辑 pom.xml 来更改它使用的端口,该端口默认为 8080。(我在这里使用默认端口,但是,如果您要使用服务器端 Java,可能已有某个东西使用了您的 8080 端口。)然后,运行 install
和 jetty:run
Maven 目标来启动服务器:
> cd org.eclipse.lyo.oslc.v3.sample > mvn install jetty:run [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building OSLC 3.0 Reference Implementation 3.0.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ ... [INFO] Started ServerConnector@600f5704{HTTP/1.1}{0.0.0.0:8080} [INFO] Started @7288ms [INFO] Started Jetty Server
此刻,示例应用程序(一个简单的错误跟踪器)正在运行。它有一个部署在默认端口上的 LDP 容器。如果我尝试直接连接该端口,我会获知一个已部署的 Web 应用程序在 http://localhost:8080/oslc3 上。如果我在浏览器中打开该位置,我会看到如 图 1 所示的 HTML 页面。如果我将鼠标悬停在 Bug Container 链接上,会获知一个 LDP 容器在 http://localhost:8080/oscl3/r/bugs 上。
图 1. OSLC 3.0 示例应用程序的初始页面
点击查看大图
关闭 [x]
像上一篇文章中一样,我可以资源形式请求容器 URL 来与容器交互。清单 1 给出了请求和响应。
清单 1. 请求容器的信息
> http get http://localhost:8080/oslc3/r/bugs HTTP/1.1 200 OK Accept-Post: text/turtle,application/json,application/json Allow: GET,HEAD,POST,OPTIONS Cache-Control: no-cache Content-Type: text/turtle Date: Sat, 15 Aug 2015 02:53:32 GMT ETag: "302493f36090f8e473289c4e5b47ee78" Link: <http://www.w3.org/ns/ldp#Resource>; rel="type" Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type" Link: <http://open-services.net/ns/cm#Defect>; rel="http://open-services.net/ns/core#creationType" Link: <http://localhost:8080/oslc3/Defect-shape.ttl>; rel="http://www.w3.org/ns/ldp#constrainedBy" Link: <http://localhost:8080/oslc3/r/bugs/creationDialog>; rel="http://open-services.net/ns/core#creationDialog" Server: Jetty(9.2.2.v20140723) Transfer-Encoding: chunked Vary: Accept,Prefer @base <http://localhost:8080/oslc3/r/bugs> . <> a <http://www.w3.org/ns/ldp#BasicContainer> ; <http://purl.org/dc/terms/title> "Bug Container" .
从响应中,我知道了我能对容器执行的操作,知道它是来自 http://www.w3.org/ns/ldp#
命名空间的 Resource
和 BasicContainer
类的一个实例。该响应还包含我未讨论的一些新链接:
http://open-services.net/ns/core#creationType
:这个链接让我很困惑。它的意图很明显,但如果您在 此位置 解析它,它没有记录在核心词汇表中。我无法找到对它的任何其他引用,所以它可能是一个遗留词汇或一个还未记录的新词汇。无论如何,它告诉了我应创建来添加到容器的事物类型是 http://open-services.net/ns/cm#Defect
。 http://open-services.net/ns/core#creationDialog
:此关系已在核心词汇表中定义,表明它 “使客户端能够通过 UI 创建资源”。我稍后将进一步解释此概念。 我还看到上一篇文章中介绍的 http://www.w3.org/ns/ldp#constrainedBy
关系的一种新用法。在这里,它被链接到一个 Turtle 文件,该文件定义一个缺陷的 形状 。
从本系列的第一篇文章我们已知道,RDF 旨在支持 开放世界假设 ;它不是为了一般性地迫使数据图表执行一种预期的领域模型。从更加面向企业的软件领域进入语义 Web 领域的人,通常想要 “关闭” 世界和验证一个图表的结构的能力。为了帮助管理跨工具集成时的预期, W3C RDF 数据形状工作组 (W3C RDF Data Shapes Working Group) 放弃了 OSLC 工作来实现此目的。如果我请求 constrainedBy
关系所指向的文档,如清单 2 所示,我会知道在创建一个缺陷时要提供 Defect
的哪些信息。 Defect
类上附加了大约 20 个属性。形状文件很大,所以我仅在清单 2 中给出了它的一部分。
清单 2. 请求缺陷形状的信息
> http get http://localhost:8080/oslc3/Defect-shape.ttl HTTP/1.1 200 OK Accept-Ranges: bytes Content-Length: 12621 Content-Type: text/turtle Date: Sat, 15 Aug 2015 03:21:56 GMT Last-Modified: Sat, 15 Aug 2015 00:38:24 GMT Server: Jetty(9.2.2.v20140723) @prefix foaf: <http://http://xmlns.com/foaf/0.1/> . @prefix oslc_cm: <http://open-services.net/ns/cm#> . @prefix oslc: <http://open-services.net/ns/core#> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix dcterms: <http://purl.org/dc/terms/> . <> a oslc:ResourceShape ; oslc:describes oslc_cm:Defect ; dcterms:title "A software or product defect." ; dcterms:description "Used by Quality Management tools to report defects in testing." ; oslc:property <#affectsPlanItem>, <#affectsRequirement>, <#attachment>, <#closeDate>, <#contributor>, <#created>, <#creator>, <#description>, <#discussedBy>, <#identifier>, <#instanceShape>, <#modified>, <#priority>, <#relatedChangeRequest>, <#severity>, <#shortTitle>, <#state>, <#subject>, <#title>, <#tracksChangeSet>, <#type> . <#affectsPlanItem> a oslc:Property ; oslc:name "affectsPlanItem" ; oslc:occurs oslc:Zero-or-many ; oslc:propertyDefinition oslc_cm:affectsPlanItem ; oslc:representation oslc:Reference ; oslc:valueType oslc:Resource ; dcterms:description "Change request affects plan item."^^rdf:XMLLiteral ; dcterms:title "Affects PlanItem" . ...
“ 该信息的预期形状的描述不言自明,且具有语义意义,这使得客户端能够提供必要和相关的内容来创建一个新缺陷。 ”
第一个属性 ( affectsPlanItem
) 的元数据表明它不是必需的,因为它可能出现 0 次或更多次。 affectsPlanItem
将一个更改请求连接到项目计划上的一个项,以便用于跟踪用途。还存在受影响的需求、附加一个相关媒体文件、缺陷的创建者等类似属性。该信息的预期形状的描述不言自明且具有语义意义,这使客户端能够提供必要和相关的内容来创建一个新缺陷。
constrainedBy
链接指向一个 Turtle 文档,该文档指明了可用来描述一个缺陷的属性。同样地,容器的响应标头中有一个 http://open-services.net/ns/core#creationDialog
链接。如果我请求此关系所链接的资源,我会获得有关另一种创建具有此容器所期望类型的资源的方式的元数据(在本例中,该资源是一个用户界面,如清单 3 所示),该资源可由客户端向其用户显示。我不仅了解了所提供的 UI 的建议高度和宽度,还了解了一个标题、一个告知它的存在的标签,以及一个我可请求本来获取实际的 HTML 对话框的 URL。
清单 3. 请求缺陷创建对话框的信息
> http get http://localhost:8080/oslc3/r/bugs/creationDialog HTTP/1.1 200 OK Content-Type: text/turtle Date: Sat, 15 Aug 2015 04:39:14 GMT Server: Jetty(9.2.2.v20140723) Transfer-Encoding: chunked <http://localhost:8080/oslc3/r/bugs/creationDialog> a <http://open-services.net/ns/core#Dialog> ; <http://open-services.net/ns/core#dialog> <http://localhost:8080/oslc3/creationDialog.html> ; <http://open-services.net/ns/core#hintHeight> "395px" ; <http://open-services.net/ns/core#hintWidth> "450px" ; <http://open-services.net/ns/core#label> "Open Bug" ; <http://purl.org/dc/terms/title> "Open Bug" .
这里的重点是,这些通知的特性对潜在的客户很有用。除了使用 Turtle 和显示一个 HTML 文档的能力,该应用程序还做出了另一些假设。任何可能希望支持创建新缺陷的嵌入式能力的客户端,都应拥有所有必要的组件来实现该目的。
任何客户端都不是必须使用这些机制。完全可以根据形状定义中的元数据来构建一个自定义界面。任何理解自己的需求的客户端都可以轻松地转换现有数据,然后以编程方式向容器 POST
一个新缺陷。但是,如清单 4 所示,传递一个预先创建的 HTML 表单很方便,尤其是在针对人类用户而不是纯软件客户端时。我省略了许多有关它返回的内容的细节,只是展示了主要结构。
清单 4. 请求一个对话框来帮助创建一个新缺陷
> http get http://localhost:8080/oslc3/creationDialog.html HTTP/1.1 200 OK Accept-Ranges: bytes Content-Length: 4068 Content-Type: text/html Date: Sat, 15 Aug 2015 05:50:20 GMT Last-Modified: Sat, 15 Aug 2015 00:38:24 GMT Server: Jetty(9.2.2.v20140723) <!DOCTYPE html> ... <html lang="en"> <head> <meta charset="utf-8" /> <meta name='viewport' content='width=device-width, initial-scale=1.0, user-scalable=no'> <title>New Bug - OSLC 3.0 Reference Implementation</title> <link rel="stylesheet" type="text/css" href="style/common.css"> <link rel="stylesheet" type="text/css" href="style/dialog.css"> <link rel="shortcut icon" href="oslc-16x16.png"> <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript"> // Our JSON-LD context for creating defects var context = { oslc_cm: "http://open-services.net/ns/cm#", dcterms: "http://purl.org/dc/terms/", Defect: "oslc_cm:Defect", description: "dcterms:description", severity: { "@id": "oslc_cm:severity", "@type": "@id" }, title: "dcterms:title" }; ... </script> </head> <body> <form> <div> <input id="title" type="text" class="bugInput" required autofocus placeholder="Enter bug title"> </input> </div> <div> <label for="severity">Severity:</label> <select id="severity"> <option value="oslc_cm:Blocker">Blocker</option> <option value="oslc_cm:Critical">Critical</option> <option value="oslc_cm:Major">Major</option> <option value="oslc_cm:Normal" selected>Normal</option> <option value="oslc_cm:Minor">Minor</option> </select> </div> <div> <label for="description">Description:</label> </div> <div> <textarea id="description" class="bugInput descriptionTextArea"></textarea> </div> <div> <input type="submit" name="OK"></input> <button type="button" id="cancel">Cancel</button> </div> </form> </body> </html>
在上一篇文章 中,我展示了如何通过直接 HTTP 向 LDP 容器添加资源。当然,真实的系统拥有只允许某些人这么做的身份验证协议。在本例中,我展示了使用 HTML 内容实现此目的的基本工作流。我已经介绍过如何发现创建对话框的位置。令人难以理解的是,示例应用程序拥有此对话框的一个重复副本(名为 newBug.html),它单独实例化了这个副本。我需要假设这只是简单的疏忽。在大多数情况下,此过程应通知和使用同样的 HTML 来创建新缺陷。但是,显然不能想象您有一个可重用的共享功能和一个特定于应用程序的自定义功能来实现此用途。在这种情况下,令人奇怪的是,一个完全相同的文件有两个副本。
查看 sample 目录中的 index.html 文件。它包含对 js/index.js 的引用 — 用户单击 Open Bug 按钮(如图 1所示)时调用的代码。清单 5 给出了一个来自该 JavaScript 文件的函数,该函数创建对话框并将它作为 iframe
附加到容器,除非使用较小的显示屏(在这种情况下,将创建一个独立的新窗口来存放对话框的内容)。
清单 5. 显示创建新缺陷的对话框
function showDialog() { if (isSmallScreen()) { // For small screens, open a new window. dialogWindow = window.open('newBug.html', 'oslcDialog'); } else { var dialog = $('.dialog'); // Do nothing if it's already showing. if (dialog.is(':hidden')) { $('<iframe/>', { src: 'newBug.html' }).css({ border: 0, width: '450px', height: '395px' }).appendTo('#dialogContainer'); dialog.fadeIn('fast'); } } }
调用清单 5 中的函数的结果是一个缺陷创建对话框,如 图 2 所示。
图 2. OSLC 3.0 示例应用程序缺陷创建对话框
点击查看大图
关闭 [x]
此刻,填充该表单对上过网的人来说应该是一个简单的操作。但是,在提交时,会出现一些新的语义操作。请仔细查看清单 6。
清单 6. 以 JSON-LD 形式提交错误信息
<script type="text/javascript"> // Our JSON-LD context for creating defects var context = { oslc_cm: "http://open-services.net/ns/cm#", dcterms: "http://purl.org/dc/terms/", Defect: "oslc_cm:Defect", description: "dcterms:description", severity: { "@id": "oslc_cm:severity", "@type": "@id" }, title: "dcterms:title" }; ... function submit() { // Post the form as JSON-LD to the bug container. var bug = { "@id": "", "@type": "Defect", "@context": context, title: $("#title").val(), description: $("#description").val(), severity: $("#severity").val() }; var request = $.ajax({ url: 'r/bugs', data: JSON.stringify(bug), type: 'post', contentType: 'application/ld+json', success: function(data, status, xhr) { var location = xhr.getResponseHeader('Location'); var response = { "oslc:results": [ { "oslc:label": bug.title, "rdf:resource": location } ] }; sendMessage(response); } }); }
来自表单的数据由 JQuery 收集和捕获来生成纯 JSON。如果双方就这些词汇和结构的含义达成一致,那么纯 JSON 没什么问题,但作为一种交互模式,JSON 没有扩展到广泛的合作伙伴。
解释 JSON-LD 的工作原理不属于本文的讨论范围,但您可以进一步了解它。它是一种令人兴奋桥接技术,能够将 Linked Data 和 Web 开发领域联系起来。参见参考资料,获取我介绍的有关 JSON-LD 的网络讲座的链接。
通过坚持使用更丰富的标准,我们可以轻松地与任何理解它们的人共享信息。尽管 JSON 是一种标准,但它没有指定解释所使用的数据结构或关键词的任何途径。回想本系列中的第一篇文章,RDF 有用的原因之一是它使用了一种图形数据结构和(频繁的)全局标识符。在使用这些标准时,无需提前向接收者解释该结构。出于同样的目的,我们可以根据上下文将 JSON 转换为 JSON-LD ,后者支持对 RDF 等定向图结构进行序列化。实际 JSON 不需要更改;我们只需提供一个上下文来解释数据,这就是清单 6 中发生的过程。指定的上下文用于将来自表单的简单词汇映射到 OSLC 词汇表词汇。这个专门形成的 JSON 由容器转换为 RDF,就像它已首先作为 Turtle 而 POST
一样。它可以与 JQuery 等工具进行互操作,这是一个令人兴奋的进步。
此刻,我可以输入一些错误或使用快捷方式,选择图 1中的 Create some? 链接。此快捷方式从虚假的数据生成一些发行股票,如 图 3 所示。真实的缺陷跟踪系统背后会拥有一个更持久的数据库或备用存储,但为了实现学习目的,示例应用程序只需记录提交的缺陷就足够了。
图 3. 包含一些数据的 OSLC 3.0 示例应用程序
点击查看大图
关闭 [x]
图 3 中的每个缺陷都有一个可在浏览器中单击的链接。此刻,如果我单击该链接或将鼠标悬停在该链接上,就会看到缺陷的 HTML 呈现结果,如 图 4 所示。这是 OSLC 3.0 委托对话框 规范的另一个特性。
图 4. 包含数据预览功能的 OSLC 3.0 示例应用程序
点击查看大图
关闭 [x]
但是,这不是简单的 Web 应用程序。该容器还通过我们建立的交互方式(也即 HTTP 请求)向我告知这些错误的存在。在清单 7 中,我可看到存在这些错误。
清单 7. 发现 LDP 中的缺陷资源
> http get http://localhost:8080/oslc3/r/bugs HTTP/1.1 200 OK Accept-Post: text/turtle,application/json,application/json Allow: GET,HEAD,POST,OPTIONS Cache-Control: no-cache Content-Type: text/turtle Date: Mon, 17 Aug 2015 01:42:21 GMT ETag: "a9c13497ed1dd32b4ec2368094c2cc30" Link: <http://www.w3.org/ns/ldp#Resource>; rel="type" Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type" Link: <http://open-services.net/ns/cm#Defect>; rel="http://open-services.net/ns/core#creationType" Link: <http://localhost:8080/oslc3/Defect-shape.ttl>; rel="http://www.w3.org/ns/ldp#constrainedBy" Link: <http://localhost:8080/oslc3/r/bugs/creationDialog>; rel="http://open-services.net/ns/core#creationDialog" Server: Jetty(9.2.2.v20140723) Transfer-Encoding: chunked Vary: Accept,Prefer @base <http://localhost:8080/oslc3/r/bugs> . <> a <http://www.w3.org/ns/ldp#BasicContainer> ; <http://purl.org/dc/terms/title> "Bug Container" ; <http://www.w3.org/ns/ldp#contains> <bugs/4> , <bugs/3> , <bugs/2> , <bugs/1> .
如果我像清单 8 中一样通过资源标识符来请求一个缺陷,那么可以查看它的详细信息。系统的客户端有机会决定它们如何与容器内容交互。它们可以使用所提供的 UI,使用一个基于元数据的自定义接口,或者直接将内容用作面向资源的数据。
清单 8. 抓取单个资源
> http get http://localhost:8080/oslc3/r/bugs/2 HTTP/1.1 200 OK Allow: GET,HEAD,OPTIONS,DELETE Cache-Control: no-cache Content-Type: text/turtle Date: Mon, 17 Aug 2015 02:27:44 GMT ETag: "10337b40b28dae5800f02ee476a315f7" Link: <http://www.w3.org/ns/ldp#Resource>; rel="type" Link: <http://localhost:8080/oslc3/r/bugs/2/compact>; rel="http://open-services.net/ns/core#Compact" Server: Jetty(9.2.2.v20140723) Transfer-Encoding: chunked Vary: Accept,Prefer @base <http://localhost:8080/oslc3/r/bugs/2> . @prefix <http://www.w3.org/2001/XMLSchema#> <> a <http://open-services.net/ns/cm#Defect> ; <http://open-services.net/ns/cm#severity> <http://open-services.net/ns/cm#Normal> ; <http://purl.org/dc/terms/created> "2015-08-15T06:02:28.772Z"^^xsd:dateTime ; <http://purl.org/dc/terms/description> "I thought we wanted the UI to look really blue? What happened?" ; <http://purl.org/dc/terms/identifier> "2" ; <http://purl.org/dc/terms/title> "Product Z isn't blue enough." .
容器拥有其内容的可发现的链接。每个资源都可以单独寻址。我通常不希望迭代每个结果来查找我寻找的东西。因此,示例应用程序对 SPARQL 的支持很方便 — 不是一种成熟的 SPARQL 协议实现,但我会在下一节中解决该问题。就目前而言,如果我在示例应用程序中选择 SPARQL Endpoint 链接,我会跳转到 图 5 所示的页面。该页面包含一个查询输入框,一个提交查询的按钮,以及一个显示结果的空间。
图 5. OSLC 3.0 示例应用程序 SPARQL 端点
点击查看大图
关闭 [x]
使用 SPARQL UI 检索所有缺陷的列表,并不比通过 LDP 容器直接抓取结果好多少。我希望能够询问特定的问题。在 图 6 中,我展示了询问具有一种特定严重级别的缺陷的信息的结果。
图 6. OSLC 3.0 示例应用程序 SPARQL 结果
点击查看大图
关闭 [x]
在这个阶段,我展示了一个使用面向 Web 的标准表达的功能性(但高度简化)的缺陷跟踪系统。该系统使用了基于标准的标识符、一个标准数据模型、标准查询机制、甚至标准 UI 元素来收集和显示特定于领域的内容。这些都是松散耦合、面向资源的系统开发中的重要进步。
“ 任何理解这些标准和 OSLC 词汇表词汇的工具现在都可以与此容器进行交互。 ”
您能够访问从 GitHub 检索的代码中的实现,但该实现的任何部分都不是本讨论中的重点。任何理解这些标准和 OSLC 词汇表词汇的工具现在都可以与此容器进行交互。要生成可被使用或使用已生成的内容的内容,必须具有一些专业知识。一个工具可原生地支持这些标准,或者拥有某种类型的适配器来包装其现有的 API 和存储机制,以便生成合适的内容。
此过程可对 OSLC 技术委员会的其他各种纵向类别进行重复,而且这种情况离不开优秀的集成案例。这些工具可预测且可互操作。不仅任意问题跟踪系统可连接到任意测试结果报告系统、需求系统等;还可以将任意附加信息插入到标准 OSLC 词汇表。在本系列中可以看到,来自 FOAF 、 Dublin Core 、 VoID 甚至自定义词汇表的词汇可轻松地插入。
任何来自其他词汇表的其他信息可包含在我们查找相关信息的 SPARQL 查询中。使用 FOAF 词汇,可以捕获安排来修复缺陷的各个开发人员的身份和联系信息。不需要任何新数据存储或模式接受这些新细节,这显然在这种系统中很有用。一些新功能不断出现,比如 “为我找到负责此错误的人” 或 “获取所有处理分配给此冲刺的任务的开发人员的电子邮件地址,提醒他们星期四代码会冻结”。
但是,处理 Linked Data 只是开始,不是终点。正如我在最后一节中展示的,使用我已展示的技术在现有系统上堆叠更多新特性很简单。
回页首
采用这种基于标准、面向资源的思维会带来新的机会。重要的概念具有稳定的标识符,可以通过内容协商,自由地采取各种形式。随着新表示形式变得 流行 ,系统也可以发生演变。
一个特定词汇表中使用的词汇也可转换为来自其他来源或对其他客户端有意义的其他词汇。图表的元素可以定义新的、还未定义的概念。示例应用程序没有提供全功能的 SPARQL 实现。它不支持 SPARQL 协议或对它发出 CONSTRUCT
查询的能力。目前为止,它只支持 SELECT
查询。
添加此支持并不是不可能,但我们暂时不需要它。我们有能力提取数据,并将它导出到另一个具有该支持的工具(比如 Stardog 、 Virtuoso 或 Apache TDB )。借助更强大的 SPARQL 引擎,我们可以运行查询并将结果添加到我们对世界的理解中,从而创建和扩展该数据模型。
例如,构成最高优先级缺陷的元素在项目的生命周期中可能会不断变化。当团队研发一个最小可行性产品 (MVP) 版本时,任何阻止进步的东西都可能是要解决的最关键问题。随后,影响某个特定系统的缺陷,资助特定工作的客户,或者待解决缺陷的其他任何潜在观察,都可能改变开发人员要执行的工作。敏捷工具和实践有助于管理不断变化的优先级,但能够实时地重新定义数据也是一个不错的能力。强大的推理系统可简化此功能,但简单的 SPARQL 构造查询也一样,比如清单 9 中的示例。
清单 9. 通过 SPARQL 重组数据
PREFIX oslc_cm: <http://open-services.net/ns/cm#> PREFIX ex: <http://example.com/ns/> CONSTRUCT { ?s a ex:HighestPriority } WHERE { ?s a oslc_cm:Defect ; oslc_cm:severity oslc_cm:Blocker . }
CONSTRUCT
查询创建了一个新语句,根据图形模式来识别哪些缺陷将被视为具有最高优先级。在本例中,任何具有 Blocker
状态的缺陷都符合条件。每位开发人员的结果可能有所不同。新规则仅通过使用不同的查询就能改变优先级的定义,无需使用任何类型的自定义代码。因为该模型没有将数据与元数据分离,所以该图形的任何部分都可用于定义规则。因为来自任何领域的数据的任何方面都可以合并,所以潜在的威力和灵活性应该很明显。
即使没有详细的三元存储或对 SPARQL 的全面支持,我也可以从示例应用程序的虚假数据中提取数据,并使用来自 Jena API 的标准 SPARQL 命令行工具对现有数据运行查询:
> sparql --data 1.ttl --data 2.ttl --data 3.ttl --data 4.ttl --query sparql/construct.rq @prefix ex: <http://example.com/ns/> . @prefix oslc_cm: <http://open-services.net/ns/cm#> . <http://localhost:8080/oslc3/r/bugs/3> a ex:HighestPriority .
我可以在这里看到,这个可重用的工具(它对所讨论的领域一无所知)能够根据手头的定义,将编号为 3
的错误识别为 HighestPriority
错误。如果示例应用程序的 SPARQL 支持得到了扩展,任何外部工具都可以根据一个编码到查询中的任意外部上下文来查找内容。添加对 SPARQL 协议和 CONSTRUCT
表单的支持,这会使得任何工具或客户端都能完成一些操作,比如:
PREFIX ex: <http://example.com/ns/> SELECT ?defect FROM <http://localhost:8080/oslc3/sparql?query=PREFIX%20oslc_cm%3A%20%3Chttp%3A%2F / %2Fopen-services.net%2Fns%2Fcm%23%3E%0APREFIX%20ex%3A%20%3Chttp%3A%2F%2F / example.com%2Fns%2F%3E%0A%0ACONSTRUCT%20%7B%0A%20%20%20%3Fs%20a%20ex%3A / HighestPriority%0A%7D%20WHERE%20%7B%0A%20%20%20%3Fs%20a%20oslc_cm%3A / Defect%20%3B%0A%20%20%20%20%20oslc_cm%3Aseverity%20oslc_cm%3ABlocker / %20.%0A%7D%0A> WHERE { ?defect a ex:HighestPriority . }
在此场景中,该工具动态地重组示例数据的内容,并使用之前的 CONSTRUCT
查询来检索结果。它采用了 URL 编码并将它传递给(目前不存在的) SPARQL 协议。
作为另一个基于面向资源的 Linked Data 的示例,很容易想象这样一种场景,其中一个在线协作工具可扩展来融合到有关软件开发流程的对话中,用于讨论各种问题。使用 RDFa 或 HTML5 Microdata 等技术,捕获对话的 Web 应用程序可编码对话的 RDF 表示。显示该对话的 HTML 文档的结构,这包含任何知晓标准 RDFa 或 HTML5 Microdata 的工具可提取到 Turtle 中的元数据,如清单 10 所示。
清单 10. 提取有关缺陷的对话
PREFIX oslc: <http://open-services.net/ns/core#> PREFIX dcterms: <http://purl.org/dc/terms/> PREFIX : <http://example.com/discussion#> :discussion1 a oslc:Discussion ; oslc:discussionAbout <http://localhost:8080/oslc3/r/bugs/4> ; oslc:comment :comment1, :comment2, :comment3, :comment4 . :comment1 a oslc:Comment ; dcterms:created "2015-08-01T10:59:25.291Z" ; dcterms:creator <http://example.com/people/bob> ; dcterms:description "I think that was Eric's doing." ; dcterms:title "Uhm..." . :comment2 a oslc:Comment ; dcterms:created "2015-08-01T11:02:19.090Z" ; dcterms:creator <http://example.com/people/eric> ; dcterms:description "Are you kidding? No way!" ; dcterms:title "Re: Uhm..." ; oslc:inReplyTo :comment1 . :comment3 a oslc:Comment ; dcterms:created "2015-08-01T11:15:44.333Z" ; dcterms:creator <http://example.com/people/bob> ; dcterms:description "Here's the GitHub commit: <...>" ; dcterms:title "Evidence" ; oslc:inReplyTo :comment2 . :comment4 a oslc:Comment ; dcterms:created "2015-08-01T12:20:54.102Z" ; dcterms:creator <http://example.com/people/eric> ; dcterms:description "Oops. My bad."; dcterms:title "Re: Evidence" ; oslc:inReplyTo :comment3 .
这不仅可以是一种分类、优先化和分配工作的机制, 缺少 这些讨论也会成为一个重要的数据点。SPARQL 查询很容易要求查找所有没有任何相关讨论的缺陷。很容易在图形中找到与某些模式不匹配的部分,就像查找匹配的部分一样。这可能是一个项目上确认已执行合适的估算的关键活动。如果没有人讨论该问题,您可能不相信附加到它之上的数字。
这里的重点是,管理对话的代码仅通过数据与问题跟踪软件具有微弱的链接,但它们的集成能获得宝贵的新特性。我希望现在很容易想象只需极少的工作即可集成构建软件所涉及的所有潜在工具,用这些工具带来增值。
回页首
“ 以专为共享信息而设计的一组标准为基础,显然是许多不同领域的一种制胜战略,比如管理各种跨越跨众多工具、合作伙伴和涉众的工程学科的工件。 ”
我不知道在新的管理人指引下,OSLC 的未来会怎样。显然 OSLC 3.0 规范需要最终确定,需要修改更多工具来支持新方法。许多有关可以或应该在 2.0 和 3.0 版规范之间保留何种兼容性的讨论正在进行当中。围绕语言级 API 构建的客户端应用程序可能不会受更改影响,而且在 REST 和 RDF 级别上工作的应用程序应该不是太难迁移。
这些是新标准和新兴标准,它们所基于的许多技术也是相同的。不是每个人都理解它们或青睐它们带来的结果。幸运的是, Linked Data 项目 等计划注重各个小组跨任意领域来共享和集成信息的规模和效率。
我希望我在本系列中已经证明,以一组专为共享信息而设计的标准为基础对各种不同领域显然是一种制胜战略 — 比如管理各种跨越跨众多工具、合作伙伴和涉众的工程学科的工件。尝试使用严格的数据库模式或临时的键值文档来这么做,将会让复杂度提高几个等级,而且让成功的可能性变得更低。
OSLC 项目已宣布在新的领域采用这些标准,实现它们的设计目的。我希望您已经看到,它们可能对您经历的其他任何集成工作同样有用。