• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

syndication/rdf

model.cpp

00001 /*
00002  * This file is part of the syndication library
00003  *
00004  * Copyright (C) 2006 Frank Osterfeld <osterfeld@kde.org>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Library General Public License
00017  * along with this library; see the file COPYING.LIB.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
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         // if there is a resource object with the same uri, replace
00194         // the resource object by the new property object and reuse the id
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         // if there is a resource object with the same uri, replace
00237         // the resource object by the new sequence object and reuse the id
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     // TODO: avoid duplicated stmts with literal objects!
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     // resource unknown
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.begin();
00337     QList<StatementPtr>::ConstIterator end = stmts.end();
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.begin();
00352     QList<StatementPtr>::ConstIterator end = stmts.end();
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.begin();
00368     QList<StatementPtr>::ConstIterator end = stmts.end();
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.begin();
00391     QList<StatementPtr>::ConstIterator end = stmts.end();
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.begin();
00417     QList<StatementPtr>::ConstIterator end = stmts.end();
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 } // namespace RDF
00489 } // namespace Syndication

syndication/rdf

Skip menu "syndication/rdf"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.7.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal