File indexing completed on 2023-09-24 04:15:35
0001 /* 0002 This file is part of the syndication library 0003 SPDX-FileCopyrightText: 2006 Frank Osterfeld <osterfeld@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "model.h" 0009 #include "model_p.h" 0010 0011 namespace Syndication 0012 { 0013 namespace RDF 0014 { 0015 long Model::ModelPrivate::idCounter = 0; 0016 0017 Model::Model() 0018 : d(new ModelPrivate) 0019 { 0020 } 0021 0022 Model::Model(const Model &other) 0023 { 0024 *this = other; 0025 } 0026 0027 Model::~Model() 0028 { 0029 } 0030 0031 Model &Model::operator=(const Model &other) 0032 { 0033 d = other.d; 0034 return *this; 0035 } 0036 0037 bool Model::operator==(const Model &other) const 0038 { 0039 return *d == *(other.d); 0040 } 0041 0042 PropertyPtr Model::createProperty(const QString &uri) 0043 { 0044 PropertyPtr prop; 0045 0046 if (d->properties.contains(uri)) { 0047 prop = d->properties[uri]; 0048 } else { 0049 prop = PropertyPtr(new Property(uri)); 0050 prop->setModel(*this); 0051 // if there is a resource object with the same uri, replace 0052 // the resource object by the new property object and reuse the id 0053 if (d->resources.contains(uri)) { 0054 prop->setId(d->resources[uri]->id()); 0055 } 0056 d->addToHashes(prop); 0057 } 0058 0059 return prop; 0060 } 0061 0062 ResourcePtr Model::createResource(const QString &uri) 0063 { 0064 ResourcePtr res; 0065 0066 if (d->resources.contains(uri)) { 0067 res = d->resources[uri]; 0068 } else { 0069 res = ResourcePtr(new Resource(uri)); 0070 res->setModel(*this); 0071 d->addToHashes(res); 0072 } 0073 0074 return res; 0075 } 0076 0077 SequencePtr Model::createSequence(const QString &uri) 0078 { 0079 SequencePtr seq; 0080 0081 if (d->sequences.contains(uri)) { 0082 seq = d->sequences[uri]; 0083 } else { 0084 seq = SequencePtr(new Sequence(uri)); 0085 seq->setModel(*this); 0086 // if there is a resource object with the same uri, replace 0087 // the resource object by the new sequence object and reuse the id 0088 if (d->resources.contains(uri)) { 0089 seq->setId(d->resources[uri]->id()); 0090 } 0091 0092 d->addToHashes(seq); 0093 } 0094 0095 return seq; 0096 } 0097 0098 LiteralPtr Model::createLiteral(const QString &text) 0099 { 0100 LiteralPtr lit(new Literal(text)); 0101 0102 d->addToHashes(lit); 0103 return lit; 0104 } 0105 0106 void Model::removeStatement(StatementPtr statement) 0107 { 0108 removeStatement(statement->subject(), statement->predicate(), statement->object()); 0109 } 0110 0111 void Model::removeStatement(ResourcePtr subject, PropertyPtr predicate, NodePtr object) 0112 { 0113 /* clang-format off */ 0114 QString key = QStringLiteral("%1-%2-%3").arg(QString::number(subject->id()), 0115 QString::number(predicate->id()), 0116 QString::number(object->id())); 0117 /* clang-format on */ 0118 0119 d->removeFromHashes(key); 0120 } 0121 0122 StatementPtr Model::addStatement(ResourcePtr subject, PropertyPtr predicate, NodePtr object) 0123 { 0124 d->init(d); 0125 ResourcePtr subjInternal = subject; 0126 0127 if (!d->nodes.contains(subjInternal->id())) { 0128 subjInternal = ResourcePtr(subject->clone()); 0129 subjInternal->setModel(*this); 0130 d->addToHashes(subjInternal); 0131 } 0132 0133 PropertyPtr predInternal = predicate; 0134 0135 if (!d->nodes.contains(predInternal->id())) { 0136 predInternal = PropertyPtr(predicate->clone()); 0137 predInternal->setModel(*this); 0138 d->addToHashes(predInternal); 0139 } 0140 0141 NodePtr objInternal = object; 0142 0143 if (!d->nodes.contains(objInternal->id())) { 0144 objInternal = NodePtr(object->clone()); 0145 objInternal->setModel(*this); 0146 d->addToHashes(objInternal); 0147 } 0148 0149 // TODO: avoid duplicated stmts with literal objects! 0150 0151 /* clang-format off */ 0152 QString key = QStringLiteral("%1-%2-%3").arg(QString::number(subjInternal->id()), 0153 QString::number(predInternal->id()), 0154 QString::number(objInternal->id())); 0155 /* clang-format on */ 0156 0157 StatementPtr stmt; 0158 0159 if (!d->statements.contains(key)) { 0160 stmt = StatementPtr(new Statement(subjInternal, predInternal, objInternal)); 0161 d->addToHashes(stmt, key); 0162 } else { 0163 stmt = d->statements[key]; 0164 } 0165 0166 return stmt; 0167 } 0168 0169 bool Model::isEmpty() const 0170 { 0171 return d->statements.isEmpty(); 0172 } 0173 0174 bool Model::resourceHasProperty(const Resource *resource, PropertyPtr property) const 0175 { 0176 return d->resourceHasProperty(resource, property); 0177 } 0178 0179 bool Model::ModelPrivate::resourceHasProperty(const Resource *resource, PropertyPtr property) const 0180 { 0181 // resource unknown 0182 if (!resources.contains(resource->uri())) { 0183 return false; 0184 } 0185 0186 const QList<StatementPtr> &stmts = stmtsBySubject[resource->uri()]; 0187 0188 return std::any_of(stmts.cbegin(), stmts.cend(), [&property](const StatementPtr &p) { 0189 return *(p->predicate()) == *property; 0190 }); 0191 } 0192 0193 StatementPtr Model::resourceProperty(const Resource *resource, PropertyPtr property) const 0194 { 0195 return d->resourceProperty(resource, property); 0196 } 0197 0198 StatementPtr Model::ModelPrivate::resourceProperty(const Resource *resource, PropertyPtr property) const 0199 { 0200 const QList<StatementPtr> &stmts = stmtsBySubject[resource->uri()]; 0201 auto it = std::find_if(stmts.cbegin(), stmts.cend(), [&property](const StatementPtr &p) { 0202 return *(p->predicate()) == *property; 0203 }); 0204 return it != stmts.cend() ? *it : nullStatement; 0205 } 0206 0207 QList<StatementPtr> Model::resourceProperties(const Resource *resource, PropertyPtr property) const 0208 { 0209 return d->resourceProperties(resource, property); 0210 } 0211 0212 QList<StatementPtr> Model::ModelPrivate::resourceProperties(const Resource *resource, PropertyPtr property) const 0213 { 0214 QList<StatementPtr> res; 0215 0216 const QList<StatementPtr> &stmts = stmtsBySubject[resource->uri()]; 0217 for (const auto &p : stmts) { 0218 if (*(p->predicate()) == *property) { 0219 res.append(p); 0220 } 0221 } 0222 0223 return res; 0224 } 0225 0226 QList<StatementPtr> Model::statements() const 0227 { 0228 return d->statements.values(); 0229 } 0230 0231 QString Model::debugInfo() const 0232 { 0233 QString info; 0234 for (const StatementPtr &stmtPtr : std::as_const(d->statements)) { 0235 info += QStringLiteral("<%1> <%2> ").arg(stmtPtr->subject()->uri(), stmtPtr->predicate()->uri()); 0236 0237 if (stmtPtr->object()->isLiteral()) { 0238 info += QStringLiteral("\"%1\"\n").arg(stmtPtr->asString()); 0239 } else { 0240 info += QStringLiteral("<%1>\n").arg(stmtPtr->asResource()->uri()); 0241 } 0242 } 0243 0244 return info; 0245 } 0246 0247 QList<ResourcePtr> Model::resourcesWithType(ResourcePtr type) const 0248 { 0249 QList<ResourcePtr> list; 0250 0251 for (const StatementPtr &stmtPtr : std::as_const(d->statements)) { 0252 if (*(stmtPtr->predicate()) == *(RDFVocab::self()->type()) // 0253 && *(stmtPtr->object()) == *type) { 0254 list.append(stmtPtr->subject()); 0255 } 0256 } 0257 0258 return list; 0259 } 0260 0261 NodePtr Model::nodeByID(uint id) const 0262 { 0263 return d->nodeByID(id); 0264 } 0265 0266 NodePtr Model::ModelPrivate::nodeByID(uint _id) const 0267 { 0268 if (!nodes.contains(_id)) { 0269 return nullLiteral; 0270 } else { 0271 return nodes.value(_id); 0272 } 0273 } 0274 0275 ResourcePtr Model::resourceByID(uint id) const 0276 { 0277 return d->resourceByID(id); 0278 } 0279 0280 ResourcePtr Model::ModelPrivate::resourceByID(uint _id) const 0281 { 0282 if (!nodes.contains(_id)) { 0283 return nullResource; 0284 } else { 0285 NodePtr node = nodes.value(_id); 0286 if (node->isResource()) { 0287 return node.staticCast<Resource>(); 0288 } else { 0289 return nullResource; 0290 } 0291 } 0292 } 0293 0294 PropertyPtr Model::propertyByID(uint id) const 0295 { 0296 return d->propertyByID(id); 0297 } 0298 0299 PropertyPtr Model::ModelPrivate::propertyByID(uint _id) const 0300 { 0301 if (!nodes.contains(_id)) { 0302 return nullProperty; 0303 } else { 0304 NodePtr node = nodes.value(_id); 0305 if (node->isProperty()) { 0306 return node.staticCast<Property>(); 0307 } else { 0308 return nullProperty; 0309 } 0310 } 0311 } 0312 0313 LiteralPtr Model::literalByID(uint id) const 0314 { 0315 return d->literalByID(id); 0316 } 0317 0318 LiteralPtr Model::ModelPrivate::literalByID(uint _id) const 0319 { 0320 if (!nodes.contains(_id)) { 0321 return nullLiteral; 0322 } else { 0323 NodePtr node = nodes.value(_id); 0324 if (node->isLiteral()) { 0325 return node.staticCast<Literal>(); 0326 } else { 0327 return nullLiteral; 0328 } 0329 } 0330 } 0331 0332 } // namespace RDF 0333 } // namespace Syndication