File indexing completed on 2024-12-29 04:49:57
0001 /* 0002 SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "extractordocumentnode.h" 0008 #include "extractordocumentprocessor.h" 0009 #include "extractorfilter.h" 0010 #include "extractorresult.h" 0011 0012 #include <QJSEngine> 0013 #include <QJSValue> 0014 0015 #include <cassert> 0016 0017 using namespace KItinerary; 0018 0019 namespace KItinerary { 0020 class ExtractorDocumentNodePrivate 0021 { 0022 public: 0023 std::weak_ptr<ExtractorDocumentNodePrivate> parent; 0024 std::vector<ExtractorDocumentNode> childNodes; 0025 QString mimeType; 0026 QVariant content; 0027 QDateTime contextDateTime; 0028 const ExtractorDocumentProcessor *processor; 0029 ExtractorResult result; 0030 QVariant location; 0031 QJSEngine *m_jsEngine = nullptr; 0032 QString usedExtractor; 0033 0034 QJSEngine *jsEngine() const; 0035 }; 0036 } 0037 0038 QJSEngine* ExtractorDocumentNodePrivate::jsEngine() const 0039 { 0040 if (m_jsEngine) { 0041 return m_jsEngine; 0042 } 0043 const auto p = parent.lock(); 0044 return p ? p->jsEngine() : nullptr; 0045 } 0046 0047 ExtractorDocumentNode::ExtractorDocumentNode() 0048 : d(std::make_shared<ExtractorDocumentNodePrivate>()) 0049 { 0050 } 0051 0052 ExtractorDocumentNode::ExtractorDocumentNode(const std::shared_ptr<ExtractorDocumentNodePrivate> &dd) 0053 : d(dd ? dd : std::make_shared<ExtractorDocumentNodePrivate>()) 0054 { 0055 } 0056 0057 ExtractorDocumentNode::ExtractorDocumentNode(const ExtractorDocumentNode &other) = default; 0058 ExtractorDocumentNode::ExtractorDocumentNode(ExtractorDocumentNode &&other) = default; 0059 0060 ExtractorDocumentNode::~ExtractorDocumentNode() 0061 { 0062 if (d && d.use_count() == 1 && d->processor) { 0063 d->processor->destroyNode(*this); 0064 } 0065 } 0066 0067 ExtractorDocumentNode& ExtractorDocumentNode::operator=(const ExtractorDocumentNode &other) 0068 { 0069 if (d && d.use_count() == 1 && d->processor) { 0070 d->processor->destroyNode(*this); 0071 } 0072 d = other.d; 0073 return *this; 0074 } 0075 0076 ExtractorDocumentNode& ExtractorDocumentNode::operator=(ExtractorDocumentNode &&other) 0077 { 0078 if (d && d.use_count() == 1 && d->processor) { 0079 d->processor->destroyNode(*this); 0080 } 0081 d = std::move(other.d); 0082 return *this; 0083 } 0084 0085 bool ExtractorDocumentNode::operator==(const ExtractorDocumentNode &other) const 0086 { 0087 return d.get() == other.d.get(); 0088 } 0089 0090 bool ExtractorDocumentNode::isNull() const 0091 { 0092 return d->content.isNull() || !d->processor || d->mimeType.isEmpty(); 0093 } 0094 0095 ExtractorDocumentNode ExtractorDocumentNode::parent() const 0096 { 0097 return ExtractorDocumentNode(d->parent.lock()); 0098 } 0099 0100 void ExtractorDocumentNode::setParent(const ExtractorDocumentNode &parent) 0101 { 0102 d->parent = parent.d; 0103 } 0104 0105 QString ExtractorDocumentNode::mimeType() const 0106 { 0107 return d->mimeType; 0108 } 0109 0110 void ExtractorDocumentNode::setMimeType(const QString &mimeType) 0111 { 0112 d->mimeType = mimeType; 0113 } 0114 0115 QVariant ExtractorDocumentNode::content() const 0116 { 0117 return d->content; 0118 } 0119 0120 void ExtractorDocumentNode::setContent(const QVariant &content) 0121 { 0122 d->content = content; 0123 } 0124 0125 const ExtractorDocumentProcessor* ExtractorDocumentNode::processor() const 0126 { 0127 return d->processor; 0128 } 0129 0130 void ExtractorDocumentNode::setProcessor(const ExtractorDocumentProcessor *processor) 0131 { 0132 assert(!d->processor); 0133 d->processor = processor; 0134 } 0135 0136 const std::vector<ExtractorDocumentNode>& ExtractorDocumentNode::childNodes() const 0137 { 0138 return d->childNodes; 0139 } 0140 0141 void ExtractorDocumentNode::appendChild(ExtractorDocumentNode &child) 0142 { 0143 if (child.isNull()) { 0144 return; 0145 } 0146 child.setParent(*this); 0147 d->childNodes.push_back(child); 0148 } 0149 0150 ExtractorResult ExtractorDocumentNode::result() const 0151 { 0152 return d->result; 0153 } 0154 0155 void ExtractorDocumentNode::addResult(ExtractorResult &&result) 0156 { 0157 d->result.append(std::move(result)); 0158 } 0159 0160 void ExtractorDocumentNode::setResult(ExtractorResult &&result) 0161 { 0162 d->result = std::move(result); 0163 } 0164 0165 QDateTime ExtractorDocumentNode::contextDateTime() const 0166 { 0167 if (!d->contextDateTime.isValid() && !d->parent.expired()) { 0168 return parent().contextDateTime(); 0169 } 0170 return d->contextDateTime; 0171 } 0172 0173 void ExtractorDocumentNode::setContextDateTime(const QDateTime &contextDateTime) 0174 { 0175 d->contextDateTime = contextDateTime; 0176 } 0177 0178 QVariant ExtractorDocumentNode::location() const 0179 { 0180 if (d->location.isNull() && !d->parent.expired()) { 0181 return parent().location(); 0182 } 0183 return d->location; 0184 } 0185 0186 void ExtractorDocumentNode::setLocation(const QVariant &location) 0187 { 0188 d->location = location; 0189 } 0190 0191 QJsonArray ExtractorDocumentNode::jsonLdResult() const 0192 { 0193 return d->result.jsonLdResult(); 0194 } 0195 0196 QVariantList ExtractorDocumentNode::childNodesVariant() const 0197 { 0198 QVariantList l; 0199 l.reserve(d->childNodes.size()); 0200 std::transform(d->childNodes.begin(), d->childNodes.end(), std::back_inserter(l), [](const auto &c) { return QVariant::fromValue(c); }); 0201 return l; 0202 } 0203 0204 QJSValue ExtractorDocumentNode::contentJsValue() const 0205 { 0206 if (!d || !d->processor) { 0207 return {}; 0208 } 0209 if (auto jsEngine = d->jsEngine()) { 0210 return d->processor->contentToScriptValue(*this, jsEngine); 0211 } 0212 return {}; 0213 } 0214 0215 void ExtractorDocumentNode::setScriptEngine(QJSEngine* jsEngine) const 0216 { 0217 if (!d->parent.expired()) { 0218 parent().setScriptEngine(jsEngine); 0219 } else { 0220 d->m_jsEngine = jsEngine; 0221 } 0222 } 0223 0224 QVariantList ExtractorDocumentNode::findChildNodes(const QJSValue &jsFilter) const 0225 { 0226 const auto filter = ExtractorFilter::fromJSValue(jsFilter); 0227 std::vector<ExtractorDocumentNode> matches; 0228 filter.allMatches(*this, matches); 0229 0230 QVariantList l; 0231 l.reserve(matches.size()); 0232 std::transform(matches.begin(), matches.end(), std::back_inserter(l), [](const auto &c) { return QVariant::fromValue(c); }); 0233 return l; 0234 } 0235 0236 QString ExtractorDocumentNode::usedExtractor() const 0237 { 0238 return d->usedExtractor; 0239 } 0240 0241 void ExtractorDocumentNode::setUsedExtractor(const QString &usedExtractor) 0242 { 0243 d->usedExtractor = usedExtractor; 0244 } 0245 0246 #include "moc_extractordocumentnode.cpp"