1
/* This file is part of the Nepomuk Project
2
Copyright (c) 2009 Sebastian Trueg <trueg@kde.org>
4
Based on CrappyInferencingConnection.java and CrappyInferencingSail.java
5
Copyright (c) 2006-2009, NEPOMUK Consortium
7
This library is free software; you can redistribute it and/or
8
modify it under the terms of the GNU Library General Public
9
License version 2 as published by the Free Software Foundation.
11
This library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Library General Public License for more details.
16
You should have received a copy of the GNU Library General Public License
17
along with this library; see the file COPYING.LIB. If not, write to
18
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
Boston, MA 02110-1301, USA.
22
#include "crappyinferencer.h"
24
#include <Soprano/Vocabulary/NRL>
25
#include <Soprano/Vocabulary/RDF>
26
#include <Soprano/Vocabulary/RDFS>
27
#include <Soprano/Statement>
28
#include <Soprano/StatementIterator>
29
#include <Soprano/Node>
30
#include <Soprano/Graph>
31
#include <Soprano/QueryResultIterator>
35
// Hint: Inverse property handling has been disabled but the code kept for possible future use or educational value.
36
// Handling inverse properties here does not make sense as the crappy inference is only applied to the ontologies,
37
// not the data itself.
40
class Nepomuk::CrappyInferencer::Private
43
QUrl infoContext() const;
45
// QHash<QUrl, QUrl> m_inverseProperties;
46
QMultiHash<QUrl, QUrl> m_subClasses;
47
QMultiHash<QUrl, QUrl> m_superClasses;
48
QMultiHash<QUrl, QUrl> m_subProperties;
49
QMultiHash<QUrl, QUrl> m_superProperties;
55
QUrl Nepomuk::CrappyInferencer::Private::infoContext() const
61
Nepomuk::CrappyInferencer::CrappyInferencer( Soprano::Model* parentModel )
62
: FilterModel( parentModel ),
65
d->m_infoContext = QUrl::fromEncoded("urn:crappyinference:inferredtriples");
67
createInferenceIndex();
71
Nepomuk::CrappyInferencer::~CrappyInferencer()
77
void Nepomuk::CrappyInferencer::setParentModel( Soprano::Model* model )
79
FilterModel::setParentModel( model );
80
createInferenceIndex();
84
QUrl Nepomuk::CrappyInferencer::crappyInferenceContext() const
86
return d->infoContext();
90
Soprano::Error::ErrorCode Nepomuk::CrappyInferencer::addStatement( const Soprano::Statement& statement )
93
// Handle the inference
95
if ( statement.subject().isResource() &&
96
statement.object().isResource() ) {
99
// handle inverse properties
101
if ( statement.predicate() == Soprano::Vocabulary::NRL::inverseProperty() ) {
102
d->m_inverseProperties.insert( statement.subject().uri(), statement.object().uri() );
103
d->m_inverseProperties.insert( statement.object().uri(), statement.subject().uri() );
104
parentModel()->addStatement( statement.object(), statement.predicate(), statement.subject(), d->infoContext() );
106
else if ( d->m_inverseProperties.contains( statement.predicate().uri() ) ) {
107
parentModel()->addStatement( statement.object(), d->m_inverseProperties[statement.predicate().uri()], statement.subject(), d->infoContext() );
111
// infer sub classing
115
if ( statement.predicate() == Soprano::Vocabulary::RDFS::subClassOf() ) {
116
addInference( statement, d->m_subClasses, d->m_superClasses );
120
// infer sub properties
122
else if ( statement.predicate() == Soprano::Vocabulary::RDFS::subPropertyOf() ) {
123
addInference( statement, d->m_subProperties, d->m_superProperties );
127
// RDFS entailment 6 and 10 (self-sub-relations)
129
else if ( statement.predicate() == Soprano::Vocabulary::RDF::type() ) {
130
if ( statement.object() == Soprano::Vocabulary::RDF::Property() ) {
131
parentModel()->addStatement( statement.subject(), Soprano::Vocabulary::RDFS::subPropertyOf(), statement.subject(), d->infoContext() );
133
else if ( statement.object() == Soprano::Vocabulary::RDFS::Class() ) {
134
parentModel()->addStatement( statement.subject(), Soprano::Vocabulary::RDFS::subClassOf(), statement.subject(), d->infoContext() );
139
return parentModel()->addStatement( statement );
143
Soprano::Error::ErrorCode Nepomuk::CrappyInferencer::removeStatement( const Soprano::Statement& statement )
145
if ( statement.subject().isResource() &&
146
statement.object().isResource() ) {
147
Soprano::Graph statementsToRemove;
148
removeStatementInference( statement, statementsToRemove );
149
parentModel()->removeStatements( statementsToRemove.toList() );
151
return parentModel()->removeStatement( statement );
155
Soprano::Error::ErrorCode Nepomuk::CrappyInferencer::removeAllStatements( const Soprano::Statement& statement )
157
if ( ( !statement.subject().isValid() || statement.subject().isResource() ) &&
158
( !statement.object().isValid() || statement.object().isResource() ) ) {
159
Soprano::Graph statementsToRemove;
160
Soprano::StatementIterator it = FilterModel::listStatements( statement );
161
while ( it.next() ) {
162
removeStatementInference( *it, statementsToRemove );
165
parentModel()->removeStatements( statementsToRemove.toList() );
168
return FilterModel::removeAllStatements( statement );
172
void Nepomuk::CrappyInferencer::removeStatementInference( const Soprano::Statement& s, Soprano::Graph& statementsToRemove )
176
// handle inverse properties
178
if ( s.predicate() == Soprano::Vocabulary::NRL::inverseProperty() ) {
179
d->m_inverseProperties.remove( s.subject().uri() );
180
d->m_inverseProperties.remove( s.object().uri() );
181
statementsToRemove.addStatement( s.object(), s.predicate(), s.subject(), d->infoContext() );
183
else if ( d->m_inverseProperties.contains( s.predicate().uri() ) ) {
184
// remove both - to ensure at least something vaguely like
186
statementsToRemove.addStatement( s.object(), d->m_inverseProperties[s.predicate().uri()], s.subject(), d->infoContext() );
190
// remove subclass inference
194
if ( s.predicate() == Soprano::Vocabulary::RDFS::subClassOf() ) {
195
removeInference( s, d->m_subClasses, d->m_superClasses, statementsToRemove );
199
// remove subproperty inference
201
else if ( s.predicate() == Soprano::Vocabulary::RDFS::subPropertyOf() ) {
202
removeInference( s, d->m_subProperties, d->m_superProperties, statementsToRemove );
206
// RDFS entailment 6 and 10 (self-sub-relations)
208
else if ( s.predicate() == Soprano::Vocabulary::RDF::type() ) {
209
if ( s.object() == Soprano::Vocabulary::RDF::Property() ) {
210
statementsToRemove.addStatement( s.subject(), Soprano::Vocabulary::RDFS::subPropertyOf(), s.subject(), d->infoContext() );
212
else if ( s.object() == Soprano::Vocabulary::RDFS::Class() ) {
213
statementsToRemove.addStatement( s.subject(), Soprano::Vocabulary::RDFS::subClassOf(), s.subject(), d->infoContext() );
219
void Nepomuk::CrappyInferencer::removeInference( const Soprano::Statement& statement,
220
QMultiHash<QUrl, QUrl>& subRelationOf,
221
QMultiHash<QUrl, QUrl>& superRelationOf,
222
Soprano::Graph& statementsToRemove )
224
subRelationOf.remove( statement.subject().uri(), statement.object().uri() );
225
subRelationOf.remove( statement.object().uri(), statement.subject().uri() );
227
Soprano::Graph removedStatements;
228
removeInference( statement, subRelationOf, superRelationOf, statementsToRemove, removedStatements );
232
void Nepomuk::CrappyInferencer::removeInference( const Soprano::Statement& statement,
233
QMultiHash<QUrl, QUrl>& subRelationOf,
234
QMultiHash<QUrl, QUrl>& superRelationOf,
235
Soprano::Graph& statementsToRemove,
236
Soprano::Graph& removedStatements )
238
Soprano::Statement s( statement );
239
s.setContext( d->infoContext() );
241
if ( !removedStatements.containsStatement( s ) ) {
242
// remove the statement
243
statementsToRemove << s;
244
removedStatements << s;
246
// infer sub relations
247
foreach( const QUrl& uri, subRelationOf.values( statement.object().uri() ) ) {
249
removeInference( s, subRelationOf, superRelationOf, statementsToRemove, removedStatements );
252
// infer super relations
253
s.setObject( statement.object() );
254
foreach( const QUrl& uri, superRelationOf.values( statement.subject().uri() ) ) {
256
removeInference( s, subRelationOf, superRelationOf, statementsToRemove, removedStatements );
262
void Nepomuk::CrappyInferencer::addInference( const Soprano::Statement& statement,
263
QMultiHash<QUrl, QUrl>& subRelationOf,
264
QMultiHash<QUrl, QUrl>& superRelationOf )
266
// update status vars
267
subRelationOf.insert( statement.subject().uri(), statement.object().uri() );
268
superRelationOf.insert( statement.object().uri(), statement.subject().uri() );
270
// do the actual inference (this will add the statement again, but we do not care)
271
Soprano::Graph graph;
272
addInference( statement, subRelationOf, superRelationOf, graph );
276
void Nepomuk::CrappyInferencer::addInference( const Soprano::Statement& statement,
277
QMultiHash<QUrl, QUrl>& subRelationOf,
278
QMultiHash<QUrl, QUrl>& superRelationOf,
279
Soprano::Graph& addedStatements )
281
Soprano::Statement s( statement );
282
s.setContext( d->infoContext() );
284
if ( !addedStatements.containsStatement( s ) ) {
287
parentModel()->addStatement( s );
288
addedStatements.addStatement( s );
290
// infer sub relations
291
foreach( const QUrl& uri, subRelationOf.values( statement.object().uri() ) ) {
293
addInference( s, subRelationOf, superRelationOf, addedStatements );
296
// infer super relations
297
s.setObject( statement.object() );
298
foreach( const QUrl& uri, superRelationOf.values( statement.subject().uri() ) ) {
300
addInference( s, subRelationOf, superRelationOf, addedStatements );
306
void Nepomuk::CrappyInferencer::createInferenceIndex()
309
// d->m_inverseProperties.clear();
310
d->m_subClasses.clear();
311
d->m_superClasses.clear();
312
d->m_subProperties.clear();
313
d->m_superProperties.clear();
316
// cache inverse properties
317
Soprano::QueryResultIterator it = executeQuery( QString( "select ?x ?y where { ?x %1 ?y . }" )
318
.arg( Soprano::Node::resourceToN3( Soprano::Vocabulary::NRL::inverseProperty() ) ),
319
Soprano::Query::QueryLanguageSparql );
320
while ( it.next() ) {
321
d->m_inverseProperties.insert( it["x"].uri(), it["y"].uri() );
322
d->m_inverseProperties.insert( it["y"].uri(), it["x"].uri() );
326
// cache subClassOf relations (only the original ones)
327
Soprano::QueryResultIterator it = executeQuery( QString( "select ?x ?y where { graph ?g { ?x %1 ?y . } . FILTER(?g != %2) . }" )
328
.arg( Soprano::Node::resourceToN3( Soprano::Vocabulary::RDFS::subClassOf() ) )
329
.arg( Soprano::Node::resourceToN3( d->infoContext() ) ),
330
Soprano::Query::QueryLanguageSparql );
331
while ( it.next() ) {
332
d->m_subClasses.insert( it["x"].uri(), it["y"].uri() );
333
d->m_superClasses.insert( it["y"].uri(), it["x"].uri() );
337
// cache subPropertyOf relations (only the original ones)
338
it = executeQuery( QString( "select ?x ?y where { graph ?g { ?x %1 ?y . } . FILTER(?g != %2) . }" )
339
.arg( Soprano::Node::resourceToN3( Soprano::Vocabulary::RDFS::subPropertyOf() ) )
340
.arg( Soprano::Node::resourceToN3( d->infoContext() ) ),
341
Soprano::Query::QueryLanguageSparql );
342
while ( it.next() ) {
343
d->m_subProperties.insert( it["x"].uri(), it["y"].uri() );
344
d->m_superProperties.insert( it["y"].uri(), it["x"].uri() );
347
// we only create ontology statements - we need to mark the graph as such
348
parentModel()->addStatement(d->infoContext(), Soprano::Vocabulary::RDF::type(), Soprano::Vocabulary::NRL::Ontology(), d->infoContext());
351
#include "crappyinferencer.moc"