summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Lippert <drtl@fastmail.fm>2014-06-01 14:18:39 +0200
committerCaolán McNamara <caolanm@redhat.com>2014-06-05 16:26:39 +0000
commit94b296d5416dd71d721ad16216b50bce79e3dc04 (patch)
treea53b0a660ce6646c5767865fe85af03bfaba3b3e
parente5345f62bf525b6258736f1ce11a61b5e638e0ff (diff)
Unittest link generation for table of contents.
The logic was moved to a separate class and unittested. Conflicts: sw/inc/ToxTextGenerator.hxx Change-Id: I0e4475f5e2950cdfdfb07b89128c4ce1d6af3f22 Reviewed-on: https://gerrit.libreoffice.org/9609 Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--sw/CppunitTest_sw_tox.mk1
-rw-r--r--sw/Library_sw.mk1
-rw-r--r--sw/inc/ToxLinkProcessor.hxx86
-rw-r--r--sw/inc/ToxTextGenerator.hxx12
-rw-r--r--sw/qa/cppunit/tox/test_ToxLinkProcessor.cxx133
-rw-r--r--sw/source/core/tox/ToxLinkProcessor.cxx70
-rw-r--r--sw/source/core/tox/ToxTextGenerator.cxx66
7 files changed, 312 insertions, 57 deletions
diff --git a/sw/CppunitTest_sw_tox.mk b/sw/CppunitTest_sw_tox.mk
index f372442390da..7911de3a1335 100644
--- a/sw/CppunitTest_sw_tox.mk
+++ b/sw/CppunitTest_sw_tox.mk
@@ -14,6 +14,7 @@ $(eval $(call gb_CppunitTest_CppunitTest,sw_tox_test))
$(eval $(call gb_CppunitTest_add_exception_objects,sw_tox_test, \
sw/qa/cppunit/tox/test_ToxWhitespaceStripper \
+ sw/qa/cppunit/tox/test_ToxLinkProcessor \
))
$(eval $(call gb_CppunitTest_use_libraries,sw_tox_test, \
diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk
index a7500ad832e3..c073564030a1 100644
--- a/sw/Library_sw.mk
+++ b/sw/Library_sw.mk
@@ -388,6 +388,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\
sw/source/core/tox/tox \
sw/source/core/tox/toxhlp \
sw/source/core/tox/txmsrt \
+ sw/source/core/tox/ToxLinkProcessor \
sw/source/core/tox/ToxTextGenerator \
sw/source/core/tox/ToxWhitespaceStripper \
sw/source/core/txtnode/SwGrammarContact \
diff --git a/sw/inc/ToxLinkProcessor.hxx b/sw/inc/ToxLinkProcessor.hxx
new file mode 100644
index 000000000000..5a4546562ec6
--- /dev/null
+++ b/sw/inc/ToxLinkProcessor.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SW_TOXLINKPROCESSOR_HXX_
+#define SW_TOXLINKPROCESSOR_HXX_
+
+#include "fmtinfmt.hxx"
+#include "rtl/ustring.hxx"
+
+#include <vector>
+
+class SwTxtNode;
+
+class ToxLinkProcessorTest;
+
+namespace sw {
+
+/** A helper class for ToxTextGenerator.
+ * It collects information about encountered link tokens and allows access in a processed form.
+ */
+class SW_DLLPUBLIC ToxLinkProcessor {
+public:
+ ToxLinkProcessor() {;}
+ virtual ~ToxLinkProcessor() {;}
+
+ void
+ StartNewLink(sal_Int32 startPosition, const OUString& characterStyle);
+
+ /** Close a link which has been found during processing.
+ *
+ * @throw std::runtime_error If there are no open links.
+ */
+ void
+ CloseLink(sal_Int32 endPosition, const OUString& url);
+
+ /** Insert the found links as attributes to a text node */
+ void
+ InsertLinkAttributes(SwTxtNode& node);
+
+private:
+ /** Obtain the pool id which belongs to a character style.
+ *
+ * @internal
+ * This method is overridden in the unittests. You should not override it yourself.
+ */
+ virtual sal_uInt16
+ ObtainPoolId(const OUString& characterStyle) const;
+
+ /** Information about a started link */
+ struct StartedLink {
+ StartedLink(sal_Int32 startPosition, OUString characterStyle) :
+ mStartPosition(startPosition), mCharacterStyle(characterStyle) {
+ ;
+ }
+ sal_Int32 mStartPosition;
+ OUString mCharacterStyle;
+ };
+
+ /** A link that has been encountered while parsing a tox.
+ * A link is closed if it has both a start and an end token.
+ */
+ struct ClosedLink {
+ ClosedLink(const OUString& url, sal_Int32 startPosition, sal_Int32 endPosition) :
+ mINetFmt(url, OUString()), mStartTextPos(endPosition), mEndTextPos(startPosition) {
+ }
+ SwFmtINetFmt mINetFmt;
+ sal_Int32 mStartTextPos;
+ sal_Int32 mEndTextPos;
+ };
+
+ std::vector<ClosedLink> mClosedLinks;
+
+ std::vector<StartedLink> mStartedLinks;
+
+ friend class ::ToxLinkProcessorTest;
+};
+
+}
+
+#endif /* SW_TOXLINKPROCESSOR_HXX_ */
diff --git a/sw/inc/ToxTextGenerator.hxx b/sw/inc/ToxTextGenerator.hxx
index e64c8b678d90..d83736b3eb31 100644
--- a/sw/inc/ToxTextGenerator.hxx
+++ b/sw/inc/ToxTextGenerator.hxx
@@ -22,6 +22,7 @@
#include "sal/types.h"
#include "swdllapi.h"
+#include <boost/shared_ptr.hpp>
#include <vector>
class SwDoc;
@@ -31,12 +32,15 @@ struct SwTOXSortTabBase;
namespace sw {
+class ToxLinkProcessor;
+
class SW_DLLPUBLIC ToxTextGenerator
{
public:
- ToxTextGenerator(const SwForm& toxForm)
- : mToxForm(toxForm)
- {}
+ ToxTextGenerator(const SwForm& toxForm);
+
+ ~ToxTextGenerator();
+
/** Generate the text for an entry of a table of X (X is, e.g., content).
*
* This method will process the entries in @p entries, starting at @p indexOfEntryToProcess and
@@ -47,9 +51,9 @@ public:
sal_uInt16 indexOfEntryToProcess, sal_uInt16 numberOfEntriesToProcess,
sal_uInt32 _nTOXSectNdIdx, const SwPageDesc* _pDefaultPageDesc);
-
private:
const SwForm& mToxForm;
+ boost::shared_ptr<ToxLinkProcessor> mLinkProcessor;
};
}
diff --git a/sw/qa/cppunit/tox/test_ToxLinkProcessor.cxx b/sw/qa/cppunit/tox/test_ToxLinkProcessor.cxx
new file mode 100644
index 000000000000..9dc621f4b0de
--- /dev/null
+++ b/sw/qa/cppunit/tox/test_ToxLinkProcessor.cxx
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <stdexcept>
+
+#include <sal/types.h>
+
+#include <rtl/ustring.hxx>
+
+#include <ToxLinkProcessor.hxx>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+using namespace sw;
+
+class ToxLinkProcessorTest : public CppUnit::TestFixture
+{
+ void ExceptionIsThrownIfTooManyLinksAreClosed();
+ void AddingAndClosingTwoLinksResultsInTwoClosedLinks();
+ void LinkIsCreatedCorrectly();
+ void LinkSequenceIsPreserved();
+
+ CPPUNIT_TEST_SUITE(ToxLinkProcessorTest);
+ CPPUNIT_TEST(ExceptionIsThrownIfTooManyLinksAreClosed);
+ CPPUNIT_TEST(AddingAndClosingTwoLinksResultsInTwoClosedLinks);
+ CPPUNIT_TEST(LinkIsCreatedCorrectly);
+ CPPUNIT_TEST(LinkSequenceIsPreserved);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ static const OUString STYLE_NAME_1;
+ static const OUString STYLE_NAME_2;
+ static const sal_uInt16 POOL_ID_1;
+ static const sal_uInt16 POOL_ID_2;
+ static const OUString URL_1;
+ static const OUString URL_2;
+};
+
+const OUString ToxLinkProcessorTest::STYLE_NAME_1 = "anyStyle1";
+const OUString ToxLinkProcessorTest::STYLE_NAME_2 = "anyStyle2";
+const OUString ToxLinkProcessorTest::URL_1 = "anyUrl1";
+const OUString ToxLinkProcessorTest::URL_2 = "anyUrl2";
+const sal_uInt16 ToxLinkProcessorTest::POOL_ID_1 = 42;
+const sal_uInt16 ToxLinkProcessorTest::POOL_ID_2 = 43;
+
+void
+ToxLinkProcessorTest::ExceptionIsThrownIfTooManyLinksAreClosed()
+{
+ ToxLinkProcessor sut;
+ sut.StartNewLink(0, STYLE_NAME_1);
+ sut.CloseLink(1, URL_1);
+ CPPUNIT_ASSERT_THROW(sut.CloseLink(1, URL_1), std::runtime_error);
+}
+
+void
+ToxLinkProcessorTest::AddingAndClosingTwoLinksResultsInTwoClosedLinks()
+{
+ ToxLinkProcessor sut;
+ sut.StartNewLink(0, STYLE_NAME_1);
+ sut.StartNewLink(0, STYLE_NAME_2);
+ sut.CloseLink(1, URL_1);
+ sut.CloseLink(1, URL_2);
+ CPPUNIT_ASSERT_EQUAL(2u, static_cast<unsigned>(sut.mClosedLinks.size()));
+ CPPUNIT_ASSERT_MESSAGE("no links are open", sut.mStartedLinks.empty());
+}
+
+class ToxLinkProcessorWithOverriddenObtainPoolId : public ToxLinkProcessor {
+public:
+ /*virtual*/ sal_uInt16
+ ObtainPoolId(const OUString& characterStyle) const {
+ if (characterStyle == ToxLinkProcessorTest::STYLE_NAME_1) {
+ return ToxLinkProcessorTest::POOL_ID_1;
+ }
+ if (characterStyle == ToxLinkProcessorTest::STYLE_NAME_2) {
+ return ToxLinkProcessorTest::POOL_ID_2;
+ }
+ return 0;
+ }
+};
+
+void
+ToxLinkProcessorTest::LinkIsCreatedCorrectly()
+{
+ // obtainpoolid needs to be overridden to check what we are
+ ToxLinkProcessorWithOverriddenObtainPoolId sut;
+
+ sut.StartNewLink(0, STYLE_NAME_1);
+ sut.CloseLink(1, URL_1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Style is stored correctly in link", STYLE_NAME_1, sut.mClosedLinks.at(0).mINetFmt.GetVisitedFmt());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Url is stored correctly in link", URL_1, sut.mClosedLinks.at(0).mINetFmt.GetValue());
+}
+
+void
+ToxLinkProcessorTest::LinkSequenceIsPreserved()
+{
+
+ // obtainpoolid needs to be overridden to check what we are
+ ToxLinkProcessorWithOverriddenObtainPoolId sut;
+
+ sut.StartNewLink(0, STYLE_NAME_1);
+ sut.StartNewLink(0, STYLE_NAME_2);
+ sut.CloseLink(1, URL_2);
+ sut.CloseLink(1, URL_1);
+
+ // check first closed element
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Style is stored correctly in link",
+ STYLE_NAME_2, sut.mClosedLinks.at(0).mINetFmt.GetVisitedFmt());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Pool id is stored correctly in link",
+ POOL_ID_2, sut.mClosedLinks.at(0).mINetFmt.GetINetFmtId());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Url is stored correctly in link",
+ URL_2, sut.mClosedLinks.at(0).mINetFmt.GetValue());
+ // check second closed element
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Style is stored correctly in link",
+ STYLE_NAME_1, sut.mClosedLinks.at(1).mINetFmt.GetVisitedFmt());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Pool id is stored correctly in link",
+ POOL_ID_1, sut.mClosedLinks.at(1).mINetFmt.GetINetFmtId());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Url is stored correctly in link",
+ URL_1, sut.mClosedLinks.at(1).mINetFmt.GetValue());
+}
+
+// Put the test suite in the registry
+CPPUNIT_TEST_SUITE_REGISTRATION(ToxLinkProcessorTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/tox/ToxLinkProcessor.cxx b/sw/source/core/tox/ToxLinkProcessor.cxx
new file mode 100644
index 000000000000..e236f008e2d0
--- /dev/null
+++ b/sw/source/core/tox/ToxLinkProcessor.cxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ToxLinkProcessor.hxx"
+
+#include "SwStyleNameMapper.hxx"
+#include "ndtxt.hxx"
+
+#include <boost/foreach.hpp>
+#include <stdexcept>
+
+namespace sw {
+
+void
+ToxLinkProcessor::StartNewLink(sal_Int32 startPosition, const OUString& characterStyle)
+{
+ mStartedLinks.push_back(StartedLink(startPosition, characterStyle));
+}
+
+void
+ToxLinkProcessor::CloseLink(sal_Int32 endPosition, const OUString& url)
+{
+ if (mStartedLinks.empty()) {
+ throw std::runtime_error("ToxLinkProcessor: More calls for CloseLink() than open links exist.");
+ }
+ StartedLink startedLink = mStartedLinks.back();
+ mStartedLinks.pop_back();
+
+ if (url.isEmpty()) {
+ return;
+ }
+
+ ClosedLink closedLink(url, startedLink.mStartPosition, endPosition);
+
+ const OUString& characterStyle = startedLink.mCharacterStyle;
+ sal_uInt16 poolId = ObtainPoolId(characterStyle);
+ closedLink.mINetFmt.SetVisitedFmtAndId(characterStyle, poolId);
+ closedLink.mINetFmt.SetINetFmtAndId(characterStyle, poolId);
+
+ mClosedLinks.push_back(closedLink);
+}
+
+sal_uInt16
+ToxLinkProcessor::ObtainPoolId(const OUString& characterStyle) const
+{
+ if (characterStyle.isEmpty()) {
+ return USHRT_MAX;
+ }
+ else {
+ return SwStyleNameMapper::GetPoolIdFromUIName(characterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
+ }
+}
+
+
+void
+ToxLinkProcessor::InsertLinkAttributes(SwTxtNode& node)
+{
+ BOOST_FOREACH(ClosedLink& clink, mClosedLinks) {
+ node.InsertItem(clink.mINetFmt, clink.mStartTextPos, clink.mEndTextPos);
+ }
+}
+
+}
+
diff --git a/sw/source/core/tox/ToxTextGenerator.cxx b/sw/source/core/tox/ToxTextGenerator.cxx
index 8554c889ef8e..86e8777781bb 100644
--- a/sw/source/core/tox/ToxTextGenerator.cxx
+++ b/sw/source/core/tox/ToxTextGenerator.cxx
@@ -34,22 +34,12 @@
#include "DocumentSettingManager.hxx"
#include "SwStyleNameMapper.hxx"
#include "ToxWhitespaceStripper.hxx"
+#include "ToxLinkProcessor.hxx"
#include "editeng/tstpitem.hxx"
#include "editeng/lrspitem.hxx"
#include "rtl/ustring.hxx"
-struct LinkStruct
-{
- SwFmtINetFmt aINetFmt;
- sal_Int32 nStartTextPos, nEndTextPos;
-
- LinkStruct( const OUString& rURL, sal_Int32 nStart, sal_Int32 nEnd )
- : aINetFmt( rURL, OUString()),
- nStartTextPos( nStart),
- nEndTextPos(nEnd) {}
-};
-
/// Generate String according to the Form and remove the
/// special characters 0-31 and 255.
static OUString lcl_GetNumString( const SwTOXSortTabBase& rBase, bool bUsePrefix, sal_uInt8 nLevel )
@@ -70,18 +60,22 @@ static OUString lcl_GetNumString( const SwTOXSortTabBase& rBase, bool bUsePrefix
return sRet;
}
-typedef std::vector<LinkStruct*> LinkStructArr;
-
namespace sw {
+ToxTextGenerator::ToxTextGenerator(const SwForm& toxForm)
+:mToxForm(toxForm),
+ mLinkProcessor(new ToxLinkProcessor())
+{;}
+
+ToxTextGenerator::~ToxTextGenerator()
+{;}
+
// Add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc> in order to control,
// which page description is used, no appropriate one is found.
void ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<SwTOXSortTabBase*> &entries,
sal_uInt16 indexOfEntryToProcess, sal_uInt16 numberOfEntriesToProcess, sal_uInt32 _nTOXSectNdIdx,
const SwPageDesc* _pDefaultPageDesc)
{
- LinkStructArr aLinkArr;
-
// pTOXNd is only set at the first mark
SwTxtNode* pTOXNd = (SwTxtNode*)entries.at(indexOfEntryToProcess)->pTOXNd;
// FIXME this operates directly on the node text
@@ -97,9 +91,6 @@ void ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<SwTOXSortTabB
OSL_ENSURE( nLvl < mToxForm.GetFormMax(), "invalid FORM_LEVEL");
SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
- sal_Int32 nLinkStartPosition = -1;
- OUString sLinkCharacterStyle; // default to "Default" character style - which is none
- OUString sURL;
// create an enumerator
// #i21237#
SwFormTokens aPattern = mToxForm.GetPattern(nLvl);
@@ -276,36 +267,11 @@ void ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<SwTOXSortTabB
break;
case TOKEN_LINK_START:
- nLinkStartPosition = rTxt.getLength();
- sLinkCharacterStyle = aToken.sCharStyleName;
- break;
+ mLinkProcessor->StartNewLink(rTxt.getLength(), aToken.sCharStyleName);
+ break;
case TOKEN_LINK_END:
- //TODO: only paired start/end tokens are valid
- if (nLinkStartPosition != -1)
- {
- SwIndex aIdx( pTOXNd, nLinkStartPosition );
- // pTOXNd->Erase( aIdx, SwForm::nFormLinkSttLen );
- sal_Int32 nEnd = rTxt.getLength();
-
- if( sURL.isEmpty() )
- {
- sURL = rBase.GetURL();
- if( sURL.isEmpty() )
- break;
- }
- LinkStruct* pNewLink = new LinkStruct(sURL, nLinkStartPosition,
- nEnd);
- const sal_uInt16 nPoolId =
- sLinkCharacterStyle.isEmpty()
- ? USHRT_MAX
- : SwStyleNameMapper::GetPoolIdFromUIName( sLinkCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
- pNewLink->aINetFmt.SetVisitedFmtAndId( sLinkCharacterStyle, nPoolId );
- pNewLink->aINetFmt.SetINetFmtAndId( sLinkCharacterStyle, nPoolId );
- aLinkArr.push_back(pNewLink);
- nLinkStartPosition = -1;
- sLinkCharacterStyle = "";
- }
+ mLinkProcessor->CloseLink(rTxt.getLength(), rBase.GetURL());
break;
case TOKEN_AUTHORITY:
@@ -339,13 +305,7 @@ void ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<SwTOXSortTabB
pTOXNd->SetAttr( aTStops );
}
-
- for(LinkStructArr::const_iterator i = aLinkArr.begin(); i != aLinkArr.end(); ++i)
- {
- pTOXNd->InsertItem((*i)->aINetFmt, (*i)->nStartTextPos,
- (*i)->nEndTextPos);
- delete (*i);
- }
+ mLinkProcessor->InsertLinkAttributes(*pTOXNd);
}
} // end namespace sw