syndication/rdf
model.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "model.h"
00024 #include "literal.h"
00025 #include "nodevisitor.h"
00026 #include "property.h"
00027 #include "rdfvocab.h"
00028 #include "resource.h"
00029 #include "sequence.h"
00030 #include "statement.h"
00031
00032 #include <QtCore/QHash>
00033 #include <QtCore/QList>
00034 #include <QtCore/QString>
00035
00036 namespace Syndication {
00037 namespace RDF {
00038
00039 class Model::ModelPrivate
00040 {
00041 public:
00042
00043 long id;
00044 static long idCounter;
00045 LiteralPtr nullLiteral;
00046 PropertyPtr nullProperty;
00047 ResourcePtr nullResource;
00048 StatementPtr nullStatement;
00049 QHash<QString, StatementPtr> statements;
00050 QHash<QString, QList<StatementPtr> > stmtsBySubject;
00051
00052 QHash<int, NodePtr> nodes;
00053 QHash<QString, ResourcePtr> resources;
00054 QHash<QString, PropertyPtr> properties;
00055 QHash<QString, SequencePtr> sequences;
00056 Model* model;
00057
00058 class AddToHashesVisitor;
00059
00060 ModelPrivate(Model* m)
00061 {
00062 model = m;
00063 id = idCounter++;
00064 addToHashesVisitor = new AddToHashesVisitor(this);
00065 initialized = false;
00066 }
00067
00068 ~ModelPrivate()
00069 {
00070 delete addToHashesVisitor;
00071 }
00072
00073 bool operator==(const ModelPrivate& other) const
00074 {
00075 return id == other.id;
00076 }
00077
00078 class AddToHashesVisitor : public NodeVisitor
00079 {
00080 public:
00081
00082 AddToHashesVisitor(ModelPrivate* parent) : p(parent)
00083 {}
00084
00085 bool visitResource(ResourcePtr res)
00086 {
00087 visitNode(res);
00088 p->resources[res->uri()] = res;
00089 return true;
00090 }
00091
00092 bool visitSequence(SequencePtr seq)
00093 {
00094 visitResource(seq);
00095 p->sequences[seq->uri()] = seq;
00096 return true;
00097 }
00098
00099 bool visitProperty(PropertyPtr prop)
00100 {
00101 visitResource(prop);
00102 p->properties[prop->uri()] = prop;
00103 return true;
00104 }
00105
00106 bool visitNode(NodePtr node)
00107 {
00108 p->nodes[node->id()] = node;
00109 return true;
00110 }
00111
00112 ModelPrivate* p;
00113 };
00114
00115 AddToHashesVisitor* addToHashesVisitor;
00116
00117 void addToHashes(NodePtr node)
00118 {
00119 addToHashesVisitor->visit(node);
00120 }
00121
00122 void addToHashes(StatementPtr stmt, const QString& key)
00123 {
00124 statements[key] = stmt;
00125 stmtsBySubject[stmt->subject()->uri()].append(stmt);
00126 }
00127
00128 void removeFromHashes(const QString& key)
00129 {
00130 StatementPtr stmt = statements[key];
00131 if (stmt)
00132 stmtsBySubject[stmt->subject()->uri()].removeAll(stmt);
00133 statements.remove(key);
00134
00135 }
00136
00137 bool initialized;
00138
00139 void init()
00140 {
00141 if (!initialized)
00142 {
00143 nullLiteral = LiteralPtr( new Literal() );
00144 nullLiteral->setModel(*model);
00145 nullProperty = PropertyPtr( new Property() );
00146 nullProperty->setModel(*model);
00147 nullResource = ResourcePtr( new Resource() );
00148 nullResource->setModel(*model);
00149 nullStatement = StatementPtr( new Statement() );
00150 initialized = true;
00151 }
00152 }
00153 };
00154
00155 long Model::ModelPrivate::idCounter = 0;
00156
00157 Model::Model() : d(new ModelPrivate(this))
00158 {
00159 }
00160
00161 Model::Model(const Model& other)
00162 {
00163 *this = other;
00164 }
00165
00166 Model::~Model()
00167 {
00168 }
00169
00170 Model& Model::operator=(const Model& other)
00171 {
00172 d = other.d;
00173 return *this;
00174 }
00175
00176 bool Model::operator==(const Model& other) const
00177 {
00178 return *d == *(other.d);
00179 }
00180
00181 PropertyPtr Model::createProperty(const QString& uri)
00182 {
00183 PropertyPtr prop;
00184
00185 if (d->properties.contains(uri))
00186 {
00187 prop = d->properties[uri];
00188 }
00189 else
00190 {
00191 prop = PropertyPtr( new Property(uri) );
00192 prop->setModel(*this);
00193
00194
00195 if (d->resources.contains(uri))
00196 {
00197 prop->setId(d->resources[uri]->id());
00198 }
00199 d->addToHashes(prop);
00200 }
00201
00202 return prop;
00203
00204 }
00205
00206 ResourcePtr Model::createResource(const QString& uri)
00207 {
00208 ResourcePtr res;
00209
00210 if (d->resources.contains(uri))
00211 {
00212 res = d->resources[uri];
00213 }
00214 else
00215 {
00216 res = ResourcePtr( new Resource(uri) );
00217 res->setModel(*this);
00218 d->addToHashes(res);
00219 }
00220
00221 return res;
00222 }
00223
00224 SequencePtr Model::createSequence(const QString& uri)
00225 {
00226 SequencePtr seq;
00227
00228 if (d->sequences.contains(uri))
00229 {
00230 seq = d->sequences[uri];
00231 }
00232 else
00233 {
00234 seq = SequencePtr( new Sequence(uri) );
00235 seq->setModel(*this);
00236
00237
00238 if (d->resources.contains(uri))
00239 {
00240 seq->setId(d->resources[uri]->id());
00241 }
00242
00243 d->addToHashes(seq);
00244 }
00245
00246 return seq;
00247 }
00248
00249 LiteralPtr Model::createLiteral(const QString& text)
00250 {
00251 LiteralPtr lit(new Literal(text));
00252
00253 d->addToHashes(lit);
00254 return lit;
00255 }
00256
00257
00258 void Model::removeStatement(StatementPtr statement)
00259 {
00260 removeStatement(statement->subject(), statement->predicate(), statement->object());
00261 }
00262
00263 void Model::removeStatement(ResourcePtr subject, PropertyPtr predicate, NodePtr object)
00264 {
00265 QString key = QString("%1-%2-%3")
00266 .arg(QString::number(subject->id()))
00267 .arg(QString::number(predicate->id()))
00268 .arg(QString::number(object->id()));
00269 d->removeFromHashes(key);
00270 }
00271
00272 StatementPtr Model::addStatement(ResourcePtr subject, PropertyPtr predicate, NodePtr object)
00273 {
00274 d->init();
00275 ResourcePtr subjInternal = subject;
00276
00277 if (!d->nodes.contains(subjInternal->id()))
00278 {
00279 subjInternal = ResourcePtr( subject->clone() );
00280 subjInternal->setModel(*this);
00281 d->addToHashes(subjInternal);
00282 }
00283
00284 PropertyPtr predInternal = predicate;
00285
00286 if (!d->nodes.contains(predInternal->id()))
00287 {
00288 predInternal = PropertyPtr( predicate->clone() );
00289 predInternal->setModel(*this);
00290 d->addToHashes(predInternal);
00291 }
00292
00293 NodePtr objInternal = object;
00294
00295 if (!d->nodes.contains(objInternal->id()))
00296 {
00297 objInternal = NodePtr( object->clone() );
00298 objInternal->setModel(*this);
00299 d->addToHashes(objInternal);
00300 }
00301
00302
00303
00304 QString key = QString("%1-%2-%3")
00305 .arg(QString::number(subjInternal->id()))
00306 .arg(QString::number(predInternal->id()))
00307 .arg(QString::number(objInternal->id()));
00308
00309 StatementPtr stmt;
00310
00311 if (!d->statements.contains(key))
00312 {
00313 stmt = StatementPtr( new Statement(subjInternal, predInternal, objInternal) );
00314 d->addToHashes(stmt, key);
00315 }
00316 else
00317 {
00318 stmt = d->statements[key];
00319 }
00320
00321 return stmt;
00322 }
00323
00324 bool Model::isEmpty() const
00325 {
00326 return d->statements.isEmpty();
00327 }
00328
00329 bool Model::resourceHasProperty(const Resource* resource, PropertyPtr property) const
00330 {
00331
00332 if (!d->resources.contains(resource->uri()))
00333 return false;
00334
00335 QList<StatementPtr> stmts = d->stmtsBySubject[resource->uri()];
00336 QList<StatementPtr>::ConstIterator it = stmts.constBegin();
00337 QList<StatementPtr>::ConstIterator end = stmts.constEnd();
00338
00339 for ( ; it != end; ++it)
00340 {
00341 if (*((*it)->predicate()) == *property)
00342 return true;
00343 }
00344
00345 return false;
00346 }
00347
00348 StatementPtr Model::resourceProperty(const Resource* resource, PropertyPtr property) const
00349 {
00350 QList<StatementPtr> stmts = d->stmtsBySubject[resource->uri()];
00351 QList<StatementPtr>::ConstIterator it = stmts.constBegin();
00352 QList<StatementPtr>::ConstIterator end = stmts.constEnd();
00353
00354 for ( ; it != end; ++it)
00355 {
00356 if (*((*it)->predicate()) == *property)
00357 return *it;
00358 }
00359
00360 return d->nullStatement;
00361 }
00362
00363 QList<StatementPtr> Model::resourceProperties(const Resource* resource, PropertyPtr property) const
00364 {
00365 QList<StatementPtr> res;
00366 QList<StatementPtr> stmts = d->stmtsBySubject[resource->uri()];
00367 QList<StatementPtr>::ConstIterator it = stmts.constBegin();
00368 QList<StatementPtr>::ConstIterator end = stmts.constEnd();
00369
00370 for ( ; it != end; ++it)
00371 {
00372 if (*((*it)->predicate()) == *property)
00373 res.append(*it);
00374 }
00375
00376 return res;
00377 }
00378
00379
00380 QList<StatementPtr> Model::statements() const
00381 {
00382 return d->statements.values();
00383 }
00384
00385 QString Model::debugInfo() const
00386 {
00387 QString info;
00388
00389 QList<StatementPtr> stmts = d->statements.values();
00390 QList<StatementPtr>::ConstIterator it = stmts.constBegin();
00391 QList<StatementPtr>::ConstIterator end = stmts.constEnd();
00392
00393 for ( ; it != end; ++it)
00394 {
00395 info += QString("<%1> <%2> ").arg((*it)->subject()->uri()).arg((*it)->predicate()->uri());
00396
00397 if ((*it)->object()->isLiteral())
00398 {
00399 info += QString("\"%1\"\n").arg((*it)->asString());
00400 }
00401 else
00402 {
00403 info += QString("<%1>\n").arg((*it)->asResource()->uri());
00404 }
00405
00406 }
00407
00408 return info;
00409 }
00410
00411 QList<ResourcePtr> Model::resourcesWithType(ResourcePtr type) const
00412 {
00413 QList<ResourcePtr> list;
00414
00415 QList<StatementPtr> stmts = d->statements.values();
00416 QList<StatementPtr>::ConstIterator it = stmts.constBegin();
00417 QList<StatementPtr>::ConstIterator end = stmts.constEnd();
00418
00419 for ( ; it != end; ++it)
00420 {
00421 if (*((*it)->predicate()) == *(RDFVocab::self()->type()) && *((*it)->object()) == *type )
00422 list.append((*it)->subject());
00423 }
00424
00425 return list;
00426 }
00427
00428 NodePtr Model::nodeByID(uint id) const
00429 {
00430 if (!d->nodes.contains(id))
00431 {
00432 return d->nullLiteral;
00433 }
00434 else
00435 {
00436 return d->nodes[id];
00437 }
00438 }
00439
00440 ResourcePtr Model::resourceByID(uint id) const
00441 {
00442 if (!d->nodes.contains(id))
00443 {
00444 return d->nullResource;
00445 }
00446 else
00447 {
00448 NodePtr node = d->nodes[id];
00449 if (node->isResource())
00450 return boost::static_pointer_cast<Resource>(node);
00451 else
00452 return d->nullResource;
00453 }
00454 }
00455
00456 PropertyPtr Model::propertyByID(uint id) const
00457 {
00458 if (!d->nodes.contains(id))
00459 {
00460 return d->nullProperty;
00461 }
00462 else
00463 {
00464 NodePtr node = d->nodes[id];
00465 if (node->isProperty())
00466 return boost::static_pointer_cast<Property>(node);
00467 else
00468 return d->nullProperty;
00469 }
00470 }
00471
00472 LiteralPtr Model::literalByID(uint id) const
00473 {
00474 if (!d->nodes.contains(id))
00475 {
00476 return d->nullLiteral;
00477 }
00478 else
00479 {
00480 NodePtr node = d->nodes[id];
00481 if (node->isLiteral())
00482 return boost::static_pointer_cast<Literal>(node);
00483 else
00484 return d->nullLiteral;
00485 }
00486 }
00487
00488 }
00489 }