本文简单介绍Jena(Jena 2.4),使用Protégé 3.1(不是最新版本)创建一个简单的生物(Creature)本体,然后参照Jena文档中的一个例子对本体进行简单的处理,输出本体中的Class、Property等信息。
本文内容安排如下:
Ø 介绍Jena
Ø 运行Jena
Ø Jena On
Ø 例子
Ø 参考资料
一、介绍Jena
Jena由 HP Labs(http://www.hpl.hp.com)开发的Java开发工具包, 用于Semantic Web(语义网)中的应用程序开发;Jana是开源的,在下载的文档中有Jena的完整代码。Jena框架主要包括:
a) 以RDF/XML、三元组形式读写RDF
资源描述框架是(RDF)是描述资源的一项标准(在技术上是W3C的推荐标准),Jena文档中有一部分呢详细介绍了RDF和Jena RDF API,其内容包括对Jena RDF包的介绍、RDF模型的创建、读写、查询等操作,以及RDF容器等的讨论。
b) RDFS,OWL,DAML+OIL等本体的操作
Jena框架包含一个本体子系统(On
c) 利用数据库保存数据
Jena 2允许将数据存储到硬盘中,或者是OWL文件,或者是关系数据库中。本文处理的本体就是OWL文件读入的。
d) 查询模型
Jena 2提供了ARQ查询引擎,它实现SPARQL查询语言和RDQL,从而支持对模型的查询。另外,查询引擎与关系数据库相关联,这使得查询存储在关系数据库中的本体时能够达到更高的效率。
e) 基于规则的推理
Jena 2支持基于规则的简单推理,其推理机制支持将推理器(inference reasoners)导入Jena,创建模型时将推理器与模型关联以实现推理。
Protégé是一个开源的本体编辑器(目前的版本是Protégé 3.2),用户可以在GUI环境下创建本体或者知识库。有一种说法是:Jena对应用程序就像Protégé对我们——我们使用Protégé操作本体,应用程序则是使用Jena来做同样的工作。当然这些应用程序还是得由我们来编写。
二、运行Jena
可以在Jena的主页(http://jena.sourceforge.net/downloads.html)下载Jena的最新版本,目前是Jena2.4版本。Jena是Java API,所以需要Java运行环境。本文使用的是jdk1.5.0_04和Eclipse3.2。
将下载的Jena-2.4.zip解压到任意路径,解压之后生成Jena2.4文件夹,将Jena2.4\lib下的jar文件全部加入CLASSPATH,这样就可以在任意的Java编辑器中调用Jena API了。在解压目录下有一个test.bat文件,用于配置的测试。在控制台运行此程序,如果你的配置正确,测试将顺利完成。
如果使用Eclipse,则可以通过修改工程的Java创建路径的方法导入Jena jar文件。在Eclipse下创建Java工程,右健单击工程名字,选择“属性/Properties”,在打开的对话框中选择“Java创建路径/Java Build Path”,在右边标签中选择“库/Libraries”,之后选择“添加外部文件/Add Extenal JARs”,找到Jena2.4\lib目录下的所有jar文件并将其添加到工程。这样就可以运行Jean文档中的例子了。
三、Jena On
Jena2.4的On
在语义网上有很多表示本体信息的本体语言,其中表达能力最强的是OWL,OWL按复杂程度分为 OWL Full、OWL DL和OWL Lite三个版本。其他的本体语言还有RDFS、DAML+OIL。Jena On
Jena提供的接口本质上都是Java程序,也就是.java文件经过javac之后生成的.class文件。显然,class文件并不能提示本体创建使用的语言。为了区别于其他的表示方法,每种本体语言都有一个自己的框架(pro
在Jena中,这种框架通过参数的设置在创建时与本体模型(On
本部分简单介绍要用到的几个java类或者接口。
1.本体模型On
本体模型(On
On
该语句不含参数,应用默认设置创建一个本体模型on
On
更多类型设置可以参照On
我们所使用的本体是从OWL文件获得的,也就是说,是从磁盘读取的。读取的方法是调用Jena On
on
就是读取位于D盘相应目录下的Creature.owl文件以建立本体模型。Read方法也有很多重载,上面调用的方法以文件的绝对路径作为参数。其他的方法声明如下
read( String url );
read( Reader reader, String base );
read( InputStream reader, String base );
read( String url, String lang );
read( Reader reader, String base, String Lang );
read( InputStream reader, String base, String Lang );
2.文档管理器Document manager
本体文档管理器(On
下面的例子创建一个文档管理器并将它与以创建的本体模型关联。
On
On
3.接口On
这个接口中定义了本体种与概念(也就是类Class)相关的操作,通过On
listClasses()
便可以返回模型中的所有概念组成的迭代器(Iterator),然后调用On
第四部分的例子主要是应用这个类的方法。
4.基本本体类型On
所有本体API中用于表示本体的类继承自On
四、例子
本文实现了一个简单的例子。通过Protégé 3.1创建一个Creature本体,并将其存储到OWL文件Creature.owl,然后使用和Jena通过读取该文件创建本体模型,实践Jena中的一些On
本体类层次图
例子的主要代码如下列出。
// 创建使用OWL语言的内存模型
On
on
// 定义一个类作为模型中Animal类的等等价类,并添加注释
On
cls.addComment("the EquivalentClass of Animal...", "EN");
// 通过完整的URI取得模型中的Animal类
On
getOntClass("http://www.owl-on
oc.addEquivalentClass(cls); // 将先前定义的类添加为Animal的等价类
// 迭代显示模型中的类,在迭代过程中完成各种操作
for (Iterator i = on
On
if (!c.isAnon()) { // 如果不是匿名类,则打印类的名字
System.out.print("Class");
// 获取类的URI并输出,在输出时对URI做了简化(将命名空间前缀省略)
System.out.println(c.getModel().getGraph().
getPrefixMapping().shortForm(c.getURI()));
// 处理Animal类
if (c.getLocalName().equals("Animal")) { // 如果当前类是Animal
System.out.println(" URI@" + c.getURI()); // 输出它的完整URI // 取得它的的等价类并打印
System.out.print(" Animal's EquivalentClass is "+
c.getEquivalentClass());
// 输出等价类的注释
System.out.println(" [comments:" +
c.getEquivalentClass().getComment("EN")+"]");
}// 处理Animal结束
// 迭代显示当前类的直接父类
for (Iterator it = c.listSuperClasses(); it.hasNext();)
{
On
String str = c.getModel().getGraph()
.getPrefixMapping().shortForm(c.getURI()) // 获取URI
+ "'s superClass is " ;
String strSP = sp.getURI();
try{ // 另一种简化处理URI的方法
str = str + ":" + strSP.substring(strSP.indexOf('#')+1);
System.out.println(" Class" +str);
}catch( Exception e ){}
} // super class ends
// 迭代显示当前类的直接子类
for (Iterator it = c.listSubClasses(); it.hasNext();){
System.out.print(" Class");
On
System.out.println(c.getModel().getGraph().getPrefixMapping()
.shortForm(c.getURI())+ "'s suberClass is "
+ sb.getModel().getGraph().getPrefixMapping()
.shortForm(sb.getURI()));
}// suber class ends
// 迭代显示与当前类相关的所有属性
for(Iterator ipp = c.listDeclaredProperties(); ipp.hasNext();){
On
System.out.println(" associated property: " + p.getLocalName());
}// property ends
}// anonymity ends
else // 是匿名类
{}
}// for ends
部分输出结果如下,说明部分不在输出中。
Class:Animal
URI@http://www.owl-on
// 等价类及其注释
Animal's EquivalentClass is :DongwuClass [comments:the EquivalentClass of Animal...] Class:Animal's superClass is :Creature // 直接父类
Class:Animal's suberClass is :MixAnimal // 直接子类
Class:Animal's suberClass is :GrassAnimal
Class:Animal's suberClass is :MeatAnimal
associated property: eat // 关联属性
associated property: beEated
associated property: mainEat
后注:该例子没有涉及Jena的推理功能,没有实现属性的过滤(只返回以当前类为主体的属性),不能输出间接父类(父类的父类)或间接子类,等等。因此,有待对Jena进一步熟悉之后作更多的改进。
五、参考资料
[1] \\Jena-2.4\doc\on
[2] \\Jena-2.4\doc\javadoc Jena 2 Java文档
[3] \\Jena-2.4\src-examples\jena\examples\on
[4] http://www.chengtao.name/modules/wordpress 维基博客
[5] iMarine http://iMarine.blog.163.com
源代码:
imp
imp
public class MyOntology
{
public static void main(String[] args) {
// 创建本体模型
On
on
// 定义一个类作为模型中Animal类的等等价类,并添加注释
On
cls.addComment("the EquivalentClass of Animal...", "EN");
On
oc.addEquivalentClass(cls); // 将先前定义的类添加为Animal的等价类
// 迭代显示模型中的类
for (Iterator i = on
On
if (!c.isAnon()) { // 如果不是匿名类
System.out.print("Class");
// 获取类的URI并输出,在输出时对URI做了简化(将命名空间前缀省略)
System.out.println(c.getModel().getGraph().getPrefixMapping().shortForm(c.getURI()));
// 处理Animal类
if (c.getLocalName().equals("Animal")) { // 如果当前类是Animal
System.out.println(" URI@" + c.getURI()); // 输出它的完整URI
// 取得特定类的等价类
System.out.print(" Animal's EquivalentClass is "+ c.getEquivalentClass());
// 输出等价类的注释
System.out.println(" [comments:" + c.getEquivalentClass().getComment("EN")+"]");
}
// 迭代显示当前类的父类
for (Iterator it = c.listSuperClasses(); it.hasNext();)
{
On
String str = c.getModel().getGraph()
.getPrefixMapping().shortForm(c.getURI()) // 获取URI
+ "'s superClass is " ;
String strSP = sp.getURI();
try{ // 另一种简化处理URI的方法
str = str + ":" + strSP.substring(strSP.indexOf('#')+1);
System.out.println(" Class" +str);
}
catch( Exception e ){
}
}
// 迭代显示当前类的子类
for (Iterator it = c.listSubClasses(); it.hasNext();)
{
System.out.print(" Class");
On
System.out.println(c.getModel().getGraph().getPrefixMapping()
.shortForm(c.getURI())
+ "'s suberClass is "
+ sb.getModel().getGraph().getPrefixMapping()
.shortForm(sb.getURI()));
}
// 迭代显示与当前类相关的所有属性
for(Iterator ipp = c.listDeclaredProperties(); ipp.hasNext();)
{
On
System.out.println(" associated property: " + p.getLocalName());
}
}
}
}
}
/**************************************