xref: /aoo42x/main/sc/source/core/data/dpsave.cxx (revision cdf0e10c)
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