~ubuntu-branches/ubuntu/quantal/kde-runtime/quantal

« back to all changes in this revision

Viewing changes to nepomuk/services/storage/crappyinferencer.cpp

  • Committer: Package Import Robot
  • Author(s): Philip Muškovac
  • Date: 2012-06-03 21:50:00 UTC
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: package-import@ubuntu.com-20120603215000-vn7oarsq0ynrydj5
Tags: upstream-4.8.80
Import upstream version 4.8.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* This file is part of the Nepomuk Project
2
 
   Copyright (c) 2009 Sebastian Trueg <trueg@kde.org>
3
 
 
4
 
   Based on CrappyInferencingConnection.java and CrappyInferencingSail.java
5
 
   Copyright (c) 2006-2009, NEPOMUK Consortium
6
 
 
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.
10
 
 
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.
15
 
 
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.
20
 
*/
21
 
 
22
 
#include "crappyinferencer.h"
23
 
 
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>
32
 
 
33
 
 
34
 
//
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.
38
 
//
39
 
 
40
 
class Nepomuk::CrappyInferencer::Private
41
 
{
42
 
public:
43
 
    QUrl infoContext() const;
44
 
 
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;
50
 
 
51
 
    QUrl m_infoContext;
52
 
};
53
 
 
54
 
 
55
 
QUrl Nepomuk::CrappyInferencer::Private::infoContext() const
56
 
{
57
 
    return m_infoContext;
58
 
}
59
 
 
60
 
 
61
 
Nepomuk::CrappyInferencer::CrappyInferencer( Soprano::Model* parentModel )
62
 
    : FilterModel( parentModel ),
63
 
      d( new Private() )
64
 
{
65
 
    d->m_infoContext = QUrl::fromEncoded("urn:crappyinference:inferredtriples");
66
 
    if ( parentModel )
67
 
        createInferenceIndex();
68
 
}
69
 
 
70
 
 
71
 
Nepomuk::CrappyInferencer::~CrappyInferencer()
72
 
{
73
 
    delete d;
74
 
}
75
 
 
76
 
 
77
 
void Nepomuk::CrappyInferencer::setParentModel( Soprano::Model* model )
78
 
{
79
 
    FilterModel::setParentModel( model );
80
 
    createInferenceIndex();
81
 
}
82
 
 
83
 
 
84
 
QUrl Nepomuk::CrappyInferencer::crappyInferenceContext() const
85
 
{
86
 
    return d->infoContext();
87
 
}
88
 
 
89
 
 
90
 
Soprano::Error::ErrorCode Nepomuk::CrappyInferencer::addStatement( const Soprano::Statement& statement )
91
 
{
92
 
    //
93
 
    // Handle the inference
94
 
    //
95
 
    if ( statement.subject().isResource() &&
96
 
         statement.object().isResource() ) {
97
 
#if 0
98
 
        //
99
 
        // handle inverse properties
100
 
        //
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() );
105
 
        }
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() );
108
 
        }
109
 
 
110
 
        //
111
 
        // infer sub classing
112
 
        //
113
 
        else
114
 
#endif
115
 
            if ( statement.predicate() == Soprano::Vocabulary::RDFS::subClassOf() ) {
116
 
            addInference( statement, d->m_subClasses, d->m_superClasses );
117
 
        }
118
 
 
119
 
        //
120
 
        // infer sub properties
121
 
        //
122
 
        else if ( statement.predicate() == Soprano::Vocabulary::RDFS::subPropertyOf() ) {
123
 
            addInference( statement, d->m_subProperties, d->m_superProperties );
124
 
        }
125
 
 
126
 
        //
127
 
        // RDFS entailment 6 and 10 (self-sub-relations)
128
 
        //
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() );
132
 
            }
133
 
            else if ( statement.object() == Soprano::Vocabulary::RDFS::Class() ) {
134
 
                parentModel()->addStatement( statement.subject(), Soprano::Vocabulary::RDFS::subClassOf(), statement.subject(), d->infoContext() );
135
 
            }
136
 
        }
137
 
    }
138
 
 
139
 
    return parentModel()->addStatement( statement );
140
 
}
141
 
 
142
 
 
143
 
Soprano::Error::ErrorCode Nepomuk::CrappyInferencer::removeStatement( const Soprano::Statement& statement )
144
 
{
145
 
    if ( statement.subject().isResource() &&
146
 
         statement.object().isResource() ) {
147
 
        Soprano::Graph statementsToRemove;
148
 
        removeStatementInference( statement, statementsToRemove );
149
 
        parentModel()->removeStatements( statementsToRemove.toList() );
150
 
    }
151
 
    return parentModel()->removeStatement( statement );
152
 
}
153
 
 
154
 
 
155
 
Soprano::Error::ErrorCode Nepomuk::CrappyInferencer::removeAllStatements( const Soprano::Statement& statement )
156
 
{
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 );
163
 
        }
164
 
 
165
 
        parentModel()->removeStatements( statementsToRemove.toList() );
166
 
    }
167
 
 
168
 
    return FilterModel::removeAllStatements( statement );
169
 
}
170
 
 
171
 
 
172
 
void Nepomuk::CrappyInferencer::removeStatementInference( const Soprano::Statement& s, Soprano::Graph& statementsToRemove )
173
 
{
174
 
#if 0
175
 
    //
176
 
    // handle inverse properties
177
 
    //
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() );
182
 
    }
