Blob Blame History Raw
From cfc9cef1e26e98153eb93229a9c18a674a3ebf11 Mon Sep 17 00:00:00 2001
From: Kohei Yoshida <kohei.yoshida@collabora.com>
Date: Fri, 6 Dec 2013 10:43:38 -0500
Subject: [PATCH 043/109] fdo#69518: Correctly handle the old constraint
 syntax.

We apparently support this syntax for ODF-backward compatibility.

To fix this, I resurrected ScDPObject::ParseFilters() which was removed as
unused, adjusted it for the String->OUString change, and changed the filter
data structure to the UNO one rather than using the old one we no longer use
elsewhere.

(cherry picked from commit 1d85c8df2fb9cb25fc524485339ae9f11e8da676)

Conflicts:
	sc/inc/dpobject.hxx
	sc/source/core/data/dpobject.cxx
	sc/source/core/tool/interpr2.cxx

Change-Id: If52b38aaa1e8b208fb0ef9d92a6e853decdf43e3
Reviewed-on: https://gerrit.libreoffice.org/6962
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Eike Rathke <erack@redhat.com>
---
 sc/inc/dpobject.hxx              |   8 +-
 sc/inc/dpoutput.hxx              |  21 -----
 sc/source/core/data/dpobject.cxx | 163 ++++++++++++++++++++-------------------
 sc/source/core/tool/interpr2.cxx |  15 ++++
 4 files changed, 103 insertions(+), 104 deletions(-)

diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index 735b033..8505a53 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -183,9 +183,11 @@ public:
         const OUString& rDataFieldName,
         std::vector<com::sun::star::sheet::DataPilotFieldFilter>& rFilters);
 
-    bool                ParseFilters( ScDPGetPivotDataField& rTarget,
-                                      std::vector< ScDPGetPivotDataField >& rFilters,
-                                      const OUString& rFilterList );
+    bool ParseFilters(
+        OUString& rDataFieldName,
+        std::vector<com::sun::star::sheet::DataPilotFieldFilter>& rFilters,
+        std::vector<com::sun::star::sheet::GeneralFunction>& rFilterFuncs,
+        const OUString& rFilterList );
 
     void GetMemberResultNames(ScDPUniqueStringSet& rNames, long nDimension);
 
