Jena语义Web开发101
2015/05/28更新 代码在 https://github.com/zhoujiagen/semanticWebTutorialUsingJena
前言
该手册参考和扩展“Hebeler J, Fisher M, et al.Web 3.0与Semantic Web编程[M]. 清华大学出版社, 北京.2010.”中的HelloWorld。
在描述中,不将Web本体与描述逻辑的术语做区分,尽量采用Web本体的英文表述,下面列出Web本体与描述逻辑的术语对应关系:
| Web本体 | 描述逻辑 |
| Class | Concept |
|
Property Object Property Data Property |
Role |
| Individual | Instance |
计划记录类容:
1 Jena RDF API使用
2 用SPARQL做RDF navigate
3 手动本体对准(ontology alignment)
4 Jena OWL推理(Inference)
5 Jena Rule推理
内容
0 数据!数据!数据!
数据准备思路:将TBox与ABox分开,两个本体(TBox1, ABox1, TBox2, ABox2),其中ABox1与TBox1的命名空间不同,ABox2与TBox2的命名空间相同。
TBox1:FOAF的规范(http://xmlns.com/foaf/spec/)
ABox1:生成自FOAF数据的链接(http://www.ldodds.com/foaf/foaf-a-matic)
TBox2, ABox2: 如何用Protege建立本体(http://protegewiki.stanford.edu/wiki/Ontology101, http://130.88.198.11/tutorials/protegeowltutorial/),话外Protege官网现在变得好炫.
1 Jena RDF API使用
这里只涉及如何用RDF文件填充Model,code sketch如下:
Model model = ModelFactory.createDefaultModel();
InputStream is = FileManager.get().open("E:/码农的世界/码农的自我修养/semantic web/workspace/foafData.rdf");
model.read(is, "http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl");
is.close();
2 用SPARQL做RDF navigate
SPARQL的全称是SPARQL Protocol and RDF Query Language,既是一个定义如何执行RDF查询、更新操作的协议,也是一个RDF查询语言。
Jena中的Graph抽象比较好,这是个类似于关系型数据库中视图的概念,只是Graph中基础的数据结构是形如<Subject, Predicate, Object>的Triple,SPARQL作为查询语言,就是在Graph中Triple中定位和导航数据。
Jena ARQ API的code sketch如下:
//组装查询字符串StringBuilder sb = new StringBuilder();
sb.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>").append(NEWLINE).append("PREFIX owl: <http://www.w3.org/2002/07/owl#>")
.append(NEWLINE).append("PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>").append(NEWLINE)
.append("PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>").append(NEWLINE).append("PREFIX foaf: <http://xmlns.com/foaf/0.1/>")
.append(NEWLINE).append("PREFIX myfoaf: <http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#>").append(NEWLINE)
.append("PREFIX people: <http://www.people.com#>").append(NEWLINE);
sb.append("SELECT DISTINCT ?name").append(NEWLINE).append("WHERE { myfoaf:me foaf:name ?name}").append(NEWLINE);
//执行查询
sparql(model, sb.toString(), "?name");
private static void sparql(Model model, String query, String field) {
Query q = QueryFactory.create(query);
QueryExecution qexec = QueryExecutionFactory.create(q, model);
System.out.println("Plan to run SPARQL query: ");
System.out.println(BOUNDARY);
System.out.println(query);
System.out.println(BOUNDARY);
ResultSet rs = qexec.execSelect();
while (rs.hasNext()) {
QuerySolution qs = rs.nextSolution();
RDFNode name = qs.get(field);// 暂用RDFNode
if (name != null) {
System.out.println("Hello to " + name);
} else {
System.out.println("No friends found!");
}
}
qexec.close();
}
3 手动本体对准(ontology alignment)
这个例子涉及4个对准:
两个命名空间中的Class等价、两个命名空间中Property等价、两个命名空间中Property蕴涵和两个命名空间中Individual等价(异名同义)。
下图中红色箭头表示本体对准关系,没有展示Property之间的对准关系(该图用Graphviz手工生成,自动生成在下一步的计划中):

本体对准code sketch如下,其中Model shema仅加载两个本体的TBox:
// [1]people:Individual = foaf:Person
Resource resource = schema.createResource(PEOPLE_NS + "#Individual");
Property property = schema.createProperty(OWL_URL + "equivalentClass");
Resource object = schema.createResource(FOAF_URL + "Person");
schema.add(resource, property, object);
// [2]people:hasName = foaf:name
resource = schema.createResource(PEOPLE_NS + "#hasName");
property = schema.createProperty(OWL_URL + "equivalentProperty");
object = schema.createResource(FOAF_URL + "name");
schema.add(resource, property, object);
// [3]people:hasFriend < foaf:knows
resource = schema.createResource(PEOPLE_NS + "#hasFriend");
property = schema.createProperty(RDFS_URL + "subPropertyOf");
object = schema.createResource(FOAF_URL + "knows");
schema.add(resource, property, object);
// [4]myfoaf:me = people:individual_5
resource = schema.createResource(MYFOAF_NS + "#me");
property = schema.createProperty(OWL_URL + "sameAs");
object = schema.createResource(PEOPLE_NS + "#individual_5");
schema.add(resource, property, object);
4 Jena OWL推理(Inference)
下表是OWL支持的推理形式的概要:
OWL构造/描述逻辑支持的推理
|
语义构造 |
推理规则 |
|
概念包含 |
C ⊑ D ∧ C(a) ⇒ D(a) |
|
概念互斥 |
C ⊓ D ⊑ ⊥ ∧ C(a) ∧ D(b) ⇒ a≉ b |
|
关系包含 |
R ⊑ S ∧ R(a, b) ⇒ S(a, b) |
|
关系定义域 |
domain(R, C) ∧ R(a, b) ⇒ C(a) |
|
关系值域 |
range(R, C) ∧ R(a, b) ⇒ C(b) |
|
自反关系 |
R ⊑ id(C) ⇒ R(a, a) |
|
传递关系 |
R+(a, b) ∧ R+(b, c) ⇒ R+(a, c) |
|
对称关系 |
R ≡ R⁻∧ R(a, b) ⇒ R(b, a) |
|
关系组合 |
R ∘ S ⊑ R ′∧ R(a, b) ∧ S(b, c) ⇒ R′(a, c) |
|
互逆关系 |
R(a, b) ⇒ R⁻(a, b) R⁻(a, b) ⇒ R(a, b) |
|
函数关系 |
Rf(a, b) ∧ Rf(a, c) ⇒ b≈ c |
|
键 |
HasKey(C, R)∧ C(a) ∧ C(b) ∧ R(a, c) ∧ R(b, c) ⇒ b≈ c |
Jena API关于OWL推理的基本策略是用Reasoner绑定TBox,在代表ABox的Model对象基础上创建出推理后模型IntModel对象。
code sketch如下:
InfModel inferredModel = null; Reasoner reasoner = ReasonerRegistry.getOWLReasoner(); reasoner = reasoner.bindSchema(schema);// tbox inferredModel = ModelFactory.createInfModel(reasoner, friendsModel);// abox
5 Jena Rule推理
尽管语义Web事实上的规则语言标准是SWRL,但Jena提供了自己的规则语言,一些值得关注的特性是Jena规则支持前向推理和后向推理、可以动态生成匿名节点。
使用Jena Rule执行推理的code sketch如下:
String rule = "[gmailFriend: (?person <http://xmlns.com/foaf/0.1/mbox_sha1sum> ?email), strConcat(?email, ?lit), regex(?lit, '(.*gmail.com)')"
+ "-> (?person " + RDF_TYPE + " <http://www.people.com#GmailPerson>)]";
Reasoner ruleReasoner = new GenericRuleReasoner(Rule.parseRules(rule));
ruleReasoner = ruleReasoner.bindSchema(schema);
inferredModel = ModelFactory.createInfModel(ruleReasoner, friendsModel);
6 总结
本手册记录了Jena如何加载RDF文件填充Model、如何用SPARQL导航Model、如何执行OWL和Jena Rule推理,也简单介绍了本体对准。
数据
foafSchema.rdf (NS=http://xmlns.com/foaf/0.1/)
下载链接为http://xmlns.com/foaf/spec/index.rdf,将其重名为foafSchema.rdf。
foafData.rdf (NS=http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl)
<?xml version="1.0"?>
<!DOCTYPE rdf:RDF [
<!ENTITY foaf "http://xmlns.com/foaf/0.1/" >
<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
<!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
]>
<rdf:RDF xmlns="http://www.w3.org/2002/07/owl#"
xml:base="http://www.w3.org/2002/07/owl"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<Ontology rdf:about="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl">
<imports rdf:resource="http://xmlns.com/foaf/0.1/"/>
</Ontology>
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Annotation properties
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<AnnotationProperty rdf:about="&foaf;givenname"/>
<AnnotationProperty rdf:about="&foaf;mbox_sha1sum"/>
<AnnotationProperty rdf:about="&foaf;nick"/>
<AnnotationProperty rdf:about="&foaf;homepage"/>
<AnnotationProperty rdf:about="&foaf;depiction"/>
<AnnotationProperty rdf:about="&foaf;title"/>
<AnnotationProperty rdf:about="&foaf;workInfoHomepage"/>
<AnnotationProperty rdf:about="&foaf;workplaceHomepage"/>
<AnnotationProperty rdf:about="&foaf;family_name"/>
<AnnotationProperty rdf:about="&foaf;knows"/>
<AnnotationProperty rdf:about="&foaf;schoolHomepage"/>
<AnnotationProperty rdf:about="&foaf;phone"/>
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Datatypes
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Individuals
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!-- http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#Ontology -->
<NamedIndividual rdf:about="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#Ontology">
<rdf:type rdf:resource="http://schema.org/Person"/>
<foaf:name rdf:datatype="&xsd;string">I. M. Ontology</foaf:name>
<rdfs:seeAlso rdf:datatype="&xsd;string">http://ont.com</rdfs:seeAlso>
<foaf:mbox_sha1sum rdf:datatype="&xsd;string">mailto:ont@gmail.com</foaf:mbox_sha1sum>
</NamedIndividual>
<!-- http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#Reasoner -->
<NamedIndividual rdf:about="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#Reasoner">
<rdf:type rdf:resource="http://schema.org/Person"/>
<foaf:name rdf:datatype="&xsd;string">Ican Reason</foaf:name>
<rdfs:seeAlso rdf:datatype="&xsd;string">http://reasoner.com</rdfs:seeAlso>
<foaf:mbox_sha1sum rdf:datatype="&xsd;string">maillto:reason@hotmail.com</foaf:mbox_sha1sum>
</NamedIndividual>
<!-- http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#Statement -->
<NamedIndividual rdf:about="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#Statement">
<rdf:type rdf:resource="http://schema.org/Person"/>
<foaf:name rdf:datatype="&xsd;string">Makea Statement</foaf:name>
<rdfs:seeAlso rdf:datatype="&xsd;string">http://statement.com</rdfs:seeAlso>
<foaf:mbox_sha1sum rdf:datatype="&xsd;string">mailto:mstatement@gmail.com</foaf:mbox_sha1sum>
</NamedIndividual>
<!-- http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://blog.sina.com.cn/zhoujiagenontology -->
<NamedIndividual rdf:about="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://blog.sina.com.cn/zhoujiagenontology"/>
<!-- http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://s8.sinaimg.cn/mw690/002RJaAlty6FSYutTO777&690 -->
<NamedIndividual rdf:about="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://s8.sinaimg.cn/mw690/002RJaAlty6FSYutTO777&690">
<rdf:type rdf:resource="&foaf;Image"/>
</NamedIndividual>
<!-- http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://www.cqu.edu.cn/ -->
<NamedIndividual rdf:about="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://www.cqu.edu.cn/"/>
<!-- http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://www.founderinternational.com/ -->
<NamedIndividual rdf:about="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://www.founderinternational.com/"/>
<!-- http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#me -->
<NamedIndividual rdf:about="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#me">
<rdf:type rdf:resource="http://schema.org/Person"/>
<foaf:givenname rdf:datatype="&xsd;string">Semantic</foaf:givenname>
<foaf:name rdf:datatype="&xsd;string">Semantic Web</foaf:name>
<foaf:family_name rdf:datatype="&xsd;string">Web</foaf:family_name>
<foaf:nick rdf:datatype="&xsd;string">Webby</foaf:nick>
<foaf:title rdf:datatype="&xsd;string">master</foaf:title>
<foaf:mbox_sha1sum rdf:datatype="&xsd;string">zhoujiagen@gmail.com</foaf:mbox_sha1sum>
<foaf:knows rdf:resource="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#Ontology"/>
<foaf:knows rdf:resource="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#Reasoner"/>
<foaf:knows rdf:resource="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#Statement"/>
<foaf:homepage rdf:resource="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://blog.sina.com.cn/zhoujiagenontology"/>
<foaf:depiction rdf:resource="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://s8.sinaimg.cn/mw690/002RJaAlty6FSYutTO777&690"/>
<foaf:schoolHomepage rdf:resource="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://www.cqu.edu.cn/"/>
<foaf:workplaceHomepage rdf:resource="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://www.founderinternational.com/"/>
<foaf:workInfoHomepage rdf:resource="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#http://www.founderinternational.com/"/>
<foaf:phone rdf:resource="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#tel:13552854032"/>
</NamedIndividual>
<!-- http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#tel:13552854032 -->
<NamedIndividual rdf:about="http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#tel:13552854032"/>
</rdf:RDF>
<!-- Generated by the OWL API (version 3.2.5.1912) http://owlapi.sourceforge.net -->
peopleSchema.rdf (NS=http://www.people.com)
<?xml version="1.0"?>
<!DOCTYPE rdf:RDF [
<!ENTITY owl "http://www.w3.org/2002/07/owl#" >
<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
<!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
]>
<rdf:RDF xmlns="http://www.people.com#"
xml:base="http://www.people.com"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<owl:Ontology rdf:about="http://www.people.com"/>
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Datatypes
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Object Properties
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!-- http://www.people.com#hasFriend -->
<owl:ObjectProperty rdf:about="http://www.people.com#hasFriend">
<rdfs:range rdf:resource="http://www.people.com#Individual"/>
<rdfs:domain rdf:resource="http://www.people.com#Individual"/>
</owl:ObjectProperty>
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Data properties
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!-- http://www.people.com#hasName -->
<owl:DatatypeProperty rdf:about="http://www.people.com#hasName">
<rdfs:domain rdf:resource="http://www.people.com#Individual"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Classes
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!-- http://www.people.com#GmailPerson -->
<owl:Class rdf:about="http://www.people.com#GmailPerson">
<rdfs:subClassOf rdf:resource="http://www.people.com#Individual"/>
</owl:Class>
<!-- http://www.people.com#Individual -->
<owl:Class rdf:about="http://www.people.com#Individual"/>
</rdf:RDF>
<!-- Generated by the OWL API (version 3.2.5.1912) http://owlapi.sourceforge.net -->
peopleData.rdf (NS=http://www.people.com)
<?xml version="1.0"?>
<!DOCTYPE rdf:RDF [
<!ENTITY www "http://www.people.com#" >
<!ENTITY owl "http://www.w3.org/2002/07/owl#" >
<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
<!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
]>
<rdf:RDF xmlns="http://www.people.com#"
xml:base="http://www.people.com"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:www="http://www.people.com#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<owl:Ontology rdf:about="http://www.people.com"/>
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Datatypes
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Object Properties
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!-- http://www.people.com#hasFriend -->
<owl:ObjectProperty rdf:about="&www;hasFriend">
<rdfs:range rdf:resource="&www;Individual"/>
<rdfs:domain rdf:resource="&www;Individual"/>
</owl:ObjectProperty>
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Data properties
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!-- http://www.people.com#hasName -->
<owl:DatatypeProperty rdf:about="&www;hasName">
<rdfs:domain rdf:resource="&www;Individual"/>
<rdfs:range rdf:resource="&xsd;string"/>
</owl:DatatypeProperty>
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Classes
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!-- http://www.people.com#GmailPerson -->
<owl:Class rdf:about="&www;GmailPerson">
<rdfs:subClassOf rdf:resource="&www;Individual"/>
</owl:Class>
<!-- http://www.people.com#Individual -->
<owl:Class rdf:about="&www;Individual"/>
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Individuals
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!-- http://www.people.com#individual_5 -->
<owl:NamedIndividual rdf:about="&www;individual_5">
<rdf:type rdf:resource="&www;Individual"/>
<hasName rdf:datatype="&xsd;string">Sem Web</hasName>
<hasFriend rdf:resource="&www;individual_6"/>
<hasFriend rdf:resource="&www;individual_7"/>
</owl:NamedIndividual>
<!-- http://www.people.com#individual_6 -->
<owl:NamedIndividual rdf:about="&www;individual_6">
<rdf:type rdf:resource="&www;Individual"/>
<hasName rdf:datatype="&xsd;string">Web O Data</hasName>
</owl:NamedIndividual>
<!-- http://www.people.com#individual_7 -->
<owl:NamedIndividual rdf:about="&www;individual_7">
<rdf:type rdf:resource="&www;Individual"/>
<hasName rdf:datatype="&xsd;string">Mr. OWL</hasName>
</owl:NamedIndividual>
</rdf:RDF>
<!-- Generated by the OWL API (version 3.2.5.1912) http://owlapi.sourceforge.net -->
代码
代码1 常量类
package util;
/**
* <ul>
* <li>Author: zhoujg | Date: 2014-3-23 下午1:25:14</li>
* <li>Description: 常量类</li>
* </ul>
*/
public class Constants {
public static final String NEWLINE = System.getProperty("line.separator");
public static final String TAB = System.getProperty("\t");
public static final String BOUNDARY = "-----------------------------------------------------------------------";
public static final String RDF_URL = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
public static final String RDFS_URL = "http://www.w3.org/2000/01/rdf-schema#";
public static final String OWL_URL = "http://www.w3.org/2002/07/owl#";
public static final String XSD_URL = "http://www.w3.org/2001/XMLSchema#";
public static final String FOAF_URL = "http://xmlns.com/foaf/0.1/";
public static final String RDF_TYPE = "<" + RDF_URL + "type>";
}
代码2 HelloSemanticWeb
package helloworld;
import java.io.IOException;
import java.io.InputStream;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.reasoner.Reasoner;
import com.hp.hpl.jena.reasoner.ReasonerRegistry;
import com.hp.hpl.jena.reasoner.rulesys.GenericRuleReasoner;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
import com.hp.hpl.jena.util.FileManager;
import static util.Constants.*;
/**
* <ul>
* <li>Author: zhoujg | Date: 2014-3-23 下午12:56:51</li>
* <li>Description: Jena语义Web编程之HelloWorld</li>
* </ul>
*/
class HelloSemanticWeb {
// FOAF命名空间
private static final String FOAF_NS = "http://xmlns.com/foaf/0.1/";
// FOAF文件绝对路径
private static final String FOAF_SCHEMA_FN = "E:/码农的世界/码农的自我修养/semantic web/workspace/foafSchema.rdf";
// myfoaf命名空间
private static final String MYFOAF_NS = "http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl";
// myfoaf文件绝对路径
private static final String MYFOAF_DATA_FN = "E:/码农的世界/码农的自我修养/semantic web/workspace/foafData.rdf";
// poeple命名空间
private static final String PEOPLE_NS = "http://www.people.com";
// people文件的绝对路径
private static final String PEOPLE_SCHEMA_FN = "E:/码农的世界/码农的自我修养/semantic web/workspace/peopleSchema.rdf";
private static final String PEOPLE_DATA_FN = "E:/码农的世界/码农的自我修养/semantic web/workspace/peopleData.rdf";
// Jena的RDF模型
private static Model friendsModel = null;
// 所有本体的Schema模型
private static Model schema = null;
// 推理后模型
private static InfModel inferredModel = null;
public static void main(String[] args) throws IOException {
version2();
}
/** version 1: rdf navigate using sparql query */
public static void version1() throws IOException {
System.out.println("Load my FOAF friends");
friendsModel = populateMyFOAFFriends(MYFOAF_DATA_FN);
System.out.println("Say Hello to myself");
sayHelloToMyself(friendsModel);
System.out.println("Say Hello to my friends");
sayHelloToMyFriends(friendsModel);
}
/** version 2: ontology integration using alignment */
public static void version2() throws IOException {
System.out.println("Load the data");
loadABox();
System.out.println("Generate the schema to contain all ontology's tbox");
loadTBox();
// 本体对准
alignmentInTBox();
// 绑定到推理机
bindReasoner();
// 执行查询
sayHelloToMyself(inferredModel);
sayHelloToMyFriends(inferredModel);
}
/** version 3: using jena rules */
public static void version3() throws IOException {
System.out.println("Load the data");
loadABox();
System.out.println("Generate the schema to contain all ontology's tbox");
loadTBox();
// 本体对准
alignmentInTBox();
// 绑定到规则推理机
bindJenaReasoner();
// 执行查询
sayHelloToGmailFriends(inferredModel);
}
private static void bindJenaReasoner() {
final String rule = "[gmailFriend: (?person <http://xmlns.com/foaf/0.1/mbox_sha1sum> ?email), strConcat(?email, ?lit), regex(?lit, '(.*gmail.com)')"
+ "-> (?person " + RDF_TYPE + " <http://www.people.com#GmailPerson>)]";
Reasoner ruleReasoner = new GenericRuleReasoner(Rule.parseRules(rule));
ruleReasoner = ruleReasoner.bindSchema(schema);
inferredModel = ModelFactory.createInfModel(ruleReasoner, friendsModel);
}
/** 加载所有本体的ABox */
private static void loadABox() {
friendsModel = ModelFactory.createDefaultModel();
InputStream is = FileManager.get().open(MYFOAF_DATA_FN);// MyFOAF的data
friendsModel.read(is, MYFOAF_NS);
is = FileManager.get().open(PEOPLE_DATA_FN);// people的data
friendsModel.read(is, PEOPLE_NS);
}
/** 加载所有本体的TBox */
private static void loadTBox() {
schema = ModelFactory.createDefaultModel();
InputStream is = FileManager.get().open(FOAF_SCHEMA_FN);// FOAF的Schema
schema.read(is, FOAF_NS);
is = FileManager.get().open(PEOPLE_SCHEMA_FN);// people的Schema
schema.read(is, PEOPLE_NS);
}
/** 本体对准ontology alignment */
private static void alignmentInTBox() {
// [1]people:Individual = foaf:Person
Resource resource = schema.createResource(PEOPLE_NS + "#Individual");
Property property = schema.createProperty(OWL_URL + "equivalentClass");
Resource object = schema.createResource(FOAF_URL + "Person");
schema.add(resource, property, object);
// [2]people:hasName = foaf:name
resource = schema.createResource(PEOPLE_NS + "#hasName");
property = schema.createProperty(OWL_URL + "equivalentProperty");
object = schema.createResource(FOAF_URL + "name");
schema.add(resource, property, object);
// [3]people:hasFriend < foaf:knows
resource = schema.createResource(PEOPLE_NS + "#hasFriend");
property = schema.createProperty(RDFS_URL + "subPropertyOf");
object = schema.createResource(FOAF_URL + "knows");
schema.add(resource, property, object);
// [4]myfoaf:me = people:individual_5
resource = schema.createResource(MYFOAF_NS + "#me");
property = schema.createProperty(OWL_URL + "sameAs");
object = schema.createResource(PEOPLE_NS + "#individual_5");
schema.add(resource, property, object);
}
private static void bindReasoner() {
Reasoner reasoner = ReasonerRegistry.getOWLReasoner();
reasoner = reasoner.bindSchema(schema);// tbox
inferredModel = ModelFactory.createInfModel(reasoner, friendsModel);// abox
}
/** 填充模型 */
private static Model fillModel(String base, String filePath) throws IOException {
Model model = ModelFactory.createDefaultModel();
InputStream is = FileManager.get().open(filePath);
model.read(is, base);
is.close();
return model;
}
/** MyFOAF填充模型 */
private static Model populateMyFOAFFriends(String filePath) throws IOException {
return fillModel(MYFOAF_NS, filePath);
}
/** RDF模型导航:SPARQL查询 - 查询自己name */
private static void sayHelloToMyself(Model model) {
String query = generateMyselfSPARQLQuery();
sparql(model, query, "?name");
}
private static void sayHelloToGmailFriends(Model model) {
String query = generateGmailFriendsSPARQLQuery();
sparql(model, query, "?name");
}
/** RDF模型导航:SPARQL查询 - 查询朋友name */
private static void sayHelloToMyFriends(Model model) {
String query = generateFriendsSPARQLQuery();
sparql(model, query, "?name");
}
/** 在RDF模型中执行SPARQL查询 */
private static void sparql(Model model, String query, String field) {
Query q = QueryFactory.create(query);
QueryExecution qexec = QueryExecutionFactory.create(q, model);
System.out.println("Plan to run SPARQL query: ");
System.out.println(BOUNDARY);
System.out.println(query);
System.out.println(BOUNDARY);
ResultSet rs = qexec.execSelect();
while (rs.hasNext()) {
QuerySolution qs = rs.nextSolution();
RDFNode name = qs.get(field);// 暂用RDFNode
if (name != null) {
System.out.println("Hello to " + name);
} else {
System.out.println("No friends found!");
}
}
qexec.close();
}
private static String generateMyselfSPARQLQuery() {
StringBuilder sb = generateSPARQLPREFIX();
// 添加查询语句
sb.append("SELECT DISTINCT ?name").append(NEWLINE).append("WHERE { myfoaf:me foaf:name ?name}").append(NEWLINE);
return sb.toString();
}
private static String generateGmailFriendsSPARQLQuery() {
StringBuilder sb = generateSPARQLPREFIX();
sb.append("SELECT DISTINCT ?name WHERE {?name rdf:type people:GmailPerson}");
return sb.toString();
}
private static String generateFriendsSPARQLQuery() {
StringBuilder sb = generateSPARQLPREFIX();
sb.append("SELECT DISTINCT ?name").append(NEWLINE).append("WHERE { myfoaf:me foaf:knows ?friend. ").append("?friend foaf:name ?name}")
.append(NEWLINE);
return sb.toString();
}
/** 添加SPARQL查询前缀PREFIX */
private static StringBuilder generateSPARQLPREFIX() {
StringBuilder sb = new StringBuilder();
sb.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>").append(NEWLINE).append("PREFIX owl: <http://www.w3.org/2002/07/owl#>")
.append(NEWLINE).append("PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>").append(NEWLINE)
.append("PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>").append(NEWLINE).append("PREFIX foaf: <http://xmlns.com/foaf/0.1/>")
.append(NEWLINE).append("PREFIX myfoaf: <http://blog.sina.com.cn/zhoujiagenontology/helloworld.owl#>").append(NEWLINE)
.append("PREFIX people: <http://www.people.com#>").append(NEWLINE);
return sb;
}
}
Jena语义Web开发101的更多相关文章
- 语义Web和本体开发相关技术
在技术实现方面,语义Web和本体理论的研究日趋成熟,已经有许多成熟的工具或程序接口,诸如Jena.OWL API等API是系统实现的关键技术.这里介绍系统的可行性分析以及系统开发设计的关键技术. 1 ...
- Jena 简介:通过 Jena Semantic Web Framework 在 Jave 应用程序中使用 RDF 模型
简介: RDF 越来越被认为是表示和处理半结构化数据的一种极好选择.本文中,Web 开发人员 Philip McCarthy 向您展示了如何使用 Jena Semantic Web Toolkit,以 ...
- 第五模块:WEB开发基础 第3章·BootStrap&JQuery开发
01-JQuery介绍 02-jQuery文件引入和加载的区别 03-jQuery的基础选择器 04-jQuery的层级选择器 05-jQuery的基本过滤选择器 06-jQuery的属性选择器 07 ...
- 通俗易懂,什么是.NET?什么是.NET Framework?什么是.NET Core? .Net Web开发技术栈
通俗易懂,什么是.NET?什么是.NET Framework?什么是.NET Core? 什么是.NET?什么是.NET Framework?本文将从上往下,循序渐进的介绍一系列相关.NET的概念 ...
- 做web开发和测试,修改hosts指定某个域名访问某个特定的IP后,如何使hosts立即生效的方法
本文转自SUN'S BLOG,原文地址:http://whosmall.com/post/143 hosts的配置方法: 在windows系统中,找到C:\windows\system32\drive ...
- Redis的Python实践,以及四中常用应用场景详解——学习董伟明老师的《Python Web开发实践》
首先,简单介绍:Redis是一个基于内存的键值对存储系统,常用作数据库.缓存和消息代理. 支持:字符串,字典,列表,集合,有序集合,位图(bitmaps),地理位置,HyperLogLog等多种数据结 ...
- 2016 Web开发资源工具大搜罗
来源于:https://zhuanlan.zhihu.com/p/22730771 作者:余博伦链接:https://zhuanlan.zhihu.com/p/22730771来源:知乎著作权归作者所 ...
- Web开发技术发展历史
Web开发技术发展历史 来自:天码营 原文:http://www.tianmaying.com/tutorial/web-history Web的诞生 提到Web,不得不提一个词就是"互 ...
- 超全的web开发工具和资源
首页 新闻 产品 地图 动态 城市 帮助 论坛 关于 登录 注册 · 不忘初心,继续前进,环境云V2接口正式上线 · 环境云测点地图全新改版 · 祝福各位环境云用户中秋快乐! 平台信息 培训互动 ...
随机推荐
- Linux休眠,挂起,待机,关机的区别及相关命令
休眠是一种更加省电的模式,它将内存中的数据保存于硬盘中,所有设备都停止工作.当再次使用时需按开关机键,机器将会恢复到您的执行休眠时的状态,而不用再次执行启动操作系统复杂的过程. 待机(挂起)是将当前处 ...
- 阻抗计算公式、polar si9000(教程)
给初学者的一直有很多人问我阻抗怎么计算的. 人家问多了,我想给大家整理个材料,于己于人都是个方便.如果大家还有什么问题或者文档有什么错误,欢迎讨论与指教!在计算阻抗之前,我想很有必要理解这儿阻抗的意义 ...
- java使用split切割字符串的时候,注意转义字符
今天在做项目的时候发现一个奇怪的问题 File file = new File("d:\\a.txt"); BufferedReader br = new BufferedRead ...
- [Git] 怎么使用Git让代码回到以前的某个节点
我们可以使某个文件回到以前的某个节点,也可以使整个文件夹下面的文件都回到以前的某个节点,下面只介绍某个文件的,全部的类似. 按步骤操作完成后本地你选中的文件会变成红色,此时的代码还是原来的代码,但是G ...
- 使用sublime时报编码错误
在执行Python脚本时报如下错误: UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-78: ordin ...
- Android SharePreference 在主进程和次进程间共享数据不同步出错
SharedPreference作为android五大存储(网络,数据库,文件,SharedPreference,contentProvider)之中最方便使用的一个,从类名上来看就不是一个存储大 ...
- Linux运行级详解
对于那些在DOS/Win9x/NT平台下的高级用户而言,Linux似乎是一个怪物.没有config.sys,没有 autoexec.bat,具有个人特色的机器配置不知道从何开始. 需要说明的是,很多人 ...
- 【apache】yum 安装Apache(Centos 6.5)
一.首先在系统上面查询一下是否已经安装了apache [Apache在linux系统里的名字是httpd] rpm -qa httpd 如果有返回的信息,则会显示已经安装的软件.如果没有则 ...
- 6/14 Sprint2 看板和燃尽图
中间部分还需要改进 小组评分:(团队总分为80) 团队成员: 101丘娟同学:21 107杨晓霞同学:18 108周诗琦同学:22 124陈程同 ...
- PHP 二维码解码 (读取二维码)
#zbar wget http://ncu.dl.sourceforge.net/project/zbar/zbar/0.10/zbar-0.10.tar.bz2 yum install gtk2 g ...