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"