1 /* 2 SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org> 3 4 SPDX-License-Identifier: LGPL-2.0-or-later 5 */ 6 7 #include "extractordocumentnode.h" 8 #include "extractordocumentprocessor.h" 9 #include "extractorfilter.h" 10 #include "extractorresult.h" 11 12 #include <QJSEngine> 13 #include <QJSValue> 14 15 #include <cassert> 16 17 using namespace KItinerary; 18 19 namespace KItinerary { 20 class ExtractorDocumentNodePrivate 21 { 22 public: 23 std::weak_ptr<ExtractorDocumentNodePrivate> parent; 24 std::vector<ExtractorDocumentNode> childNodes; 25 QString mimeType; 26 QVariant content; 27 QDateTime contextDateTime; 28 const ExtractorDocumentProcessor *processor; 29 ExtractorResult result; 30 QVariant location; 31 QJSEngine *m_jsEngine = nullptr; 32 33 QJSEngine *jsEngine() const; 34 }; 35 } 36 jsEngine() const37QJSEngine* ExtractorDocumentNodePrivate::jsEngine() const 38 { 39 if (m_jsEngine) { 40 return m_jsEngine; 41 } 42 const auto p = parent.lock(); 43 return p ? p->jsEngine() : nullptr; 44 } 45 ExtractorDocumentNode()46ExtractorDocumentNode::ExtractorDocumentNode() 47 : d(std::make_shared<ExtractorDocumentNodePrivate>()) 48 { 49 } 50 ExtractorDocumentNode(const std::shared_ptr<ExtractorDocumentNodePrivate> & dd)51ExtractorDocumentNode::ExtractorDocumentNode(const std::shared_ptr<ExtractorDocumentNodePrivate> &dd) 52 : d(dd ? dd : std::make_shared<ExtractorDocumentNodePrivate>()) 53 { 54 } 55 56 ExtractorDocumentNode::ExtractorDocumentNode(const ExtractorDocumentNode &other) = default; 57 ExtractorDocumentNode::ExtractorDocumentNode(ExtractorDocumentNode &&other) = default; 58 ~ExtractorDocumentNode()59ExtractorDocumentNode::~ExtractorDocumentNode() 60 { 61 if (d && d.use_count() == 1 && d->processor) { 62 d->processor->destroyNode(*this); 63 } 64 } 65 operator =(const ExtractorDocumentNode & other)66ExtractorDocumentNode& ExtractorDocumentNode::operator=(const ExtractorDocumentNode &other) 67 { 68 if (d && d.use_count() == 1 && d->processor) { 69 d->processor->destroyNode(*this); 70 } 71 d = other.d; 72 return *this; 73 } 74 operator =(ExtractorDocumentNode && other)75ExtractorDocumentNode& ExtractorDocumentNode::operator=(ExtractorDocumentNode &&other) 76 { 77 if (d && d.use_count() == 1 && d->processor) { 78 d->processor->destroyNode(*this); 79 } 80 d = std::move(other.d); 81 return *this; 82 } 83 isNull() const84bool ExtractorDocumentNode::isNull() const 85 { 86 return d->content.isNull() || !d->processor || d->mimeType.isEmpty(); 87 } 88 parent() const89ExtractorDocumentNode ExtractorDocumentNode::parent() const 90 { 91 return ExtractorDocumentNode(d->parent.lock()); 92 } 93 setParent(const ExtractorDocumentNode & parent)94void ExtractorDocumentNode::setParent(const ExtractorDocumentNode &parent) 95 { 96 d->parent = parent.d; 97 } 98 mimeType() const99QString ExtractorDocumentNode::mimeType() const 100 { 101 return d->mimeType; 102 } 103 setMimeType(const QString & mimeType)104void ExtractorDocumentNode::setMimeType(const QString &mimeType) 105 { 106 d->mimeType = mimeType; 107 } 108 content() const109QVariant ExtractorDocumentNode::content() const 110 { 111 return d->content; 112 } 113 setContent(const QVariant & content)114void ExtractorDocumentNode::setContent(const QVariant &content) 115 { 116 d->content = content; 117 } 118 processor() const119const ExtractorDocumentProcessor* ExtractorDocumentNode::processor() const 120 { 121 return d->processor; 122 } 123 setProcessor(const ExtractorDocumentProcessor * processor)124void ExtractorDocumentNode::setProcessor(const ExtractorDocumentProcessor *processor) 125 { 126 assert(!d->processor); 127 d->processor = processor; 128 } 129 childNodes() const130const std::vector<ExtractorDocumentNode>& ExtractorDocumentNode::childNodes() const 131 { 132 return d->childNodes; 133 } 134 appendChild(ExtractorDocumentNode & child)135void ExtractorDocumentNode::appendChild(ExtractorDocumentNode &child) 136 { 137 if (child.isNull()) { 138 return; 139 } 140 child.setParent(*this); 141 d->childNodes.push_back(child); 142 } 143 result() const144ExtractorResult ExtractorDocumentNode::result() const 145 { 146 return d->result; 147 } 148 addResult(ExtractorResult && result)149void ExtractorDocumentNode::addResult(ExtractorResult &&result) 150 { 151 d->result.append(std::move(result)); 152 } 153 setResult(ExtractorResult && result)154void ExtractorDocumentNode::setResult(ExtractorResult &&result) 155 { 156 d->result = std::move(result); 157 } 158 contextDateTime() const159QDateTime ExtractorDocumentNode::contextDateTime() const 160 { 161 if (!d->contextDateTime.isValid() && !d->parent.expired()) { 162 return parent().contextDateTime(); 163 } 164 return d->contextDateTime; 165 } 166 setContextDateTime(const QDateTime & contextDateTime)167void ExtractorDocumentNode::setContextDateTime(const QDateTime &contextDateTime) 168 { 169 d->contextDateTime = contextDateTime; 170 } 171 location() const172QVariant ExtractorDocumentNode::location() const 173 { 174 if (d->location.isNull() && !d->parent.expired()) { 175 return parent().location(); 176 } 177 return d->location; 178 } 179 setLocation(const QVariant & location)180void ExtractorDocumentNode::setLocation(const QVariant &location) 181 { 182 d->location = location; 183 } 184 jsonLdResult() const185QJsonArray ExtractorDocumentNode::jsonLdResult() const 186 { 187 return d->result.jsonLdResult(); 188 } 189 childNodesVariant() const190QVariantList ExtractorDocumentNode::childNodesVariant() const 191 { 192 QVariantList l; 193 l.reserve(d->childNodes.size()); 194 std::transform(d->childNodes.begin(), d->childNodes.end(), std::back_inserter(l), [](const auto &c) { return QVariant::fromValue(c); }); 195 return l; 196 } 197 contentJsValue() const198QJSValue ExtractorDocumentNode::contentJsValue() const 199 { 200 if (!d || !d->processor) { 201 return {}; 202 } 203 if (auto jsEngine = d->jsEngine()) { 204 return d->processor->contentToScriptValue(*this, jsEngine); 205 } 206 return {}; 207 } 208 setScriptEngine(QJSEngine * jsEngine) const209void ExtractorDocumentNode::setScriptEngine(QJSEngine* jsEngine) const 210 { 211 if (!d->parent.expired()) { 212 parent().setScriptEngine(jsEngine); 213 } else { 214 d->m_jsEngine = jsEngine; 215 } 216 } 217 findChildNodes(const QJSValue & jsFilter) const218QVariantList ExtractorDocumentNode::findChildNodes(const QJSValue &jsFilter) const 219 { 220 const auto filter = ExtractorFilter::fromJSValue(jsFilter); 221 std::vector<ExtractorDocumentNode> matches; 222 filter.allMatches(*this, matches); 223 224 QVariantList l; 225 l.reserve(matches.size()); 226 std::transform(matches.begin(), matches.end(), std::back_inserter(l), [](const auto &c) { return QVariant::fromValue(c); }); 227 return l; 228 } 229 230 #include "moc_extractordocumentnode.cpp" 231