xref: /trunk/main/sc/source/core/data/dpsave.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 // INCLUDE ---------------------------------------------------------------
34 
35 #include "dpsave.hxx"
36 #include "dpdimsave.hxx"
37 #include "dpobject.hxx"     // GetMemberNames used in BuildAllDimensionMembersFromSource
38 #include "miscuno.hxx"
39 #include "scerrors.hxx"
40 #include "unonames.hxx"
41 #include "global.hxx"
42 
43 #include <tools/debug.hxx>
44 
45 #include <com/sun/star/sheet/GeneralFunction.hpp>
46 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
47 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
48 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
49 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
50 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
51 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
52 #include <com/sun/star/sheet/TableFilterField.hpp>
53 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
54 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
55 #include <com/sun/star/sheet/XMembersSupplier.hpp>
56 #include <com/sun/star/container/XNamed.hpp>
57 #include <com/sun/star/util/XCloneable.hpp>
58 // Wang Xu Ming -- 2009-8-17
59 // DataPilot Migration - Cache&&Performance
60 #include "dptabsrc.hxx"
61 #include "dpglobal.hxx"
62 using namespace ScDPGlobal;
63 #ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDREFERENCETYPE_HPP_
64 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
65 #endif
66 #ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDREFERENCEITEMTYPE_HPP_
67 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
68 #endif
69 using namespace com::sun::star::sheet;
70 // End Comments
71 
72 #include <hash_map>
73 
74 using namespace com::sun::star;
75 using ::com::sun::star::uno::Reference;
76 using ::com::sun::star::uno::Any;
77 using ::rtl::OUString;
78 using ::rtl::OUStringHash;
79 using ::std::hash_map;
80 using ::std::auto_ptr;
81 
82 // -----------------------------------------------------------------------
83 
84 #define SC_DPSAVEMODE_NO        0
85 #define SC_DPSAVEMODE_YES       1
86 #define SC_DPSAVEMODE_DONTKNOW  2
87 
88 // -----------------------------------------------------------------------
89 
90 void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp,
91                             const rtl::OUString& rName, sal_Bool bValue )
92 {
93     //! move to ScUnoHelpFunctions?
94 
95     xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) );
96 }
97 
98 // -----------------------------------------------------------------------
99 
100 ScDPSaveMember::ScDPSaveMember(const String& rName) :
101     aName( rName ),
102     mpLayoutName(NULL),
103     nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
104     nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
105 {
106 }
107 
108 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
109     aName( r.aName ),
110     mpLayoutName(NULL),
111     nVisibleMode( r.nVisibleMode ),
112     nShowDetailsMode( r.nShowDetailsMode )
113 {
114     if (r.mpLayoutName.get())
115         mpLayoutName.reset(new OUString(*r.mpLayoutName));
116 }
117 
118 ScDPSaveMember::~ScDPSaveMember()
119 {
120 }
121 
122 sal_Bool ScDPSaveMember::operator== ( const ScDPSaveMember& r ) const
123 {
124     if ( aName            != r.aName            ||
125          nVisibleMode     != r.nVisibleMode     ||
126          nShowDetailsMode != r.nShowDetailsMode )
127         return sal_False;
128 
129     return sal_True;
130 }
131 
132 sal_Bool ScDPSaveMember::HasIsVisible() const
133 {
134     return nVisibleMode != SC_DPSAVEMODE_DONTKNOW;
135 }
136 
137 void ScDPSaveMember::SetIsVisible(sal_Bool bSet)
138 {
139     nVisibleMode = bSet;
140 }
141 
142 sal_Bool ScDPSaveMember::HasShowDetails() const
143 {
144     return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW;
145 }
146 
147 void ScDPSaveMember::SetShowDetails(sal_Bool bSet)
148 {
149     nShowDetailsMode = bSet;
150 }
151 
152 void ScDPSaveMember::SetName( const String& rNew )
153 {
154     // Used only if the source member was renamed (groups).
155     // For UI renaming of members, a layout name must be used.
156 
157     aName = rNew;
158 }
159 
160 void ScDPSaveMember::SetLayoutName( const OUString& rName )
161 {
162     mpLayoutName.reset(new OUString(rName));
163 }
164 
165 const OUString* ScDPSaveMember::GetLayoutName() const
166 {
167     return mpLayoutName.get();
168 }
169 
170 void ScDPSaveMember::RemoveLayoutName()
171 {
172     mpLayoutName.reset(NULL);
173 }
174 
175 void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
176 {
177     uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
178     DBG_ASSERT( xMembProp.is(), "no properties at member" );
179     if ( xMembProp.is() )
180     {
181         // exceptions are caught at ScDPSaveData::WriteToSource
182 
183         if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
184             lcl_SetBoolProperty( xMembProp,
185                     rtl::OUString::createFromAscii(DP_PROP_ISVISIBLE), (sal_Bool)nVisibleMode );
186 
187         if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
188             lcl_SetBoolProperty( xMembProp,
189                     rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS), (sal_Bool)nShowDetailsMode );
190 
191         if (mpLayoutName.get())
192             ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_LAYOUTNAME, *mpLayoutName);
193 
194         if ( nPosition >= 0 )
195             ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, DP_PROP_POSITION, nPosition);
196     }
197 }
198 
199 // -----------------------------------------------------------------------
200 
201 ScDPSaveDimension::ScDPSaveDimension(const String& rName, sal_Bool bDataLayout) :
202     aName( rName ),
203     pSelectedPage( NULL ),
204     mpLayoutName(NULL),
205     mpSubtotalName(NULL),
206     bIsDataLayout( bDataLayout ),
207     bDupFlag( sal_False ),
208     nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ),
209     nFunction( sheet::GeneralFunction_AUTO ),
210     nUsedHierarchy( -1 ),
211     nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
212     bSubTotalDefault( sal_True ),
213     nSubTotalCount( 0 ),
214     pSubTotalFuncs( NULL ),
215     pReferenceValue( NULL ),
216     pSortInfo( NULL ),
217     pAutoShowInfo( NULL ),
218     pLayoutInfo( NULL )
219 {
220 }
221 
222 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
223     aName( r.aName ),
224     mpLayoutName(NULL),
225     mpSubtotalName(NULL),
226     bIsDataLayout( r.bIsDataLayout ),
227     bDupFlag( r.bDupFlag ),
228     nOrientation( r.nOrientation ),
229     nFunction( r.nFunction ),
230     nUsedHierarchy( r.nUsedHierarchy ),
231     nShowEmptyMode( r.nShowEmptyMode ),
232     bSubTotalDefault( r.bSubTotalDefault ),
233     nSubTotalCount( r.nSubTotalCount ),
234     pSubTotalFuncs( NULL )
235 {
236     if ( nSubTotalCount && r.pSubTotalFuncs )
237     {
238         pSubTotalFuncs = new sal_uInt16[nSubTotalCount];
239         for (long nSub=0; nSub<nSubTotalCount; nSub++)
240             pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
241     }
242 
243     for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; i++)
244     {
245         const String& rName =  (*i)->GetName();
246         ScDPSaveMember* pNew = new ScDPSaveMember( **i );
247         maMemberHash[rName] = pNew;
248         maMemberList.push_back( pNew );
249     }
250     if (r.pReferenceValue)
251         pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) );
252     else
253         pReferenceValue = NULL;
254     if (r.pSortInfo)
255         pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) );
256     else
257         pSortInfo = NULL;
258     if (r.pAutoShowInfo)
259         pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) );
260     else
261         pAutoShowInfo = NULL;
262     if (r.pLayoutInfo)
263         pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
264     else
265         pLayoutInfo = NULL;
266     if (r.pSelectedPage)
267         pSelectedPage = new String( *(r.pSelectedPage) );
268     else
269         pSelectedPage = NULL;
270     if (r.mpLayoutName.get())
271         mpLayoutName.reset(new OUString(*r.mpLayoutName));
272     if (r.mpSubtotalName.get())
273         mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
274 }
275 
276 ScDPSaveDimension::~ScDPSaveDimension()
277 {
278     for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; i++)
279         delete i->second;
280     delete pReferenceValue;
281     delete pSortInfo;
282     delete pAutoShowInfo;
283     delete pLayoutInfo;
284     delete pSelectedPage;
285     delete [] pSubTotalFuncs;
286 }
287 
288 sal_Bool ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const
289 {
290     if ( aName            != r.aName            ||
291          bIsDataLayout    != r.bIsDataLayout    ||
292          bDupFlag         != r.bDupFlag         ||
293          nOrientation     != r.nOrientation     ||
294          nFunction        != r.nFunction        ||
295          nUsedHierarchy   != r.nUsedHierarchy   ||
296          nShowEmptyMode   != r.nShowEmptyMode   ||
297          bSubTotalDefault != r.bSubTotalDefault ||
298          nSubTotalCount   != r.nSubTotalCount )
299         return sal_False;
300 
301     if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) )   // should not happen
302         return sal_False;
303 
304     long i;
305     for (i=0; i<nSubTotalCount; i++)
306         if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] )
307             return sal_False;
308 
309     if (maMemberHash.size() != r.maMemberHash.size() )
310         return sal_False;
311 
312     MemberList::const_iterator a=maMemberList.begin();
313     MemberList::const_iterator b=r.maMemberList.begin();
314     for (; a != maMemberList.end() ; ++a, ++b)
315         if (!(**a == **b))
316             return sal_False;
317 
318     if ( this->HasCurrentPage() && r.HasCurrentPage() )
319     {
320         if ( this->GetCurrentPage() != r.GetCurrentPage() )
321         {
322             return sal_False;
323         }
324     }
325     else if ( this->HasCurrentPage() || r.HasCurrentPage() )
326     {
327         return sal_False;
328     }
329     if( pReferenceValue && r.pReferenceValue )
330     {
331         if ( !(*pReferenceValue == *r.pReferenceValue) )
332         {
333             return sal_False;
334         }
335     }
336     else if ( pReferenceValue || r.pReferenceValue )
337     {
338         return sal_False;
339     }
340     if( this->pSortInfo && r.pSortInfo )
341     {
342         if ( !(*this->pSortInfo == *r.pSortInfo) )
343         {
344             return sal_False;
345         }
346     }
347     else if ( this->pSortInfo || r.pSortInfo )
348     {
349         return sal_False;
350     }
351     if( this->pAutoShowInfo && r.pAutoShowInfo )
352     {
353         if ( !(*this->pAutoShowInfo == *r.pAutoShowInfo) )
354         {
355             return sal_False;
356         }
357     }
358     else if ( this->pAutoShowInfo || r.pAutoShowInfo )
359     {
360         return sal_False;
361     }
362 
363     return sal_True;
364 }
365 
366 void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember)
367 {
368     const String & rName =  pMember->GetName();
369     MemberHash::iterator aExisting = maMemberHash.find( rName );
370     if ( aExisting == maMemberHash.end() )
371     {
372         std::pair< const String, ScDPSaveMember *> key( rName, pMember );
373         maMemberHash.insert ( key );
374     }
375     else
376     {
377         maMemberList.remove( aExisting->second );
378         delete aExisting->second;
379         aExisting->second = pMember;
380     }
381     maMemberList.push_back( pMember );
382 }
383 
384 void ScDPSaveDimension::SetName( const String& rNew )
385 {
386     // Used only if the source dim was renamed (groups).
387     // For UI renaming of dimensions, the layout name must be used.
388 
389     aName = rNew;
390 }
391 
392 void ScDPSaveDimension::SetOrientation(sal_uInt16 nNew)
393 {
394     nOrientation = nNew;
395 }
396 
397 void ScDPSaveDimension::SetSubTotals(long nCount, const sal_uInt16* pFuncs)
398 {
399     if (pSubTotalFuncs)
400         delete [] pSubTotalFuncs;
401     nSubTotalCount = nCount;
402     if ( nCount && pFuncs )
403     {
404         pSubTotalFuncs = new sal_uInt16[nCount];
405         for (long i=0; i<nCount; i++)
406             pSubTotalFuncs[i] = pFuncs[i];
407     }
408     else
409         pSubTotalFuncs = NULL;
410 
411     bSubTotalDefault = sal_False;
412 }
413 
414 bool ScDPSaveDimension::HasShowEmpty() const
415 {
416     return nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW;
417 }
418 
419 void ScDPSaveDimension::SetShowEmpty(sal_Bool bSet)
420 {
421     nShowEmptyMode = bSet;
422 }
423 
424 void ScDPSaveDimension::SetFunction(sal_uInt16 nNew)
425 {
426     nFunction = nNew;
427 }
428 
429 void ScDPSaveDimension::SetUsedHierarchy(long nNew)
430 {
431     nUsedHierarchy = nNew;
432 }
433 
434 void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
435 {
436     mpSubtotalName.reset(new OUString(rName));
437 }
438 
439 const OUString* ScDPSaveDimension::GetSubtotalName() const
440 {
441     return mpSubtotalName.get();
442 }
443 
444 bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const
445 {
446     MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end();
447     for (; itr != itrEnd; ++itr)
448     {
449         const ScDPSaveMember* pMem = *itr;
450         if (rName.equalsIgnoreAsciiCase(pMem->GetName()))
451             return true;
452 
453         const OUString* pLayoutName = pMem->GetLayoutName();
454         if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName))
455             return true;
456     }
457     return false;
458 }
459 
460 void ScDPSaveDimension::SetLayoutName(const OUString& rName)
461 {
462     mpLayoutName.reset(new OUString(rName));
463 }
464 
465 const OUString* ScDPSaveDimension::GetLayoutName() const
466 {
467     return mpLayoutName.get();
468 }
469 
470 void ScDPSaveDimension::RemoveLayoutName()
471 {
472     mpLayoutName.reset(NULL);
473 }
474 
475 void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
476 {
477     delete pReferenceValue;
478     if (pNew)
479         pReferenceValue = new sheet::DataPilotFieldReference(*pNew);
480     else
481         pReferenceValue = NULL;
482 }
483 
484 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew)
485 {
486     delete pSortInfo;
487     if (pNew)
488         pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew);
489     else
490         pSortInfo = NULL;
491 }
492 
493 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew)
494 {
495     delete pAutoShowInfo;
496     if (pNew)
497         pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew);
498     else
499         pAutoShowInfo = NULL;
500 }
501 
502 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew)
503 {
504     delete pLayoutInfo;
505     if (pNew)
506         pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew);
507     else
508         pLayoutInfo = NULL;
509 }
510 
511 void ScDPSaveDimension::SetCurrentPage( const String* pPage )
512 {
513     delete pSelectedPage;
514     if (pPage)
515         pSelectedPage = new String( *pPage );
516     else
517         pSelectedPage = NULL;
518 }
519 
520 sal_Bool ScDPSaveDimension::HasCurrentPage() const
521 {
522     return ( pSelectedPage != NULL );
523 }
524 
525 const String& ScDPSaveDimension::GetCurrentPage() const
526 {
527     if (pSelectedPage)
528         return *pSelectedPage;
529     return EMPTY_STRING;
530 }
531 
532 ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const String& rName)
533 {
534     MemberHash::const_iterator res = maMemberHash.find (rName);
535     if (res != maMemberHash.end())
536         return res->second;
537     return NULL;
538 }
539 
540 
541 ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const String& rName)
542 {
543     MemberHash::const_iterator res = maMemberHash.find (rName);
544     if (res != maMemberHash.end())
545         return res->second;
546 
547     ScDPSaveMember* pNew = new ScDPSaveMember( rName );
548     maMemberHash[rName] = pNew;
549     maMemberList.push_back( pNew );
550     return pNew;
551 }
552 
553 void ScDPSaveDimension::SetMemberPosition( const String& rName, sal_Int32 nNewPos )
554 {
555     ScDPSaveMember* pMember = GetMemberByName( rName );     // make sure it exists and is in the hash
556 
557     maMemberList.remove( pMember );
558 
559     MemberList::iterator aIter = maMemberList.begin();
560     for (sal_Int32 i=0; i<nNewPos && aIter != maMemberList.end(); i++)
561         ++aIter;
562     maMemberList.insert( aIter, pMember );
563 }
564 
565 void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
566 {
567     uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
568     DBG_ASSERT( xDimProp.is(), "no properties at dimension" );
569     if ( xDimProp.is() )
570     {
571         // exceptions are caught at ScDPSaveData::WriteToSource
572         uno::Any aAny;
573 
574         sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
575         aAny <<= eOrient;
576         xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
577 
578         sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
579         aAny <<= eFunc;
580         xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FUNCTION), aAny );
581 
582         if ( nUsedHierarchy >= 0 )
583         {
584             aAny <<= (sal_Int32)nUsedHierarchy;
585             xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY), aAny );
586         }
587 
588         if ( pReferenceValue )
589         {
590             aAny <<= *pReferenceValue;
591             xDimProp->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_REFVALUE), aAny );
592         }
593 
594         uno::Sequence<sheet::TableFilterField> aFilter;
595         // set the selected page field only if the dimension is used as page dimension
596         if ( pSelectedPage && nOrientation == sheet::DataPilotFieldOrientation_PAGE )
597         {
598             // single filter field: first field equal to selected string
599             sheet::TableFilterField aField( sheet::FilterConnection_AND, 0,
600                     sheet::FilterOperator_EQUAL, sal_False, 0.0, *pSelectedPage );
601             aFilter = uno::Sequence<sheet::TableFilterField>( &aField, 1 );
602         }
603         // else keep empty sequence
604 
605         ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, DP_PROP_FILTER, aFilter);
606         if (mpLayoutName.get())
607             ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_LAYOUTNAME, *mpLayoutName);
608 
609         const OUString* pSubTotalName = GetSubtotalName();
610         if (pSubTotalName)
611             // Custom subtotal name, with '?' being replaced by the visible field name later.
612             ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_FIELD_SUBTOTALNAME, *pSubTotalName);
613     }
614 
615     //  Level loop outside of maMemberList loop
616     //  because SubTotals have to be set independently of known members
617 
618     long nCount = maMemberHash.size();
619 
620     long nHierCount = 0;
621     uno::Reference<container::XIndexAccess> xHiers;
622     uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
623     if ( xHierSupp.is() )
624     {
625         uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
626         xHiers = new ScNameToIndexAccess( xHiersName );
627         nHierCount = xHiers->getCount();
628     }
629 
630     sal_Bool bHasHiddenMember = false;
631 
632     for (long nHier=0; nHier<nHierCount; nHier++)
633     {
634         uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
635 
636         long nLevCount = 0;
637         uno::Reference<container::XIndexAccess> xLevels;
638         uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
639         if ( xLevSupp.is() )
640         {
641             uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
642             xLevels = new ScNameToIndexAccess( xLevelsName );
643             nLevCount = xLevels->getCount();
644         }
645 
646         for (long nLev=0; nLev<nLevCount; nLev++)
647         {
648             uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
649             uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
650             DBG_ASSERT( xLevProp.is(), "no properties at level" );
651             if ( xLevProp.is() )
652             {
653                 uno::Any aAny;
654                 if ( !bSubTotalDefault )
655                 {
656                     if ( !pSubTotalFuncs )
657                         nSubTotalCount = 0;
658 
659                     uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
660                     sheet::GeneralFunction* pArray = aSeq.getArray();
661                     for (long i=0; i<nSubTotalCount; i++)
662                         pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
663                     aAny <<= aSeq;
664                     xLevProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS), aAny );
665                 }
666                 if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
667                     lcl_SetBoolProperty( xLevProp,
668                         rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY), (sal_Bool)nShowEmptyMode );
669 
670                 if ( pSortInfo )
671                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_SORTING, *pSortInfo);
672 
673                 if ( pAutoShowInfo )
674                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_AUTOSHOW, *pAutoShowInfo);
675 
676                 if ( pLayoutInfo )
677                     ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_LAYOUT, *pLayoutInfo);
678 
679                 // exceptions are caught at ScDPSaveData::WriteToSource
680             }
681 
682             if ( nCount > 0 )
683             {
684                 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
685                 if ( xMembSupp.is() )
686                 {
687                     uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
688                     if ( xMembers.is() )
689                     {
690                         sal_Int32 nPosition = -1;           // set position only in manual mode
691                         if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL )
692                             nPosition = 0;
693 
694                         for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; i++)
695                         {
696                             ScDPSaveMember* pMember = *i;
697                             if (!pMember->GetIsVisible())
698                                 bHasHiddenMember = true;
699                             rtl::OUString aMemberName = pMember->GetName();
700                             if ( xMembers->hasByName( aMemberName ) )
701                             {
702                                 uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
703                                     xMembers->getByName( aMemberName ) );
704                                 pMember->WriteToSource( xMemberInt, nPosition );
705 
706                                 if ( nPosition >= 0 )
707                                     ++nPosition;            // increase if initialized
708                             }
709                             // missing member is no error
710                         }
711                     }
712                 }
713             }
714         }
715     }
716 
717     if (xDimProp.is())
718         ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_HAS_HIDDEN_MEMBER, bHasHiddenMember);
719 }
720 
721 void ScDPSaveDimension::UpdateMemberVisibility(const hash_map<OUString, bool, OUStringHash>& rData)
722 {
723     typedef hash_map<OUString, bool, OUStringHash> DataMap;
724     MemberList::iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
725     for (; itrMem != itrMemEnd; ++itrMem)
726     {
727         ScDPSaveMember* pMem = *itrMem;
728         const String& rMemName = pMem->GetName();
729         DataMap::const_iterator itr = rData.find(rMemName);
730         if (itr != rData.end())
731             pMem->SetIsVisible(itr->second);
732     }
733 }
734 
735 bool ScDPSaveDimension::HasInvisibleMember() const
736 {
737     MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end();
738     for (; itrMem != itrMemEnd; ++itrMem)
739     {
740         const ScDPSaveMember* pMem = *itrMem;
741         if (!pMem->GetIsVisible())
742             return true;
743     }
744     return false;
745 }
746 
747 // -----------------------------------------------------------------------
748 
749 ScDPSaveData::ScDPSaveData() :
750     pDimensionData( NULL ),
751     nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW ),
752     nRowGrandMode( SC_DPSAVEMODE_DONTKNOW ),
753     nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
754     nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
755     bFilterButton( sal_True ),
756     bDrillDown( sal_True ),
757     // Wang Xu Ming -- 2009-8-17
758     // DataPilot Migration - Cache&&Performance
759     mnCacheId( -1),
760     // End Comments
761     mbDimensionMembersBuilt(false),
762     mpGrandTotalName(NULL)
763 {
764 }
765 
766 ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
767     nColumnGrandMode( r.nColumnGrandMode ),
768     nRowGrandMode( r.nRowGrandMode ),
769     nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
770     nRepeatEmptyMode( r.nRepeatEmptyMode ),
771     bFilterButton( r.bFilterButton ),
772     bDrillDown( r.bDrillDown ),
773     // Wang Xu Ming -- 2009-8-17
774     // DataPilot Migration - Cache&&Performance
775     mnCacheId(  r.mnCacheId ),
776     // End Comments
777     mbDimensionMembersBuilt(r.mbDimensionMembersBuilt),
778     mpGrandTotalName(NULL)
779 {
780     if ( r.pDimensionData )
781         pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
782     else
783         pDimensionData = NULL;
784 
785     long nCount = r.aDimList.Count();
786     for (long i=0; i<nCount; i++)
787     {
788         ScDPSaveDimension* pNew = new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
789         aDimList.Insert( pNew, LIST_APPEND );
790     }
791 
792     if (r.mpGrandTotalName.get())
793         mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
794 }
795 
796 ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
797 {
798     if ( &r != this )
799     {
800         // Wang Xu Ming -- 2009-8-17
801         // DataPilot Migration - Cache&&Performance
802         this->~ScDPSaveData();
803         new( this ) ScDPSaveData ( r );
804         // End Comments
805     }
806     return *this;
807 }
808 
809 sal_Bool ScDPSaveData::operator== ( const ScDPSaveData& r ) const
810 {
811     if ( nColumnGrandMode != r.nColumnGrandMode ||
812          nRowGrandMode    != r.nRowGrandMode    ||
813          nIgnoreEmptyMode != r.nIgnoreEmptyMode ||
814          nRepeatEmptyMode != r.nRepeatEmptyMode ||
815          bFilterButton    != r.bFilterButton    ||
816          mnCacheId        != r.mnCacheId ||/// Wang Xu Ming -- 2009-6-18 DataPilot Migration
817          bDrillDown       != r.bDrillDown ||
818          mbDimensionMembersBuilt != r.mbDimensionMembersBuilt)
819         return sal_False;
820 
821     if ( pDimensionData || r.pDimensionData )
822         if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) )
823             return sal_False;
824 
825     sal_uLong nCount = aDimList.Count();
826     if ( nCount != r.aDimList.Count() )
827         return sal_False;
828 
829     for (sal_uLong i=0; i<nCount; i++)
830         if ( !( *(ScDPSaveDimension*)aDimList.GetObject(i) ==
831                 *(ScDPSaveDimension*)r.aDimList.GetObject(i) ) )
832             return sal_False;
833 
834     if (mpGrandTotalName.get())
835     {
836         if (!r.mpGrandTotalName.get())
837             return false;
838         if (!mpGrandTotalName->equals(*r.mpGrandTotalName))
839             return false;
840     }
841     else if (r.mpGrandTotalName.get())
842         return false;
843 
844     return sal_True;
845 }
846 
847 ScDPSaveData::~ScDPSaveData()
848 {
849     long nCount = aDimList.Count();
850     for (long i=0; i<nCount; i++)
851         delete (ScDPSaveDimension*)aDimList.GetObject(i);
852     aDimList.Clear();
853 
854     delete pDimensionData;
855 }
856 
857 void ScDPSaveData::SetGrandTotalName(const OUString& rName)
858 {
859     mpGrandTotalName.reset(new OUString(rName));
860 }
861 
862 const OUString* ScDPSaveData::GetGrandTotalName() const
863 {
864     return mpGrandTotalName.get();
865 }
866 
867 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName)
868 {
869     long nCount = aDimList.Count();
870     for (long i=0; i<nCount; i++)
871     {
872         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
873         if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
874             return pDim;
875     }
876     ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, sal_False );
877     aDimList.Insert( pNew, LIST_APPEND );
878     mbDimensionMembersBuilt = false;        // BuildAllDimensionMembers only handles existing entries in aDimList
879     return pNew;
880 }
881 
882 ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const String& rName) const
883 {
884     long nCount = aDimList.Count();
885     for (long i=0; i<nCount; i++)
886     {
887         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
888         if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
889             return pDim;
890     }
891     return NULL;        // don't create new
892 }
893 
894 ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const String& rName)
895 {
896     long nCount = aDimList.Count();
897     for (long i=0; i<nCount; i++)
898     {
899         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
900         if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
901             return DuplicateDimension(rName);
902     }
903     ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, sal_False );
904     aDimList.Insert( pNew, LIST_APPEND );
905     mbDimensionMembersBuilt = false;        // BuildAllDimensionMembers only handles existing entries in aDimList
906     return pNew;
907 }
908 
909 ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
910 {
911     ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
912     if (pDim)
913         return pDim;
914 
915     ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), sal_True );
916     aDimList.Insert( pNew, LIST_APPEND );
917     mbDimensionMembersBuilt = false;        // BuildAllDimensionMembers only handles existing entries in aDimList
918     return pNew;
919 }
920 
921 ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
922 {
923     long nCount = aDimList.Count();
924     for (long i=0; i<nCount; i++)
925     {
926         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
927         if ( pDim->IsDataLayout() )
928             return pDim;
929     }
930     return NULL;
931 }
932 
933 ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const String& rName)
934 {
935     //  always insert new
936     //! check if dimension is there?
937 
938     ScDPSaveDimension* pOld = GetDimensionByName( rName );
939     ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
940     pNew->SetDupFlag( sal_True );
941     aDimList.Insert( pNew, LIST_APPEND );
942     mbDimensionMembersBuilt = false;        // BuildAllDimensionMembers only handles existing entries in aDimList
943     return pNew;
944 }
945 
946 void ScDPSaveData::RemoveDimensionByName(const String& rName)
947 {
948     long nCount = aDimList.Count();
949     for (long i=0; i<nCount; i++)
950     {
951         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
952         if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
953         {
954             delete pDim;
955             aDimList.Remove(i);
956             break;
957         }
958     }
959 }
960 
961 ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim )
962 {
963     ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim );
964     pNew->SetDupFlag( sal_True );
965     aDimList.Insert( pNew, LIST_APPEND );
966     mbDimensionMembersBuilt = false;        // BuildAllDimensionMembers only handles existing entries in aDimList
967     return *pNew;
968 }
969 
970 ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(sal_uInt16 nOrientation)
971 {
972     //  return the innermost dimension for the given orientation,
973     //  excluding data layout dimension
974 
975     ScDPSaveDimension* pInner = NULL;
976     long nCount = aDimList.Count();
977     for (long i=0; i<nCount; i++)
978     {
979         ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
980         if ( pDim->GetOrientation() == nOrientation && !pDim->IsDataLayout() )
981             pInner = pDim;
982     }
983     return pInner;      // the last matching one
984 }
985 
986 ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)
987 {
988     long nCount = aDimList.Count();
989     for (long i = 0; i < nCount; ++i)
990     {
991         ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
992         if (pDim->GetOrientation() == eOrientation && !pDim->IsDataLayout())
993             return pDim;
994     }
995     return NULL;
996 }
997 
998 long ScDPSaveData::GetDataDimensionCount() const
999 {
1000     long nDataCount = 0;
1001 
1002     long nCount = aDimList.Count();
1003     for (long i=0; i<nCount; i++)
1004     {
1005         const ScDPSaveDimension* pDim = static_cast<const ScDPSaveDimension*>(aDimList.GetObject(i));
1006         if ( pDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA )
1007             ++nDataCount;
1008     }
1009 
1010     return nDataCount;
1011 }
1012 
1013 void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
1014 {
1015     //  position (nNew) is counted within dimensions of the same orientation
1016 
1017     sal_uInt16 nOrient = pDim->GetOrientation();
1018 
1019     aDimList.Remove( pDim );
1020     sal_uLong nCount = aDimList.Count();        // after remove
1021 
1022     sal_uLong nInsPos = 0;
1023     while ( nNew > 0 && nInsPos < nCount )
1024     {
1025         if ( ((ScDPSaveDimension*)aDimList.GetObject(nInsPos))->GetOrientation() == nOrient )
1026             --nNew;
1027         ++nInsPos;
1028     }
1029 
1030     aDimList.Insert( pDim, nInsPos );
1031 }
1032 
1033 void ScDPSaveData::SetColumnGrand(sal_Bool bSet)
1034 {
1035     nColumnGrandMode = bSet;
1036 }
1037 
1038 void ScDPSaveData::SetRowGrand(sal_Bool bSet)
1039 {
1040     nRowGrandMode = bSet;
1041 }
1042 
1043 void ScDPSaveData::SetIgnoreEmptyRows(sal_Bool bSet)
1044 {
1045     nIgnoreEmptyMode = bSet;
1046 }
1047 
1048 void ScDPSaveData::SetRepeatIfEmpty(sal_Bool bSet)
1049 {
1050     nRepeatEmptyMode = bSet;
1051 }
1052 
1053 void ScDPSaveData::SetFilterButton(sal_Bool bSet)
1054 {
1055     bFilterButton = bSet;
1056 }
1057 
1058 void ScDPSaveData::SetDrillDown(sal_Bool bSet)
1059 {
1060     bDrillDown = bSet;
1061 }
1062 
1063 void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1064 {
1065     sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
1066 
1067     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1068     uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1069     long nIntCount = xIntDims->getCount();
1070     for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
1071     {
1072         uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1073         uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1074         if (xDimProp.is())
1075         {
1076             uno::Any aAny;
1077             aAny <<= eOrient;
1078             xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
1079         }
1080     }
1081 }
1082 
1083 void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1084 {
1085     if (!xSource.is())
1086         return;
1087 
1088     //  source options must be first!
1089 
1090     uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
1091     DBG_ASSERT( xSourceProp.is(), "no properties at source" );
1092     if ( xSourceProp.is() )
1093     {
1094         //  source options are not available for external sources
1095         //! use XPropertySetInfo to test for availability?
1096 
1097         try
1098         {
1099             if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1100                 lcl_SetBoolProperty( xSourceProp,
1101                     rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY), (sal_Bool)nIgnoreEmptyMode );
1102             if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1103                 lcl_SetBoolProperty( xSourceProp,
1104                     rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY), (sal_Bool)nRepeatEmptyMode );
1105         }
1106         catch(uno::Exception&)
1107         {
1108             // no error
1109         }
1110 
1111         const OUString* pGrandTotalName = GetGrandTotalName();
1112         if (pGrandTotalName)
1113             ScUnoHelpFunctions::SetOptionalPropertyValue(xSourceProp, SC_UNO_GRANDTOTAL_NAME, *pGrandTotalName);
1114     }
1115 
1116     // exceptions in the other calls are errors
1117     try
1118     {
1119         //  reset all orientations
1120         //! "forgetSettings" or similar at source ?????
1121         //! reset all duplicated dimensions, or reuse them below !!!
1122         DBG_TRACE( "ScDPSaveData::WriteToSource" );
1123 
1124         lcl_ResetOrient( xSource );
1125 
1126         long nCount = aDimList.Count();
1127         for (long i=0; i<nCount; i++)
1128         {
1129             ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1130             rtl::OUString aName = pDim->GetName();
1131 
1132             DBG_TRACESTR(pDim->GetName());
1133 
1134             sal_Bool bData = pDim->IsDataLayout();
1135 
1136             //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
1137 
1138             uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1139             uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1140             long nIntCount = xIntDims->getCount();
1141             sal_Bool bFound = sal_False;
1142             for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1143             {
1144                 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1145                 if ( bData )
1146                 {
1147                     uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1148                     if ( xDimProp.is() )
1149                     {
1150                         bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
1151                                     rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
1152                         //! error checking -- is "IsDataLayoutDimension" property required??
1153                     }
1154                 }
1155                 else
1156                 {
1157                     uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1158                     if ( xDimName.is() && xDimName->getName() == aName )
1159                         bFound = sal_True;
1160                 }
1161 
1162                 if ( bFound )
1163                 {
1164                     if ( pDim->GetDupFlag() )
1165                     {
1166                         String aNewName = pDim->GetName();
1167 
1168                         // different name for each duplication of a (real) dimension...
1169                         for (long j=0; j<=i; j++)   //! Test !!!!!!
1170                             aNewName += '*';        //! modify name at creation of SaveDimension
1171 
1172                         uno::Reference<util::XCloneable> xCloneable( xIntDim, uno::UNO_QUERY );
1173                         DBG_ASSERT( xCloneable.is(), "cannot clone dimension" );
1174                         if (xCloneable.is())
1175                         {
1176                             uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
1177                             uno::Reference<container::XNamed> xNewName( xNew, uno::UNO_QUERY );
1178                             if (xNewName.is())
1179                             {
1180                                 xNewName->setName( aNewName );
1181                                 pDim->WriteToSource( xNew );
1182                             }
1183                         }
1184                     }
1185                     else
1186                         pDim->WriteToSource( xIntDim );
1187                 }
1188             }
1189             DBG_ASSERT(bFound, "WriteToSource: Dimension not found");
1190         }
1191 
1192         if ( xSourceProp.is() )
1193         {
1194             if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
1195                 lcl_SetBoolProperty( xSourceProp,
1196                     rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND), (sal_Bool)nColumnGrandMode );
1197             if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
1198                 lcl_SetBoolProperty( xSourceProp,
1199                     rtl::OUString::createFromAscii(DP_PROP_ROWGRAND), (sal_Bool)nRowGrandMode );
1200         }
1201     }
1202     catch(uno::Exception&)
1203     {
1204         DBG_ERROR("exception in WriteToSource");
1205     }
1206 }
1207 
1208 sal_Bool ScDPSaveData::IsEmpty() const
1209 {
1210     long nCount = aDimList.Count();
1211     for (long i=0; i<nCount; i++)
1212     {
1213         ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1214         if ( pDim->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !pDim->IsDataLayout() )
1215             return sal_False;
1216     }
1217     return sal_True;    // no entries that are not hidden
1218 }
1219 
1220 ScDPDimensionSaveData* ScDPSaveData::GetDimensionData()
1221 {
1222     if (!pDimensionData)
1223         pDimensionData = new ScDPDimensionSaveData;
1224     return pDimensionData;
1225 }
1226 
1227 void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew )
1228 {
1229     delete pDimensionData;
1230     if ( pNew )
1231         pDimensionData = new ScDPDimensionSaveData( *pNew );
1232     else
1233         pDimensionData = NULL;
1234 }
1235 
1236 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
1237 {
1238     if (mbDimensionMembersBuilt)
1239         return;
1240 
1241     // First, build a dimension name-to-index map.
1242     typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1243     NameIndexMap aMap;
1244     long nColCount = pData->GetColumnCount();
1245     for (long i = 0; i < nColCount; ++i)
1246         aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
1247 
1248     NameIndexMap::const_iterator itrEnd = aMap.end();
1249 
1250     sal_uInt32 n = aDimList.Count();
1251     for (sal_uInt32 i = 0; i < n; ++i)
1252     {
1253         ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1254         const String& rDimName = pDim->GetName();
1255         if (!rDimName.Len())
1256             // empty dimension name.  It must be data layout.
1257             continue;
1258 
1259         NameIndexMap::const_iterator itr = aMap.find(rDimName);
1260         if (itr == itrEnd)
1261             // dimension name not in the data.  This should never happen!
1262             continue;
1263 
1264         long nDimIndex = itr->second;
1265         const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex);
1266         size_t mMemberCount = rMembers.size();
1267         for (size_t j = 0; j < mMemberCount; ++j)
1268         {
1269             const ScDPItemData* pMemberData = pData->GetMemberById( nDimIndex, rMembers[j] );
1270             String aMemName = pMemberData->GetString();
1271             if (pDim->GetExistingMemberByName(aMemName))
1272                 // this member instance already exists.  nothing to do.
1273                 continue;
1274 
1275             auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
1276             pNewMember->SetIsVisible(true);
1277             pDim->AddMember(pNewMember.release());
1278         }
1279     }
1280 
1281     mbDimensionMembersBuilt = true;
1282 }
1283 
1284 void ScDPSaveData::BuildAllDimensionMembersFromSource( ScDPObject* pDPObj )
1285 {
1286     // Initialize all members like BuildAllDimensionMembers, but access only the DataPilotSource, not the table data.
1287     // This could also replace BuildAllDimensionMembers, but the performance implications still have to be checked.
1288     // ScDPObject is used for the helper method GetMemberNames.
1289 
1290     if (mbDimensionMembersBuilt)
1291         return;
1292 
1293     uno::Reference<sheet::XDimensionsSupplier> xSource = pDPObj->GetSource();
1294     uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1295     // GetMemberNames uses the dimension index from getElementNames
1296     uno::Sequence<OUString> aDimNames = xDimsName->getElementNames();
1297 
1298     // First, build a dimension name-to-index map.
1299     typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1300     NameIndexMap aMap;
1301     long nColCount = aDimNames.getLength();
1302     for (long i = 0; i < nColCount; ++i)
1303         aMap.insert( NameIndexMap::value_type(aDimNames[i], i) );
1304 
1305     NameIndexMap::const_iterator itrEnd = aMap.end();
1306 
1307     sal_uInt32 n = aDimList.Count();
1308     for (sal_uInt32 i = 0; i < n; ++i)
1309     {
1310         ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1311         const String& rDimName = pDim->GetName();
1312         if (!rDimName.Len())
1313             // empty dimension name.  It must be data layout.
1314             continue;
1315 
1316         NameIndexMap::const_iterator itr = aMap.find(rDimName);
1317         if (itr == itrEnd)
1318             // dimension name not in the data.  This should never happen!
1319             continue;
1320 
1321         long nDimIndex = itr->second;
1322         uno::Sequence<OUString> aMemberNames;
1323         pDPObj->GetMemberNames( nDimIndex, aMemberNames );
1324         sal_Int32 nMemberCount = aMemberNames.getLength();
1325         for (sal_Int32 j = 0; j < nMemberCount; ++j)
1326         {
1327             String aMemName = aMemberNames[j];
1328             if (pDim->GetExistingMemberByName(aMemName))
1329                 // this member instance already exists.  nothing to do.
1330                 continue;
1331 
1332             auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName));
1333             pNewMember->SetIsVisible(true);
1334             pDim->AddMember(pNewMember.release());
1335         }
1336     }
1337 
1338     mbDimensionMembersBuilt = true;
1339 }
1340 
1341 bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const
1342 {
1343     ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName);
1344     if (!pDim)
1345         return false;
1346 
1347     return pDim->HasInvisibleMember();
1348 }
1349 
1350 void ScDPSaveData::Refresh( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
1351 {
1352     try
1353     {
1354         long nCount = aDimList.Count();
1355         std::list<String> deletedDims;
1356         for (long i=nCount-1; i >=0 ; i--)
1357         {
1358             ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1359 
1360             rtl::OUString aName = pDim->GetName();
1361             if ( pDim->IsDataLayout() )
1362                 continue;
1363 
1364             uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1365             uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1366             long nIntCount = xIntDims->getCount();
1367             sal_Bool bFound = sal_False;
1368             for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1369             {
1370                 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
1371                 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1372                 if ( xDimName.is() && xDimName->getName() == aName )
1373                     bFound = sal_True;
1374             }
1375             if ( !bFound )
1376             {
1377                 deletedDims.push_back( aName );
1378                 aDimList.Remove(i);
1379                 DBG_TRACE( "\n Remove dim: \t" );
1380                 DBG_TRACESTR(  String( aName ) );
1381             }
1382 
1383         }
1384 
1385         nCount = aDimList.Count();
1386         for (long  i=nCount-1; i >=0 ; i--) //check every dimension ??
1387         {
1388             ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
1389 
1390             rtl::OUString aName = pDim->GetName();
1391             if ( pDim->IsDataLayout() )
1392                 continue;
1393             pDim->Refresh( xSource, deletedDims );
1394 
1395         }
1396 
1397         mbDimensionMembersBuilt = false;    // there may be new members
1398     }
1399     catch(uno::Exception&)
1400     {
1401         DBG_ERROR("error in ScDPSaveData::Refresh");
1402     }
1403 
1404 }
1405 void ScDPSaveDimension::Refresh( const com::sun::star::uno::Reference<
1406                                 com::sun::star::sheet::XDimensionsSupplier>& xSource ,
1407                                 const std::list<String>& deletedDims)
1408 {
1409     if ( xSource.is() )
1410     {
1411         ScDPSource* pTabSource = static_cast<ScDPSource*>( xSource.get() );
1412         ScDPTableDataCache*  pCache = pTabSource->GetCache();
1413         if ( pCache->GetId() == -1 )
1414             return;
1415 
1416         SCCOL nSrcDim = pCache->GetDimensionIndex( GetName() );
1417 
1418         if ( nSrcDim == -1 )
1419             return;
1420         if ( pSelectedPage )
1421         {//check pSelected page
1422             DBG_TRACESTR( (*pSelectedPage) );
1423             if ( pCache->GetIdByItemData( nSrcDim, *pSelectedPage ) == -1 )
1424             {
1425                 delete pSelectedPage;
1426                 pSelectedPage = NULL;
1427             }
1428 
1429         };
1430 
1431         if ( pReferenceValue && pReferenceValue->ReferenceItemType == DataPilotFieldReferenceItemType::NAMED )
1432         {//check pReferenceValue
1433 #ifdef DEBUG
1434             switch( pReferenceValue->ReferenceType)
1435             {
1436             case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE: //both
1437                 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE \n" );
1438                 break;
1439             case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE: //both
1440                 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE \n" );
1441                 break;
1442             case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE: //both
1443                 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE \n" );
1444                 break;
1445             case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL:
1446                 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::RUNNING_TOTAL \n" ); //enable name
1447                 break;
1448             }
1449 #endif
1450             switch( pReferenceValue->ReferenceType)
1451             {
1452             case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE:
1453             case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE:
1454             case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
1455             case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL:
1456                 {
1457                     if( pReferenceValue->ReferenceItemType == DataPilotFieldReferenceItemType::NAMED  )
1458                     {
1459                         const String& sReferenceFieldName = pReferenceValue->ReferenceField;
1460                         DBG_TRACESTR( sReferenceFieldName );
1461                         SCCOL nRefDim = pCache->GetDimensionIndex( sReferenceFieldName );
1462                         bool bValid = true;
1463                         if ( nRefDim == -1 )
1464                             bValid = false;
1465                         else if ( pReferenceValue->ReferenceType != sheet::DataPilotFieldReferenceType::RUNNING_TOTAL )
1466                         { //running total has not reference item
1467                             const String& sReferenceItemName = pReferenceValue->ReferenceItemName;
1468                             DBG_TRACESTR( sReferenceItemName );
1469                             if ( pCache->GetIdByItemData( nRefDim, sReferenceItemName ) == -1 )
1470                                 bValid = false;
1471                         }
1472                         if ( !bValid )
1473                         {
1474                             delete pReferenceValue;
1475                             pReferenceValue = NULL;
1476                         }
1477                     }
1478                 }
1479                 break;
1480             }
1481 
1482         };
1483 
1484         if ( pSortInfo )
1485         { //check sortinfo
1486             if ( pSortInfo->Mode == DataPilotFieldSortMode::DATA )
1487             {
1488                 DBG_TRACE( "\n DataPilotFieldSortMode::DATA \n" );
1489                 const String& sFieldDimName = pSortInfo->Field;
1490                 std::list<String>::const_iterator iter = std::find( deletedDims.begin(), deletedDims.end(), sFieldDimName );
1491                 if ( iter != deletedDims.end() && pCache->GetDimensionIndex( sFieldDimName ) == -1  )
1492                 {
1493                     pSortInfo->Mode = DataPilotFieldSortMode::MANUAL;
1494                     pSortInfo->Field = GetName();
1495                 }
1496             }
1497 
1498         };
1499 
1500         if ( pAutoShowInfo )
1501         { //check autoshow
1502             const String& sFieldDimName = pAutoShowInfo->DataField;
1503             std::list<String>::const_iterator iter = std::find( deletedDims.begin(), deletedDims.end(), sFieldDimName );
1504             if ( iter != deletedDims.end() && pCache->GetDimensionIndex( sFieldDimName ) == -1  )
1505             {
1506                 delete pAutoShowInfo;
1507                 pAutoShowInfo = NULL;
1508             }
1509 
1510         };
1511 
1512         //remove unused members
1513         //SODC_19124
1514         for (MemberList::iterator i=maMemberList.begin(); i != maMemberList.end() ; )
1515         {
1516             rtl::OUString aMemberName = (*i)->GetName();
1517             if ( pCache->GetIdByItemData( nSrcDim, aMemberName ) == -1 )
1518                 i = maMemberList.erase( i );
1519             else
1520                 i++;
1521         }
1522     }
1523 }
1524 // End Comments
1525 bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r )
1526 {
1527     return l.Field == r.Field && l.IsAscending == r.IsAscending && l.Mode == r.Mode;
1528 }
1529 bool operator == (const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &l, const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &r )
1530 {
1531     return l.IsEnabled == r.IsEnabled &&
1532         l.ShowItemsMode == r.ShowItemsMode &&
1533         l.ItemCount == r.ItemCount &&
1534         l.DataField == r.DataField;
1535 }
1536 bool operator == (const ::com::sun::star::sheet::DataPilotFieldReference &l, const ::com::sun::star::sheet::DataPilotFieldReference &r )
1537 {
1538     return l.ReferenceType == r.ReferenceType &&
1539         l.ReferenceField == r.ReferenceField &&
1540         l.ReferenceItemType == r.ReferenceItemType &&
1541         l.ReferenceItemName == r.ReferenceItemName;
1542 }
1543 
1544