diff --git a/sc/inc/dpoutput.hxx b/sc/inc/dpoutput.hxx
index 293d937..7b38c7e 100644
--- a/sc/inc/dpoutput.hxx
+++ b/sc/inc/dpoutput.hxx
@@ -41,29 +41,8 @@ namespace com { namespace sun { namespace star { namespace sheet {
 
 class Rectangle;
 class ScDocument;
-
 struct ScDPOutLevelData;
 
-
-struct ScDPGetPivotDataField
-{
-    OUString maFieldName;
-    com::sun::star::sheet::GeneralFunction meFunction;
-
-    bool   mbValIsStr;
-    OUString maValStr;
-    double mnValNum;
-
-        ScDPGetPivotDataField() :
-            meFunction( com::sun::star::sheet::GeneralFunction_NONE ),
-            mbValIsStr( false ),
-            mnValNum( 0.0 )
-        {
-        }
-};
-
-
-
 class ScDPOutput
 {
 private:
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 3a45a34..677ccd5 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -1400,25 +1400,27 @@ void ScDPObject::GetMemberResultNames(ScDPUniqueStringSet& rNames, long nDimensi
     pOutput->GetMemberResultNames(rNames, nDimension);    // used only with table data -> level not needed
 }
 
-static bool lcl_Dequote( const String& rSource, xub_StrLen nStartPos, xub_StrLen& rEndPos, String& rResult )
+namespace {
+
+bool dequote( const OUString& rSource, sal_Int32 nStartPos, sal_Int32& rEndPos, OUString& rResult )
 {
     // nStartPos has to point to opening quote
 
     bool bRet = false;
     const sal_Unicode cQuote = '\'';
 
-    if ( rSource.GetChar(nStartPos) == cQuote )
+    if (rSource[nStartPos] == cQuote)
     {
         OUStringBuffer aBuffer;
-        xub_StrLen nPos = nStartPos + 1;
-        const xub_StrLen nLen = rSource.Len();
+        sal_Int32 nPos = nStartPos + 1;
+        const sal_Int32 nLen = rSource.getLength();
 
         while ( nPos < nLen )
         {
-            const sal_Unicode cNext = rSource.GetChar(nPos);
+            const sal_Unicode cNext = rSource[nPos];
             if ( cNext == cQuote )
             {
-                if ( nPos+1 < nLen && rSource.GetChar(nPos+1) == cQuote )
+                if (nPos+1 < nLen && rSource[nPos+1] == cQuote)
                 {
                     // double quote is used for an embedded quote
                     aBuffer.append( cNext );    // append one quote
@@ -1449,7 +1451,7 @@ struct ScGetPivotDataFunctionEntry
     sheet::GeneralFunction  eFunc;
 };
 
-static bool lcl_ParseFunction( const String& rList, xub_StrLen nStartPos, xub_StrLen& rEndPos, sheet::GeneralFunction& rFunc )
+bool parseFunction( const OUString& rList, sal_Int32 nStartPos, sal_Int32& rEndPos, sheet::GeneralFunction& rFunc )
 {
     static const ScGetPivotDataFunctionEntry aFunctions[] =
     {
@@ -1471,22 +1473,22 @@ static bool lcl_ParseFunction( const String& rList, xub_StrLen nStartPos, xub_St
         { "StdDevp",    sheet::GeneralFunction_STDEVP    }
     };
 
-    const xub_StrLen nListLen = rList.Len();
-    while ( nStartPos < nListLen && rList.GetChar(nStartPos) == ' ' )
+    const sal_Int32 nListLen = rList.getLength();
+    while (nStartPos < nListLen && rList[nStartPos] == ' ')
         ++nStartPos;
 
     bool bParsed = false;
     bool bFound = false;
-    String aFuncStr;
-    xub_StrLen nFuncEnd = 0;
-    if ( nStartPos < nListLen && rList.GetChar(nStartPos) == '\'' )
-        bParsed = lcl_Dequote( rList, nStartPos, nFuncEnd, aFuncStr );
+    OUString aFuncStr;
+    sal_Int32 nFuncEnd = 0;
+    if (nStartPos < nListLen && rList[nStartPos] == '\'')
+        bParsed = dequote( rList, nStartPos, nFuncEnd, aFuncStr );
     else
     {
-        nFuncEnd = rList.Search( static_cast<sal_Unicode>(']'), nStartPos );
-        if ( nFuncEnd != STRING_NOTFOUND )
+        nFuncEnd = rList.indexOf(']', nStartPos);
+        if (nFuncEnd >= 0)
         {
-            aFuncStr = rList.Copy( nStartPos, nFuncEnd - nStartPos );
+            aFuncStr = rList.copy(nStartPos, nFuncEnd - nStartPos);
             bParsed = true;
         }
     }
@@ -1498,12 +1500,12 @@ static bool lcl_ParseFunction( const String& rList, xub_StrLen nStartPos, xub_St
         const sal_Int32 nFuncCount = sizeof(aFunctions) / sizeof(aFunctions[0]);
         for ( sal_Int32 nFunc=0; nFunc<nFuncCount && !bFound; nFunc++ )
         {
-            if ( aFuncStr.EqualsIgnoreCaseAscii( aFunctions[nFunc].pName ) )
+           if (aFuncStr.equalsIgnoreAsciiCaseAscii(aFunctions[nFunc].pName))
             {
                 rFunc = aFunctions[nFunc].eFunc;
                 bFound = true;
 
-                while ( nFuncEnd < nListLen && rList.GetChar(nFuncEnd) == ' ' )
+                while (nFuncEnd < nListLen && rList[nFuncEnd] == ' ')
                     ++nFuncEnd;
                 rEndPos = nFuncEnd;
             }
@@ -1513,48 +1515,49 @@ static bool lcl_ParseFunction( const String& rList, xub_StrLen nStartPos, xub_St
     return bFound;
 }
 
-static bool lcl_IsAtStart( const String& rList, const String& rSearch, sal_Int32& rMatched,
-                    bool bAllowBracket, sheet::GeneralFunction* pFunc )
+bool isAtStart(
+    const OUString& rList, const OUString& rSearch, sal_Int32& rMatched,
+    bool bAllowBracket, sheet::GeneralFunction* pFunc )
 {
     sal_Int32 nMatchList = 0;
     sal_Int32 nMatchSearch = 0;
-    sal_Unicode cFirst = rList.GetChar(0);
+    sal_Unicode cFirst = rList[0];
     if ( cFirst == '\'' || cFirst == '[' )
     {
         // quoted string or string in brackets must match completely
 
-        String aDequoted;
-        xub_StrLen nQuoteEnd = 0;
+        OUString aDequoted;
+        sal_Int32 nQuoteEnd = 0;
         bool bParsed = false;
 
         if ( cFirst == '\'' )
-            bParsed = lcl_Dequote( rList, 0, nQuoteEnd, aDequoted );
+            bParsed = dequote( rList, 0, nQuoteEnd, aDequoted );
         else if ( cFirst == '[' )
         {
             // skip spaces after the opening bracket
 
-            xub_StrLen nStartPos = 1;
-            const xub_StrLen nListLen = rList.Len();
-            while ( nStartPos < nListLen && rList.GetChar(nStartPos) == ' ' )
+            sal_Int32 nStartPos = 1;
+            const sal_Int32 nListLen = rList.getLength();
+            while (nStartPos < nListLen && rList[nStartPos] == ' ')
                 ++nStartPos;
 
-            if ( rList.GetChar(nStartPos) == '\'' )         // quoted within the brackets?
+            if (nStartPos < nListLen && rList[nStartPos] == '\'')         // quoted within the brackets?
             {
-                if ( lcl_Dequote( rList, nStartPos, nQuoteEnd, aDequoted ) )
+                if ( dequote( rList, nStartPos, nQuoteEnd, aDequoted ) )
                 {
                     // after the quoted string, there must be the closing bracket, optionally preceded by spaces,
                     // and/or a function name
-                    while ( nQuoteEnd < nListLen && rList.GetChar(nQuoteEnd) == ' ' )
+                    while (nQuoteEnd < nListLen && rList[nQuoteEnd] == ' ')
                         ++nQuoteEnd;
 
                     // semicolon separates function name
-                    if ( nQuoteEnd < nListLen && rList.GetChar(nQuoteEnd) == ';' && pFunc )
+                    if (nQuoteEnd < nListLen && rList[nQuoteEnd] == ';' && pFunc)
                     {
-                        xub_StrLen nFuncEnd = 0;
-                        if ( lcl_ParseFunction( rList, nQuoteEnd + 1, nFuncEnd, *pFunc ) )
+                        sal_Int32 nFuncEnd = 0;
+                        if ( parseFunction( rList, nQuoteEnd + 1, nFuncEnd, *pFunc ) )
                             nQuoteEnd = nFuncEnd;
                     }
-                    if ( nQuoteEnd < nListLen && rList.GetChar(nQuoteEnd) == ']' )
+                    if (nQuoteEnd < nListLen && rList[nQuoteEnd] == ']')
                     {
                         ++nQuoteEnd;        // include the closing bracket for the matched length
                         bParsed = true;
@@ -1565,19 +1568,19 @@ static bool lcl_IsAtStart( const String& rList, const String& rSearch, sal_Int32
             {
                 // implicit quoting to the closing bracket
 
-                xub_StrLen nClosePos = rList.Search( static_cast<sal_Unicode>(']'), nStartPos );
-                if ( nClosePos != STRING_NOTFOUND )
+                sal_Int32 nClosePos = rList.indexOf(']', nStartPos);
+                if (nClosePos >= 0)
                 {
-                    xub_StrLen nNameEnd = nClosePos;
-                    xub_StrLen nSemiPos = rList.Search( static_cast<sal_Unicode>(';'), nStartPos );
-                    if ( nSemiPos != STRING_NOTFOUND && nSemiPos < nClosePos && pFunc )
+                    sal_Int32 nNameEnd = nClosePos;
+                    sal_Int32 nSemiPos = rList.indexOf(';', nStartPos);
+                    if (nSemiPos >= 0 && nSemiPos < nClosePos && pFunc)
                     {
-                        xub_StrLen nFuncEnd = 0;
-                        if ( lcl_ParseFunction( rList, nSemiPos + 1, nFuncEnd, *pFunc ) )
+                        sal_Int32 nFuncEnd = 0;
+                        if (parseFunction(rList, nSemiPos+1, nFuncEnd, *pFunc))
                             nNameEnd = nSemiPos;
                     }
 
-                    aDequoted = rList.Copy( nStartPos, nNameEnd - nStartPos );
+                    aDequoted = rList.copy(nStartPos, nNameEnd - nStartPos);
                     // spaces before the closing bracket or semicolon
                     aDequoted = comphelper::string::stripEnd(aDequoted, ' ');
                     nQuoteEnd = nClosePos + 1;
@@ -1589,26 +1592,26 @@ static bool lcl_IsAtStart( const String& rList, const String& rSearch, sal_Int32
         if ( bParsed && ScGlobal::GetpTransliteration()->isEqual( aDequoted, rSearch ) )
         {
             nMatchList = nQuoteEnd;             // match count in the list string, including quotes
-            nMatchSearch = rSearch.Len();
+            nMatchSearch = rSearch.getLength();
         }
     }
     else
     {
         // otherwise look for search string at the start of rList
-        ScGlobal::GetpTransliteration()->equals( rList, 0, rList.Len(), nMatchList,
-                                            rSearch, 0, rSearch.Len(), nMatchSearch );
+        ScGlobal::GetpTransliteration()->equals(
+            rList, 0, rList.getLength(), nMatchList, rSearch, 0, rSearch.getLength(), nMatchSearch);
     }
 
-    if ( nMatchSearch == rSearch.Len() )
+    if (nMatchSearch == rSearch.getLength())
     {
         // search string is at start of rList - look for following space or end of string
 
         bool bValid = false;
-        if ( sal::static_int_cast<xub_StrLen>(nMatchList) >= rList.Len() )
+        if ( sal::static_int_cast<sal_Int32>(nMatchList) >= rList.getLength() )
             bValid = true;
         else
         {
-            sal_Unicode cNext = rList.GetChar(sal::static_int_cast<xub_StrLen>(nMatchList));
+            sal_Unicode cNext = rList[nMatchList];
             if ( cNext == ' ' || ( bAllowBracket && cNext == '[' ) )
                 bValid = true;
         }
@@ -1623,17 +1626,20 @@ static bool lcl_IsAtStart( const String& rList, const String& rSearch, sal_Int32
     return false;
 }
 
-bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
-                               std::vector< ScDPGetPivotDataField >& rFilters,
-                               const OUString& rFilterList )
+} // anonymous namespace
+
+bool ScDPObject::ParseFilters(
+    OUString& rDataFieldName,
+    std::vector<sheet::DataPilotFieldFilter>& rFilters,
+    std::vector<sheet::GeneralFunction>& rFilterFuncs, const OUString& rFilterList )
 {
     // parse the string rFilterList into parameters for GetPivotData
 
     CreateObjects();            // create xSource if not already done
 
-    std::vector<String> aDataNames;     // data fields (source name)
-    std::vector<String> aGivenNames;    // data fields (compound name)
-    std::vector<String> aFieldNames;    // column/row/data fields
+    std::vector<OUString> aDataNames;     // data fields (source name)
+    std::vector<OUString> aGivenNames;    // data fields (compound name)
+    std::vector<OUString> aFieldNames;    // column/row/data fields
     std::vector< uno::Sequence<OUString> > aFieldValues;
 
     //
@@ -1691,7 +1697,7 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
                         {
                             uno::Reference<container::XNameAccess> xMembers = xLevSupp->getMembers();
 
-                            String aFieldName( xLevNam->getName() );
+                            OUString aFieldName( xLevNam->getName() );
                             uno::Sequence<OUString> aMemberNames( xMembers->getElementNames() );
 
                             aFieldNames.push_back( aFieldName );
@@ -1713,8 +1719,8 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
 
     bool bError = false;
     bool bHasData = false;
-    String aRemaining(comphelper::string::strip(rFilterList, ' '));
-    while ( aRemaining.Len() && !bError )
+    OUString aRemaining(comphelper::string::strip(rFilterList, ' '));
+    while (!aRemaining.isEmpty() && !bError)
     {
         bool bUsed = false;
 
@@ -1722,17 +1728,17 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
 
         for ( SCSIZE nDataPos=0; nDataPos<nDataFields && !bUsed; nDataPos++ )
         {
-            String aFound;
+            OUString aFound;
             sal_Int32 nMatched = 0;
-            if ( lcl_IsAtStart( aRemaining, aDataNames[nDataPos], nMatched, false, NULL ) )
+            if (isAtStart(aRemaining, aDataNames[nDataPos], nMatched, false, NULL))
                 aFound = aDataNames[nDataPos];
-            else if ( lcl_IsAtStart( aRemaining, aGivenNames[nDataPos], nMatched, false, NULL ) )
+            else if (isAtStart(aRemaining, aGivenNames[nDataPos], nMatched, false, NULL))
                 aFound = aGivenNames[nDataPos];
 
-            if ( aFound.Len() )
+            if (!aFound.isEmpty())
             {
-                rTarget.maFieldName = aFound;
-                aRemaining.Erase( 0, sal::static_int_cast<xub_StrLen>(nMatched) );
+                rDataFieldName = aFound;
+                aRemaining = aRemaining.copy(nMatched);
                 bHasData = true;
                 bUsed = true;
             }
@@ -1740,21 +1746,21 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
 
         // look for field name
 
-        String aSpecField;
+        OUString aSpecField;
         bool bHasFieldName = false;
         if ( !bUsed )
         {
             sal_Int32 nMatched = 0;
             for ( SCSIZE nField=0; nField<nFieldCount && !bHasFieldName; nField++ )
             {
-                if ( lcl_IsAtStart( aRemaining, aFieldNames[nField], nMatched, true, NULL ) )
+                if (isAtStart(aRemaining, aFieldNames[nField], nMatched, true, NULL))
                 {
                     aSpecField = aFieldNames[nField];
-                    aRemaining.Erase( 0, sal::static_int_cast<xub_StrLen>(nMatched) );
+                    aRemaining = aRemaining.copy(nMatched);
                     aRemaining = comphelper::string::stripStart(aRemaining, ' ');
 
                     // field name has to be followed by item name in brackets
-                    if ( aRemaining.GetChar(0) == '[' )
+                    if (!aRemaining.isEmpty() && aRemaining[0] == '[')
                     {
                         bHasFieldName = true;
                         // bUsed remains false - still need the item
@@ -1774,8 +1780,8 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
         {
             bool bItemFound = false;
             sal_Int32 nMatched = 0;
-            String aFoundName;
-            String aFoundValue;
+            OUString aFoundName;
+            OUString aFoundValue;
             sheet::GeneralFunction eFunc = sheet::GeneralFunction_NONE;
             sheet::GeneralFunction eFoundFunc = sheet::GeneralFunction_NONE;
 
@@ -1790,7 +1796,7 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
                     const OUString* pItemArr = rItems.getConstArray();
                     for ( sal_Int32 nItem=0; nItem<nItemCount; nItem++ )
                     {
-                        if ( lcl_IsAtStart( aRemaining, pItemArr[nItem], nMatched, false, &eFunc ) )
+                        if ( isAtStart( aRemaining, pItemArr[nItem], nMatched, false, &eFunc ) )
                         {
                             if ( bItemFound )
                                 bError = true;      // duplicate (also across fields)
@@ -1809,15 +1815,12 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
 
             if ( bItemFound && !bError )
             {
-                ScDPGetPivotDataField aField;
-                aField.maFieldName = aFoundName;
-                aField.meFunction = eFoundFunc;
-                aField.mbValIsStr = true;
-                aField.maValStr = aFoundValue;
-                aField.mnValNum = 0.0;
-                rFilters.push_back( aField );
-
-                aRemaining.Erase( 0, sal::static_int_cast<xub_StrLen>(nMatched) );
+                sheet::DataPilotFieldFilter aField;
+                aField.FieldName = aFoundName;
+                aField.MatchValue = aFoundValue;
+                rFilters.push_back(aField);
+                rFilterFuncs.push_back(eFoundFunc);
+                aRemaining = aRemaining.copy(nMatched);
             }
         }
 
@@ -1831,7 +1834,7 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
     if ( !bError && !bHasData && aDataNames.size() == 1 )
     {
         // if there's only one data field, its name need not be specified
-        rTarget.maFieldName = aDataNames[0];
+        rDataFieldName = aDataNames[0];
         bHasData = true;
     }
 
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index 7cc59de..a0f270d 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -3005,6 +3005,21 @@ void ScInterpreter::ScGetPivotData()
         return;
     }
 
+    if (bOldSyntax)
+    {
+        OUString aFilterStr = aDataFieldName;
+        std::vector<sheet::GeneralFunction> aFilterFuncs;
+        if (!pDPObj->ParseFilters(aDataFieldName, aFilters, aFilterFuncs, aFilterStr))
+        {
+            PushError(errNoRef);
+            return;
+        }
+
+        // TODO : For now, we ignore filter functions since we couldn't find a
+        // live example of how they are supposed to be used. We'll support
+        // this again once we come across a real-world example.
+    }
+
     double fVal = pDPObj->GetPivotData(aDataFieldName, aFilters);
     if (rtl::math::isNan(fVal))
     {
-- 
1.8.4.2