183
 
    else if ( d->m_inverseProperties.contains( s.predicate().uri() ) ) {
184
 
        // remove both - to ensure at least something vaguely like
185
 
        // consistency.
186
 
        statementsToRemove.addStatement( s.object(), d->m_inverseProperties[s.predicate().uri()], s.subject(), d->infoContext() );
187
 
    }
188
 
 
189
 
    //
190
 
    // remove subclass inference
191
 
    //
192
 
    else
193
 
#endif
194
 
        if ( s.predicate() == Soprano::Vocabulary::RDFS::subClassOf() ) {
195
 
        removeInference( s, d->m_subClasses, d->m_superClasses, statementsToRemove );
196
 
    }
197
 
 
198
 
    //
199
 
    // remove subproperty inference
200
 
    //
201
 
    else if ( s.predicate() == Soprano::Vocabulary::RDFS::subPropertyOf() ) {
202
 
        removeInference( s, d->m_subProperties, d->m_superProperties, statementsToRemove );
203
 
    }
204
 
 
205
 
    //
206
 
    // RDFS entailment 6 and 10 (self-sub-relations)
207
 
    //
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() );
211
 
        }
212
 
        else if ( s.object() == Soprano::Vocabulary::RDFS::Class() ) {
213
 
            statementsToRemove.addStatement( s.subject(), Soprano::Vocabulary::RDFS::subClassOf(), s.subject(), d->infoContext() );
214
 
        }
215
 
    }
216
 
}
217
 
 
218
 
 
219
 
void Nepomuk::CrappyInferencer::removeInference( const Soprano::Statement& statement,
220
 
                                                 QMultiHash<QUrl, QUrl>& subRelationOf,
221
 
                                                 QMultiHash<QUrl, QUrl>& superRelationOf,
222
 
                                                 Soprano::Graph& statementsToRemove )
223
 
{
224
 
    subRelationOf.remove( statement.subject().uri(), statement.object().uri() );
225
 
    subRelationOf.remove( statement.object().uri(), statement.subject().uri() );
226
 
 
227
 
    Soprano::Graph removedStatements;
228
 
    removeInference( statement, subRelationOf, superRelationOf, statementsToRemove, removedStatements );
229
 
}
230
 
 
231
 
 
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 )
237
 
{
238
 
    Soprano::Statement s( statement );
239
 
    s.setContext( d->infoContext() );
240
 
 
241
 
    if ( !removedStatements.containsStatement( s ) ) {
242
 
        // remove the statement
243
 
        statementsToRemove << s;
244
 
        removedStatements << s;
245
 
 
246
 
        // infer sub relations
247
 
        foreach( const QUrl& uri, subRelationOf.values( statement.object().uri() ) ) {
248
 
            s.setObject( uri );
249
 
            removeInference( s, subRelationOf, superRelationOf, statementsToRemove, removedStatements );
250
 
        }
251
 
 
252
 
        // infer super relations
253
 
        s.setObject( statement.object() );
254
 
        foreach( const QUrl& uri, superRelationOf.values( statement.subject().uri() ) ) {
255
 
            s.setSubject( uri );
256
 
            removeInference( s, subRelationOf, superRelationOf, statementsToRemove, removedStatements );
257
 
        }
258
 
    }
259
 
}
260
 
 
261
 
 
262
 
void Nepomuk::CrappyInferencer::addInference( const Soprano::Statement& statement,
263
 
                                              QMultiHash<QUrl, QUrl>& subRelationOf,
264
 
                                              QMultiHash<QUrl, QUrl>& superRelationOf )
265
 
{
266
 
    // update status vars
267
 
    subRelationOf.insert( statement.subject().uri(), statement.object().uri() );
268
 
    superRelationOf.insert( statement.object().uri(), statement.subject().uri() );
269
 
 
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 );
273
 
}
274
 
 
275
 
 
276
 
void Nepomuk::CrappyInferencer::addInference( const Soprano::Statement& statement,
277
 
                                              QMultiHash<QUrl, QUrl>& subRelationOf,
278
 
                                              QMultiHash<QUrl, QUrl>& superRelationOf,
279
 
                                              Soprano::Graph& addedStatements )
280
 
{
281
 
    Soprano::Statement s( statement );
282
 
    s.setContext( d->infoContext() );
283
 
 
284
 
    if ( !addedStatements.containsStatement( s ) ) {
285
 
 
286
 
        // add the statement
287
 
        parentModel()->addStatement( s );
288
 
        addedStatements.addStatement( s );
289
 
 
290
 
        // infer sub relations
291
 
        foreach( const QUrl& uri, subRelationOf.values( statement.object().uri() ) ) {
292
 
            s.setObject( uri );
293
 
            addInference( s, subRelationOf, superRelationOf, addedStatements );
294
 
        }
295
 
 
296
 
        // infer super relations
297
 
        s.setObject( statement.object() );
298
 
        foreach( const QUrl& uri, superRelationOf.values( statement.subject().uri() ) ) {
299
 
            s.setSubject( uri );
300
 
            addInference( s, subRelationOf, superRelationOf, addedStatements );
301
 
        }
302
 
    }
303
 
}
304
 
 
305
 
 
306
 
void Nepomuk::CrappyInferencer::createInferenceIndex()
307
 
{
308
 
    // clear cache
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();
314
 
 
315
 
#if 0
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() );
323
 
    }
324
 
#endif
325
 
 
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() );
334
 
    }
335
 
 
336
 
 
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() );
345
 
    }
346
 
 
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());
349
 
}
350
 
 
351
 
#include "crappyinferencer.moc"