From eac288d02cafc49c5a14fa27bb449c33eb4b1803 Mon Sep 17 00:00:00 2001 From: Tomaž Vajngerl Date: Mon, 6 Sep 2021 14:17:01 +0900 Subject: indexing: support JSON and XML as input for SearchResultLocator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JSON is much easier to deal with when using REST and javascript, so support both. Change-Id: I61035452d9a7ba889ac355a42201d79b9fafec6f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121742 Tested-by: Tomaž Vajngerl Reviewed-by: Tomaž Vajngerl --- sw/source/core/model/SearchResultLocator.cxx | 98 ++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 28 deletions(-) (limited to 'sw/source/core/model') diff --git a/sw/source/core/model/SearchResultLocator.cxx b/sw/source/core/model/SearchResultLocator.cxx index a0e405b2ed33..089859683cb4 100644 --- a/sw/source/core/model/SearchResultLocator.cxx +++ b/sw/source/core/model/SearchResultLocator.cxx @@ -20,6 +20,8 @@ #include #include +#include + #include #include @@ -30,7 +32,7 @@ void SearchResultLocator::findOne(LocationResult& rResult, SearchIndexData const if (rSearchIndexData.meType == NodeType::WriterNode) { SwNodes const& rNodes = mpDocument->GetNodes(); - if (rSearchIndexData.mnNodeIndex >= rNodes.Count()) + if (rSearchIndexData.mnNodeIndex >= sal_Int32(rNodes.Count())) return; SwNode* pNode = rNodes[rSearchIndexData.mnNodeIndex]; @@ -85,51 +87,91 @@ LocationResult SearchResultLocator::find(std::vector const& rSe return aResult; } -LocationResult SearchResultLocator::findForPayload(const char* pPayload) +/** Trying to parse the payload as JSON + * + * Returns true if parsing was successful and the payload was identified as JSON, else false + */ +bool SearchResultLocator::tryParseJSON(const char* pPayload, + std::vector& rDataVector) { - LocationResult aResult; + boost::property_tree::ptree aTree; + std::stringstream aStream(pPayload); + try + { + boost::property_tree::read_json(aStream, aTree); + } + catch (const boost::property_tree::json_parser_error& /*exception*/) + { + return false; + } + for (auto& rEachNode : boost::make_iterator_range(aTree.equal_range(""))) + { + auto const& rEach = rEachNode.second; + + sal_Int32 nType = rEach.get("type", 0); + sal_Int32 nIndex = rEach.get("index", -1); + + // Don't add search data elements that don't have valid data + if (nType > 0 && nIndex >= 0) + rDataVector.emplace_back(sw::search::NodeType(nType), nIndex); + } + + return true; +} + +/** Trying to parse the payload as XML + * + * Returns true if parsing was successful and the payload was identified as XML, else false + */ +bool SearchResultLocator::tryParseXML(const char* pPayload, + std::vector& rDataVector) +{ const OString aPayloadString(pPayload); SvMemoryStream aStream(const_cast(aPayloadString.getStr()), aPayloadString.getLength(), StreamMode::READ); + tools::XmlWalker aWalker; if (!aWalker.open(&aStream)) - return aResult; + return false; - if (aWalker.name() == "indexing") + if (aWalker.name() != "indexing") + return true; + + aWalker.children(); + while (aWalker.isValid()) { - std::vector aDataVector; - aWalker.children(); - while (aWalker.isValid()) + if (aWalker.name() == "paragraph") { - if (aWalker.name() == "paragraph") - { - OString sType = aWalker.attribute("type"); - OString sIndex = aWalker.attribute("index"); + OString sType = aWalker.attribute("type"); + OString sIndex = aWalker.attribute("index"); - if (!sType.isEmpty() && !sIndex.isEmpty()) - { - sw::search::SearchIndexData aData; - aData.mnNodeIndex = sIndex.toInt32(); - aData.meType = sw::search::NodeType(sType.toInt32()); + if (!sType.isEmpty() && !sIndex.isEmpty()) + { + sw::search::SearchIndexData aData; + aData.mnNodeIndex = sIndex.toInt32(); + aData.meType = sw::search::NodeType(sType.toInt32()); - aDataVector.push_back(aData); - } + rDataVector.push_back(aData); } - aWalker.next(); - } - aWalker.parent(); - - if (!aDataVector.empty()) - { - for (auto const& rSearchIndexData : aDataVector) - findOne(aResult, rSearchIndexData); } + aWalker.next(); } + aWalker.parent(); + return true; +} - return aResult; +LocationResult SearchResultLocator::findForPayload(const char* pPayload) +{ + std::vector aDataVector; + + // Try parse the payload as JSON, if not recognised as JSON, try parse + // it as XML + tryParseJSON(pPayload, aDataVector) || tryParseXML(pPayload, aDataVector); + + return find(aDataVector); } } // end sw namespace -- cgit v1.2.3