/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <tools/debug.hxx>
#include <rtl/math.hxx>
#include <bf_svtools/itemprop.hxx>
#include <vcl/svapp.hxx>

#include "dptabsrc.hxx"
#include "dptabdat.hxx"
#include "global.hxx"
#include "collect.hxx"
#include "datauno.hxx"      // ScDataUnoConversion
#include "miscuno.hxx"
#include "unonames.hxx"
#include "dptabres.hxx"

#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>

#include <unotools/calendarwrapper.hxx>
#include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
namespace binfilter {

using namespace ::com::sun::star;

// -----------------------------------------------------------------------

#define SC_MINCOUNT_LIMIT   1000000

// -----------------------------------------------------------------------

/*N*/ SC_SIMPLE_SERVICE_INFO( ScDPSource,      "ScDPSource",      "com.sun.star.sheet.DataPilotSource" )
/*N*/ SC_SIMPLE_SERVICE_INFO( ScDPDimensions,  "ScDPDimensions",  "com.sun.star.sheet.DataPilotSourceDimensions" )
/*N*/ SC_SIMPLE_SERVICE_INFO( ScDPDimension,   "ScDPDimension",   "com.sun.star.sheet.DataPilotSourceDimension" )
/*N*/ SC_SIMPLE_SERVICE_INFO( ScDPHierarchies, "ScDPHierarchies", "com.sun.star.sheet.DataPilotSourceHierarcies" )
/*N*/ SC_SIMPLE_SERVICE_INFO( ScDPHierarchy,   "ScDPHierarchy",   "com.sun.star.sheet.DataPilotSourceHierarcy" )
/*N*/ SC_SIMPLE_SERVICE_INFO( ScDPLevels,      "ScDPLevels",      "com.sun.star.sheet.DataPilotSourceLevels" )
/*N*/ SC_SIMPLE_SERVICE_INFO( ScDPLevel,       "ScDPLevel",       "com.sun.star.sheet.DataPilotSourceLevel" )

// -----------------------------------------------------------------------

// property maps for PropertySetInfo
//  DataDescription / NumberFormat are internal

// -----------------------------------------------------------------------

//! move to a header?
/*N*/ BOOL lcl_GetBoolFromAny( const uno::Any& aAny )
/*N*/ {
/*N*/   if ( aAny.getValueTypeClass() == uno::TypeClass_BOOLEAN )
/*N*/       return *(sal_Bool*)aAny.getValue();
/*N*/   return FALSE;
/*N*/ }

/*N*/ void lcl_SetBoolInAny( uno::Any& rAny, BOOL bValue )
/*N*/ {
/*N*/   rAny.setValue( &bValue, getBooleanCppuType() );
/*N*/ }

// -----------------------------------------------------------------------

/*N*/ ScDPSource::ScDPSource( ScDPTableData* pD ) :
/*N*/   pData( pD ),
/*N*/   pDimensions( NULL ),
/*N*/   nColDimCount( 0 ),
/*N*/   nRowDimCount( 0 ),
/*N*/   nDataDimCount( 0 ),
/*N*/   nPageDimCount( 0 ),
/*N*/   bColumnGrand( TRUE ),       // default is true
/*N*/   bRowGrand( TRUE ),
/*N*/   bIgnoreEmptyRows( FALSE ),
/*N*/   bRepeatIfEmpty( FALSE ),
/*N*/   nDupCount( 0 ),
/*N*/   pResData( NULL ),
/*N*/   pColResRoot( NULL ),
/*N*/   pRowResRoot( NULL ),
/*N*/   pColResults( NULL ),
/*N*/   pRowResults( NULL ),
/*N*/   bResultOverflow( FALSE )
/*N*/ {
/*N*/   pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
/*N*/ }

/*N*/ ScDPSource::~ScDPSource()
/*N*/ {
/*N*/   delete pData;           // ScDPTableData is not ref-counted
/*N*/
/*N*/   if (pDimensions)
/*N*/       pDimensions->release();     // ref-counted
/*N*/
/*N*/   //! free lists
/*N*/
/*N*/   delete[] pColResults;
/*N*/   delete[] pRowResults;
/*N*/
/*N*/   delete pColResRoot;
/*N*/   delete pRowResRoot;
/*N*/   delete pResData;
/*N*/ }

/*N*/ USHORT ScDPSource::GetOrientation(long nColumn)
/*N*/ {
/*N*/   long i;
/*N*/   for (i=0; i<nColDimCount; i++)
/*N*/       if (nColDims[i] == nColumn)
/*N*/           return sheet::DataPilotFieldOrientation_COLUMN;
/*N*/   for (i=0; i<nRowDimCount; i++)
/*N*/       if (nRowDims[i] == nColumn)
/*N*/           return sheet::DataPilotFieldOrientation_ROW;
/*N*/   for (i=0; i<nDataDimCount; i++)
/*N*/       if (nDataDims[i] == nColumn)
/*N*/           return sheet::DataPilotFieldOrientation_DATA;
/*N*/   for (i=0; i<nPageDimCount; i++)
/*?*/       if (nPageDims[i] == nColumn)
/*?*/           return sheet::DataPilotFieldOrientation_PAGE;
/*N*/   return sheet::DataPilotFieldOrientation_HIDDEN;
/*N*/ }



/*N*/ long ScDPSource::GetPosition(long nColumn)
/*N*/ {
/*N*/   long i;
/*N*/   for (i=0; i<nColDimCount; i++)
/*N*/       if (nColDims[i] == nColumn)
/*N*/           return i;
/*N*/   for (i=0; i<nRowDimCount; i++)
/*N*/       if (nRowDims[i] == nColumn)
/*N*/           return i;
/*N*/   for (i=0; i<nDataDimCount; i++)
/*N*/       if (nDataDims[i] == nColumn)
/*N*/           return i;
/*N*/   for (i=0; i<nPageDimCount; i++)
/*?*/       if (nPageDims[i] == nColumn)
/*?*/           return i;
/*N*/   return 0;
/*N*/ }

/*N*/ BOOL lcl_TestSubTotal( BOOL& rAllowed, long nColumn, long* pArray, long nCount, ScDPSource* pSource )
/*N*/ {
/*N*/   for (long i=0; i<nCount; i++)
/*N*/       if (pArray[i] == nColumn)
/*N*/       {
/*N*/           //  no subtotals for data layout dim, no matter where
/*N*/           if ( pSource->IsDataLayoutDimension(nColumn) )
/*N*/               rAllowed = FALSE;
/*N*/           else
/*N*/           {
/*N*/               //  no subtotals if no other dim but data layout follows
/*N*/               long nNextIndex = i+1;
/*N*/               if ( nNextIndex < nCount && pSource->IsDataLayoutDimension(pArray[nNextIndex]) )
/*N*/                   ++nNextIndex;
/*N*/               if ( nNextIndex >= nCount )
/*N*/                   rAllowed = FALSE;
/*N*/           }
/*N*/
/*N*/           return TRUE;    // found
/*N*/       }
/*N*/   return FALSE;
/*N*/ }

/*N*/ BOOL ScDPSource::SubTotalAllowed(long nColumn)
/*N*/ {
/*N*/   //! cache this at ScDPResultData
/*N*/   BOOL bAllowed = TRUE;
/*N*/   if ( lcl_TestSubTotal( bAllowed, nColumn, nColDims, nColDimCount, this ) )
/*N*/       return bAllowed;
/*N*/   if ( lcl_TestSubTotal( bAllowed, nColumn, nRowDims, nRowDimCount, this ) )
/*N*/       return bAllowed;
/*N*/   return bAllowed;
/*N*/ }

/*N*/ void lcl_RemoveDim( long nRemove, long* pDims, long& rCount )
/*N*/ {
/*N*/   for (long i=0; i<rCount; i++)
/*N*/       if ( pDims[i] == nRemove )
/*N*/       {
/*?*/           for (long j=i; j+1<rCount; j++)
/*?*/               pDims[j] = pDims[j+1];
/*?*/           --rCount;
/*?*/           return;
/*N*/       }
/*N*/ }

/*N*/ void ScDPSource::SetOrientation(long nColumn, USHORT nNew)
/*N*/ {
/*N*/   //! change to no-op if new orientation is equal to old?
/*N*/
/*N*/   // remove from old list
/*N*/   lcl_RemoveDim( nColumn, nColDims, nColDimCount );
/*N*/   lcl_RemoveDim( nColumn, nRowDims, nRowDimCount );
/*N*/   lcl_RemoveDim( nColumn, nDataDims, nDataDimCount );
/*N*/   lcl_RemoveDim( nColumn, nPageDims, nPageDimCount );
/*N*/
/*N*/   // add to new list
/*N*/   switch (nNew)
/*N*/   {
/*N*/       case sheet::DataPilotFieldOrientation_COLUMN:
/*N*/           nColDims[nColDimCount++] = nColumn;
/*N*/           break;
/*N*/       case sheet::DataPilotFieldOrientation_ROW:
/*N*/           nRowDims[nRowDimCount++] = nColumn;
/*N*/           break;
/*N*/       case sheet::DataPilotFieldOrientation_DATA:
/*N*/           nDataDims[nDataDimCount++] = nColumn;
/*N*/           break;
/*N*/       case sheet::DataPilotFieldOrientation_PAGE:
/*?*/           nPageDims[nPageDimCount++] = nColumn;
/*N*/           break;
/*N*/   }
/*N*/ }

/*N*/ BOOL ScDPSource::IsDataLayoutDimension(long nDim)
/*N*/ {
/*N*/   return nDim == pData->GetColumnCount();
/*N*/ }


/*N*/ BOOL ScDPSource::IsDateDimension(long nDim)
/*N*/ {
/*N*/   return pData->IsDateDimension(nDim);
/*N*/ }

/*N*/ ScDPDimensions* ScDPSource::GetDimensionsObject()
/*N*/ {
/*N*/   if (!pDimensions)
/*N*/   {
/*N*/       pDimensions = new ScDPDimensions(this);
/*N*/       pDimensions->acquire();                     // ref-counted
/*N*/   }
/*N*/   return pDimensions;
/*N*/ }

/*N*/ uno::Reference<container::XNameAccess> SAL_CALL ScDPSource::getDimensions() throw(uno::RuntimeException)
/*N*/ {
/*N*/   return GetDimensionsObject();
/*N*/ }



/*N*/ long ScDPSource::GetSourceDim(long nDim)
/*N*/ {
/*N*/   //  original source dimension or data layout dimension?
/*N*/   if ( nDim <= pData->GetColumnCount() )
/*N*/       return nDim;
/*N*/
/*?*/   if ( nDim < pDimensions->getCount() )
/*?*/   {
/*?*/       ScDPDimension* pDimObj = pDimensions->getByIndex( nDim );
/*?*/       if ( pDimObj )
/*?*/       {
/*?*/           long nSource = pDimObj->GetSourceDim();
/*?*/           if ( nSource >= 0 )
/*?*/               return nSource;
/*?*/       }
/*?*/   }
/*?*/
/*?*/   OSL_FAIL("GetSourceDim: wrong dim");
/*?*/   return nDim;
/*N*/ }

uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResults()
    throw(uno::RuntimeException)
{
    return uno::Sequence< uno::Sequence<sheet::DataResult> >(0);
}

/*?*/ void SAL_CALL ScDPSource::addRefreshListener( const uno::Reference<util::XRefreshListener >& )
/*?*/                                               throw(uno::RuntimeException)
/*?*/ {
/*?*/   OSL_FAIL("not implemented");    //! exception?
/*?*/ }

/*?*/ void SAL_CALL ScDPSource::removeRefreshListener( const uno::Reference<util::XRefreshListener >& )
/*?*/                                               throw(uno::RuntimeException)
/*?*/ {
/*?*/   OSL_FAIL("not implemented");    //! exception?
/*?*/ }


/*N*/ BOOL ScDPSource::getColumnGrand() const
/*N*/ {
/*N*/   return bColumnGrand;
/*N*/ }

/*N*/ void ScDPSource::setColumnGrand(BOOL bSet)
/*N*/ {
/*N*/   bColumnGrand = bSet;
/*N*/ }

/*N*/ BOOL ScDPSource::getRowGrand() const
/*N*/ {
/*N*/   return bRowGrand;
/*N*/ }

/*N*/ void ScDPSource::setRowGrand(BOOL bSet)
/*N*/ {
/*N*/   bRowGrand = bSet;
/*N*/ }

/*N*/ BOOL ScDPSource::getIgnoreEmptyRows() const
/*N*/ {
/*N*/   return bIgnoreEmptyRows;
/*N*/ }

/*N*/ void ScDPSource::setIgnoreEmptyRows(BOOL bSet)
/*N*/ {
/*N*/   bIgnoreEmptyRows = bSet;
/*N*/   pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
/*N*/ }

/*N*/ BOOL ScDPSource::getRepeatIfEmpty() const
/*N*/ {
/*N*/   return bRepeatIfEmpty;
/*N*/ }

/*N*/ void ScDPSource::setRepeatIfEmpty(BOOL bSet)
/*N*/ {
/*N*/   bRepeatIfEmpty = bSet;
/*N*/   pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
/*N*/ }








// XPropertySet

/*N*/ void SAL_CALL ScDPSource::setPropertyValue( const ::rtl::OUString& aPropertyName, const uno::Any& aValue )
/*N*/               throw(beans::UnknownPropertyException, beans::PropertyVetoException,
/*N*/                       lang::IllegalArgumentException, lang::WrappedTargetException,
/*N*/                       uno::RuntimeException)
/*N*/ {
/*N*/   String aNameStr = aPropertyName;
/*N*/   if ( aNameStr.EqualsAscii( SC_UNO_COLGRAND ) )
/*N*/       setColumnGrand( lcl_GetBoolFromAny( aValue ) );
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_ROWGRAND ) )
/*N*/       setRowGrand( lcl_GetBoolFromAny( aValue ) );
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_IGNOREEM ) )
/*N*/       setIgnoreEmptyRows( lcl_GetBoolFromAny( aValue ) );
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_REPEATIF ) )
/*N*/       setRepeatIfEmpty( lcl_GetBoolFromAny( aValue ) );
/*N*/   else
/*N*/   {
/*N*/       OSL_FAIL("unknown property");
/*N*/       //! THROW( UnknownPropertyException() );
/*N*/   }
/*N*/ }

/*N*/ uno::Any SAL_CALL ScDPSource::getPropertyValue( const ::rtl::OUString& aPropertyName )
/*N*/               throw(beans::UnknownPropertyException, lang::WrappedTargetException,
/*N*/                       uno::RuntimeException)
/*N*/ {
/*N*/   uno::Any aRet;
/*N*/   String aNameStr = aPropertyName;
/*N*/   if ( aNameStr.EqualsAscii( SC_UNO_COLGRAND ) )
/*N*/       lcl_SetBoolInAny( aRet, getColumnGrand() );
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_ROWGRAND ) )
/*N*/       lcl_SetBoolInAny( aRet, getRowGrand() );
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_IGNOREEM ) )
/*N*/       lcl_SetBoolInAny( aRet, getIgnoreEmptyRows() );
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_REPEATIF ) )
/*N*/       lcl_SetBoolInAny( aRet, getRepeatIfEmpty() );
/*N*/   else if ( !aNameStr.EqualsAscii( SC_UNO_DATADESC ) )             // read-only
/*N*/   {
/*N*/       OSL_FAIL("unknown property");
/*N*/       //! THROW( UnknownPropertyException() );
/*N*/   }
/*N*/   return aRet;
/*N*/ }

/*N*/ SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPSource )

// -----------------------------------------------------------------------

/*N*/ ScDPDimensions::ScDPDimensions( ScDPSource* pSrc ) :
/*N*/   pSource( pSrc ),
/*N*/   ppDims( NULL )
/*N*/ {
/*N*/   //! hold pSource
/*N*/
/*N*/   // include data layout dimension and duplicated dimensions
/*N*/   nDimCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
/*N*/ }

/*N*/ ScDPDimensions::~ScDPDimensions()
/*N*/ {
/*N*/   //! release pSource
/*N*/
/*N*/   if (ppDims)
/*N*/   {
/*N*/       for (long i=0; i<nDimCount; i++)
/*N*/           if ( ppDims[i] )
/*N*/               ppDims[i]->release();           // ref-counted
/*N*/       delete[] ppDims;
/*N*/   }
/*N*/ }


// very simple XNameAccess implementation using getCount/getByIndex

/*N*/ uno::Any SAL_CALL ScDPDimensions::getByName( const ::rtl::OUString& aName )
/*N*/           throw(container::NoSuchElementException,
/*N*/                   lang::WrappedTargetException, uno::RuntimeException)
/*N*/ {
/*N*/   long nCount = getCount();
/*N*/   for (long i=0; i<nCount; i++)
/*N*/       if ( getByIndex(i)->getName() == aName )
/*N*/       {
/*N*/           uno::Reference<container::XNamed> xNamed = getByIndex(i);
/*N*/           uno::Any aRet;
/*N*/           aRet <<= xNamed;
/*N*/           return aRet;
/*N*/       }
/*N*/
/*N*/   throw container::NoSuchElementException();
/*N*/   return uno::Any();
/*N*/ }

/*N*/ uno::Sequence<rtl::OUString> SAL_CALL ScDPDimensions::getElementNames() throw(uno::RuntimeException)
/*N*/ {
/*N*/   long nCount = getCount();
/*N*/   uno::Sequence<rtl::OUString> aSeq(nCount);
/*N*/   ::rtl::OUString* pArr = aSeq.getArray();
/*N*/   for (long i=0; i<nCount; i++)
/*N*/       pArr[i] = getByIndex(i)->getName();
/*N*/   return aSeq;
/*N*/ }

/*?*/ sal_Bool SAL_CALL ScDPDimensions::hasByName( const ::rtl::OUString& aName ) throw(uno::RuntimeException)
/*?*/ {
/*?*/   long nCount = getCount();
/*?*/   for (long i=0; i<nCount; i++)
/*?*/       if ( getByIndex(i)->getName() == aName )
/*?*/           return TRUE;
/*?*/   return FALSE;
/*?*/ }

/*?*/ uno::Type SAL_CALL ScDPDimensions::getElementType() throw(uno::RuntimeException)
/*?*/ {
/*?*/   return getCppuType((uno::Reference<container::XNamed>*)0);
/*?*/ }

/*?*/ sal_Bool SAL_CALL ScDPDimensions::hasElements() throw(uno::RuntimeException)
/*?*/ {
/*?*/   return ( getCount() > 0 );
/*?*/ }

// end of XNameAccess implementation

/*N*/ long ScDPDimensions::getCount() const
/*N*/ {
/*N*/   //  in tabular data, every column of source data is a dimension
/*N*/
/*N*/   return nDimCount;
/*N*/ }

/*N*/ ScDPDimension* ScDPDimensions::getByIndex(long nIndex) const
/*N*/ {
/*N*/   if ( nIndex >= 0 && nIndex < nDimCount )
/*N*/   {
/*N*/       if ( !ppDims )
/*N*/       {
/*N*/           ((ScDPDimensions*)this)->ppDims = new ScDPDimension*[nDimCount];
/*N*/           for (long i=0; i<nDimCount; i++)
/*N*/               ppDims[i] = NULL;
/*N*/       }
/*N*/       if ( !ppDims[nIndex] )
/*N*/       {
/*N*/           ppDims[nIndex] = new ScDPDimension( pSource, nIndex );
/*N*/           ppDims[nIndex]->acquire();      // ref-counted
/*N*/       }
/*N*/
/*N*/       return ppDims[nIndex];
/*N*/   }
/*N*/
/*N*/   return NULL;    //! exception?
/*N*/ }

// -----------------------------------------------------------------------

/*N*/ ScDPDimension::ScDPDimension( ScDPSource* pSrc, long nD ) :
/*N*/   pSource( pSrc ),
/*N*/   nDim( nD ),
/*N*/   pHierarchies( NULL ),
/*N*/   nUsedHier( 0 ),
/*N*/   nFunction( SUBTOTAL_FUNC_SUM ),     // sum is default
/*N*/   nSourceDim( -1 )
/*N*/ {
/*N*/   //! hold pSource
/*N*/ }

/*N*/ ScDPDimension::~ScDPDimension()
/*N*/ {
/*N*/   //! release pSource
/*N*/
/*N*/   if ( pHierarchies )
/*N*/       pHierarchies->release();    // ref-counted
/*N*/ }

/*N*/ ScDPHierarchies* ScDPDimension::GetHierarchiesObject()
/*N*/ {
/*N*/   if (!pHierarchies)
/*N*/   {
/*N*/       pHierarchies = new ScDPHierarchies( pSource, nDim );
/*N*/       pHierarchies->acquire();        // ref-counted
/*N*/   }
/*N*/   return pHierarchies;
/*N*/ }

/*N*/ uno::Reference<container::XNameAccess> SAL_CALL ScDPDimension::getHierarchies()
/*N*/                                                   throw(uno::RuntimeException)
/*N*/ {
/*N*/   return GetHierarchiesObject();
/*N*/ }

/*N*/ ::rtl::OUString SAL_CALL ScDPDimension::getName() throw(uno::RuntimeException)
/*N*/ {
/*N*/   if (aName.Len())
/*N*/       return aName;
/*N*/   else
/*N*/       return pSource->GetData()->getDimensionName( nDim );
/*N*/ }

/*?*/ void SAL_CALL ScDPDimension::setName( const ::rtl::OUString& rNewName ) throw(uno::RuntimeException)
/*?*/ {
/*?*/   //  used after cloning
/*?*/   aName = String( rNewName );
/*?*/ }

/*N*/ USHORT ScDPDimension::getOrientation() const
/*N*/ {
/*N*/   return pSource->GetOrientation( nDim );
/*N*/ }

/*N*/ void ScDPDimension::setOrientation(USHORT nNew)
/*N*/ {
/*N*/   pSource->SetOrientation( nDim, nNew );
/*N*/ }

/*N*/ long ScDPDimension::getPosition() const
/*N*/ {
/*N*/   return pSource->GetPosition( nDim );
/*N*/ }


/*N*/ BOOL ScDPDimension::getIsDataLayoutDimension() const
/*N*/ {
/*N*/   return pSource->GetData()->getIsDataLayoutDimension( nDim );
/*N*/ }

/*N*/ USHORT ScDPDimension::getFunction() const
/*N*/ {
/*N*/   return nFunction;
/*N*/ }

/*N*/ void ScDPDimension::setFunction(USHORT nNew)
/*N*/ {
/*N*/   nFunction = nNew;
/*N*/ }

/*N*/ long ScDPDimension::getUsedHierarchy() const
/*N*/ {
/*N*/   return nUsedHier;
/*N*/ }



// XPropertySet

/*N*/ void SAL_CALL ScDPDimension::setPropertyValue( const ::rtl::OUString& aPropertyName, const uno::Any& aValue )
/*N*/               throw(beans::UnknownPropertyException, beans::PropertyVetoException,
/*N*/                       lang::IllegalArgumentException, lang::WrappedTargetException,
/*N*/                       uno::RuntimeException)
/*N*/ {
/*N*/   String aNameStr = aPropertyName;
/*N*/   if ( aNameStr.EqualsAscii( SC_UNO_USEDHIER ) )
/*N*/   {
/*?*/       INT32 nInt;
/*?*/       aValue >>= nInt;
/*N*/   }
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_ORIENTAT ) )
/*N*/   {
/*N*/       sheet::DataPilotFieldOrientation eEnum;
/*N*/       if (aValue >>= eEnum)
/*N*/           setOrientation( eEnum );
/*N*/   }
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_FUNCTION ) )
/*N*/   {
/*N*/       sheet::GeneralFunction eEnum;
/*N*/       if (aValue >>= eEnum)
/*N*/           setFunction( eEnum );
/*N*/   }
/*N*/   if ( !aNameStr.EqualsAscii( SC_UNO_POSITION ) )
/*N*/   {
/*N*/       OSL_FAIL("unknown property");
/*N*/       //! THROW( UnknownPropertyException() );
/*N*/   }
/*N*/ }

/*N*/ uno::Any SAL_CALL ScDPDimension::getPropertyValue( const ::rtl::OUString& aPropertyName )
/*N*/               throw(beans::UnknownPropertyException, lang::WrappedTargetException,
/*N*/                       uno::RuntimeException)
/*N*/ {
/*N*/   uno::Any aRet;
/*N*/   String aNameStr = aPropertyName;
/*N*/   if ( aNameStr.EqualsAscii( SC_UNO_POSITION ) )
/*N*/       aRet <<= (sal_Int32) getPosition();
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_USEDHIER ) )
/*N*/       aRet <<= (sal_Int32) getUsedHierarchy();
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_ORIENTAT ) )
/*N*/   {
/*N*/       sheet::DataPilotFieldOrientation eVal = (sheet::DataPilotFieldOrientation)getOrientation();
/*N*/       aRet <<= eVal;
/*N*/   }
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_FUNCTION ) )
/*N*/   {
/*N*/       sheet::GeneralFunction eVal = (sheet::GeneralFunction)getFunction();
/*N*/       aRet <<= eVal;
/*N*/   }
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_ISDATALA ) )                 // read-only properties
/*N*/       lcl_SetBoolInAny( aRet, getIsDataLayoutDimension() );
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_ORIGINAL ) )
/*N*/   {
/*N*/       uno::Reference<container::XNamed> xOriginal;
/*N*/       if (nSourceDim >= 0)
/*?*/           xOriginal = pSource->GetDimensionsObject()->getByIndex(nSourceDim);
/*N*/       aRet <<= xOriginal;
/*N*/   }
/*N*/   else if ( !aNameStr.EqualsAscii( SC_UNO_NUMBERFO ) )
/*N*/   {
/*N*/       OSL_FAIL("unknown property");
/*N*/       //! THROW( UnknownPropertyException() );
/*N*/   }
/*N*/   return aRet;
/*N*/ }

/*N*/ SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPDimension )

// -----------------------------------------------------------------------

/*N*/ ScDPHierarchies::ScDPHierarchies( ScDPSource* pSrc, long nD ) :
/*N*/   pSource( pSrc ),
/*N*/   nDim( nD ),
/*N*/   ppHiers( NULL )
/*N*/ {
/*N*/   //! hold pSource
/*N*/
/*N*/   //  date columns have 3 hierarchies (flat/quarter/week), other columns only one
/*N*/   long nSrcDim = pSource->GetSourceDim( nDim );
/*N*/   if ( pSource->IsDateDimension( nSrcDim ) )
/*?*/       nHierCount = SC_DAPI_DATE_HIERARCHIES;
/*N*/   else
/*N*/       nHierCount = 1;
/*N*/ }

/*N*/ ScDPHierarchies::~ScDPHierarchies()
/*N*/ {
/*N*/   //! release pSource
/*N*/
/*N*/   if (ppHiers)
/*N*/   {
/*N*/       for (long i=0; i<nHierCount; i++)
/*N*/           if ( ppHiers[i] )
/*N*/               ppHiers[i]->release();      // ref-counted
/*N*/       delete[] ppHiers;
/*N*/   }
/*N*/ }

// very simple XNameAccess implementation using getCount/getByIndex

/*N*/ uno::Any SAL_CALL ScDPHierarchies::getByName( const ::rtl::OUString& aName )
/*N*/           throw(container::NoSuchElementException,
/*N*/                   lang::WrappedTargetException, uno::RuntimeException)
/*N*/ {
/*N*/   long nCount = getCount();
/*N*/   for (long i=0; i<nCount; i++)
/*N*/       if ( getByIndex(i)->getName() == aName )
/*N*/       {
/*N*/           uno::Reference<container::XNamed> xNamed = getByIndex(i);
/*N*/           uno::Any aRet;
/*N*/           aRet <<= xNamed;
/*N*/           return aRet;
/*N*/       }
/*N*/
/*?*/   throw container::NoSuchElementException();
/*N*/   return uno::Any();
/*N*/ }

/*N*/ uno::Sequence<rtl::OUString> SAL_CALL ScDPHierarchies::getElementNames() throw(uno::RuntimeException)
/*N*/ {
/*N*/   long nCount = getCount();
/*N*/   uno::Sequence<rtl::OUString> aSeq(nCount);
/*N*/   ::rtl::OUString* pArr = aSeq.getArray();
/*N*/   for (long i=0; i<nCount; i++)
/*N*/       pArr[i] = getByIndex(i)->getName();
/*N*/   return aSeq;
/*N*/ }

/*?*/ sal_Bool SAL_CALL ScDPHierarchies::hasByName( const ::rtl::OUString& aName ) throw(uno::RuntimeException)
/*?*/ {
/*?*/   long nCount = getCount();
/*?*/   for (long i=0; i<nCount; i++)
/*?*/       if ( getByIndex(i)->getName() == aName )
/*?*/           return TRUE;
/*?*/   return FALSE;
/*?*/ }

/*?*/ uno::Type SAL_CALL ScDPHierarchies::getElementType() throw(uno::RuntimeException)
/*?*/ {
/*?*/   return getCppuType((uno::Reference<container::XNamed>*)0);
/*?*/ }

/*?*/ sal_Bool SAL_CALL ScDPHierarchies::hasElements() throw(uno::RuntimeException)
/*?*/ {
/*?*/   return ( getCount() > 0 );
/*?*/ }

// end of XNameAccess implementation

/*N*/ long ScDPHierarchies::getCount() const
/*N*/ {
/*N*/   return nHierCount;
/*N*/ }

/*N*/ ScDPHierarchy* ScDPHierarchies::getByIndex(long nIndex) const
/*N*/ {
/*N*/   //  pass hierarchy index to new object in case the implementation
/*N*/   //  will be extended to more than one hierarchy
/*N*/
/*N*/   if ( nIndex >= 0 && nIndex < nHierCount )
/*N*/   {
/*N*/       if ( !ppHiers )
/*N*/       {
/*N*/           ((ScDPHierarchies*)this)->ppHiers = new ScDPHierarchy*[nHierCount];
/*N*/           for (long i=0; i<nHierCount; i++)
/*N*/               ppHiers[i] = NULL;
/*N*/       }
/*N*/       if ( !ppHiers[nIndex] )
/*N*/       {
/*N*/           ppHiers[nIndex] = new ScDPHierarchy( pSource, nDim, nIndex );
/*N*/           ppHiers[nIndex]->acquire();         // ref-counted
/*N*/       }
/*N*/
/*N*/       return ppHiers[nIndex];
/*N*/   }
/*N*/
/*N*/   return NULL;    //! exception?
/*N*/ }

// -----------------------------------------------------------------------

/*N*/ ScDPHierarchy::ScDPHierarchy( ScDPSource* pSrc, long nD, long nH ) :
/*N*/   pSource( pSrc ),
/*N*/   nDim( nD ),
/*N*/   nHier( nH ),
/*N*/   pLevels( NULL )
/*N*/ {
/*N*/   //! hold pSource
/*N*/ }

/*N*/ ScDPHierarchy::~ScDPHierarchy()
/*N*/ {
/*N*/   //! release pSource
/*N*/
/*N*/   if (pLevels)
/*N*/       pLevels->release();     // ref-counted
/*N*/ }

/*N*/ ScDPLevels* ScDPHierarchy::GetLevelsObject()
/*N*/ {
/*N*/   if (!pLevels)
/*N*/   {
/*N*/       pLevels = new ScDPLevels( pSource, nDim, nHier );
/*N*/       pLevels->acquire();     // ref-counted
/*N*/   }
/*N*/   return pLevels;
/*N*/ }

/*N*/ uno::Reference<container::XNameAccess> SAL_CALL ScDPHierarchy::getLevels()
/*N*/                                                   throw(uno::RuntimeException)
/*N*/ {
/*N*/   return GetLevelsObject();
/*N*/ }

/*N*/ ::rtl::OUString SAL_CALL ScDPHierarchy::getName() throw(uno::RuntimeException)
/*N*/ {
/*N*/   String aRet;        //! globstr-ID !!!!
/*N*/   switch (nHier)
/*N*/   {
/*N*/       case SC_DAPI_HIERARCHY_FLAT:
/*N*/           aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("flat"));
/*N*/           break;  //! name ???????
/*N*/       case SC_DAPI_HIERARCHY_QUARTER:
/*?*/           aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Quarter"));
/*?*/           break;  //! name ???????
/*N*/       case SC_DAPI_HIERARCHY_WEEK:
/*?*/           aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Week"));
/*?*/           break;  //! name ???????
/*N*/   }
/*N*/   return aRet;
/*N*/ }

/*?*/ void SAL_CALL ScDPHierarchy::setName( const ::rtl::OUString& ) throw(uno::RuntimeException)
/*?*/ {
/*?*/   OSL_FAIL("not implemented");        //! exception?
/*?*/ }

// -----------------------------------------------------------------------

/*N*/ ScDPLevels::ScDPLevels( ScDPSource* pSrc, long nD, long nH ) :
/*N*/   pSource( pSrc ),
/*N*/   nDim( nD ),
/*N*/   nHier( nH ),
/*N*/   ppLevs( NULL )
/*N*/ {
/*N*/   //! hold pSource
/*N*/
/*N*/   //  text columns have only one level
/*N*/
/*N*/   long nSrcDim = pSource->GetSourceDim( nDim );
/*N*/   if ( pSource->IsDateDimension( nSrcDim ) )
/*N*/   {
/*?*/       switch ( nHier )
/*?*/       {
/*?*/           case SC_DAPI_HIERARCHY_FLAT:    nLevCount = SC_DAPI_FLAT_LEVELS;    break;
/*?*/           case SC_DAPI_HIERARCHY_QUARTER: nLevCount = SC_DAPI_QUARTER_LEVELS; break;
/*?*/           case SC_DAPI_HIERARCHY_WEEK:    nLevCount = SC_DAPI_WEEK_LEVELS;    break;
/*?*/           default:
/*?*/               OSL_FAIL("wrong hierarchy");
/*?*/               nLevCount = 0;
/*?*/       }
/*N*/   }
/*N*/   else
/*N*/       nLevCount = 1;
/*N*/ }

/*N*/ ScDPLevels::~ScDPLevels()
/*N*/ {
/*N*/   //! release pSource
/*N*/
/*N*/   if (ppLevs)
/*N*/   {
/*N*/       for (long i=0; i<nLevCount; i++)
/*N*/           if ( ppLevs[i] )
/*N*/               ppLevs[i]->release();   // ref-counted
/*N*/       delete[] ppLevs;
/*N*/   }
/*N*/ }

// very simple XNameAccess implementation using getCount/getByIndex

/*N*/ uno::Any SAL_CALL ScDPLevels::getByName( const ::rtl::OUString& aName )
/*N*/           throw(container::NoSuchElementException,
/*N*/                   lang::WrappedTargetException, uno::RuntimeException)
/*N*/ {
/*N*/   long nCount = getCount();
/*N*/   for (long i=0; i<nCount; i++)
/*N*/       if ( getByIndex(i)->getName() == aName )
/*N*/       {
/*N*/           uno::Reference<container::XNamed> xNamed = getByIndex(i);
/*N*/           uno::Any aRet;
/*N*/           aRet <<= xNamed;
/*N*/           return aRet;
/*N*/       }
/*N*/
/*?*/   throw container::NoSuchElementException();
/*N*/   return uno::Any();
/*N*/ }

/*N*/ uno::Sequence<rtl::OUString> SAL_CALL ScDPLevels::getElementNames() throw(uno::RuntimeException)
/*N*/ {
/*N*/   long nCount = getCount();
/*N*/   uno::Sequence<rtl::OUString> aSeq(nCount);
/*N*/   ::rtl::OUString* pArr = aSeq.getArray();
/*N*/   for (long i=0; i<nCount; i++)
/*N*/       pArr[i] = getByIndex(i)->getName();
/*N*/   return aSeq;
/*N*/ }

/*N*/ sal_Bool SAL_CALL ScDPLevels::hasByName( const ::rtl::OUString& aName ) throw(uno::RuntimeException)
/*N*/ {
/*N*/   long nCount = getCount();
/*N*/   for (long i=0; i<nCount; i++)
/*N*/       if ( getByIndex(i)->getName() == aName )
/*N*/           return TRUE;
/*N*/   return FALSE;
/*N*/ }

/*N*/ uno::Type SAL_CALL ScDPLevels::getElementType() throw(uno::RuntimeException)
/*N*/ {
/*N*/   return getCppuType((uno::Reference<container::XNamed>*)0);
/*N*/ }

/*N*/ sal_Bool SAL_CALL ScDPLevels::hasElements() throw(uno::RuntimeException)
/*N*/ {
/*N*/   return ( getCount() > 0 );
/*N*/ }

// end of XNameAccess implementation

/*N*/ long ScDPLevels::getCount() const
/*N*/ {
/*N*/   return nLevCount;
/*N*/ }

/*N*/ ScDPLevel* ScDPLevels::getByIndex(long nIndex) const
/*N*/ {
/*N*/   if ( nIndex >= 0 && nIndex < nLevCount )
/*N*/   {
/*N*/       if ( !ppLevs )
/*N*/       {
/*N*/           ((ScDPLevels*)this)->ppLevs = new ScDPLevel*[nLevCount];
/*N*/           for (long i=0; i<nLevCount; i++)
/*N*/               ppLevs[i] = NULL;
/*N*/       }
/*N*/       if ( !ppLevs[nIndex] )
/*N*/       {
/*N*/           ppLevs[nIndex] = new ScDPLevel( pSource, nDim, nHier, nIndex );
/*N*/           ppLevs[nIndex]->acquire();      // ref-counted
/*N*/       }
/*N*/
/*N*/       return ppLevs[nIndex];
/*N*/   }
/*N*/
/*N*/   return NULL;    //! exception?
/*N*/ }

// -----------------------------------------------------------------------

/*N*/ ScDPLevel::ScDPLevel( ScDPSource* pSrc, long nD, long nH, long nL ) :
/*N*/   pSource( pSrc ),
/*N*/   nDim( nD ),
/*N*/   nHier( nH ),
/*N*/   nLev( nL ),
/*N*/   pMembers( NULL ),
/*N*/   bShowEmpty( FALSE )
/*N*/ {
/*N*/   //! hold pSource
/*N*/   //  aSubTotals is empty
/*N*/ }

/*N*/ ScDPLevel::~ScDPLevel()
/*N*/ {
/*N*/ }


uno::Reference<container::XNameAccess> SAL_CALL ScDPLevel::getMembers() throw(uno::RuntimeException)
{
    return uno::Reference<container::XNameAccess>(0);
}

uno::Sequence<sheet::MemberResult> SAL_CALL ScDPLevel::getResults() throw(uno::RuntimeException)
{
    return uno::Sequence<sheet::MemberResult>(0);       //! Error?
}

/*N*/ ::rtl::OUString SAL_CALL ScDPLevel::getName() throw(uno::RuntimeException)
/*N*/ {
/*N*/   long nSrcDim = pSource->GetSourceDim( nDim );
/*N*/   if ( pSource->IsDateDimension( nSrcDim ) )
/*?*/   {
/*?*/       String aRet;        //! globstr-ID !!!!
/*?*/
/*?*/       if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
/*?*/       {
/*?*/           switch ( nLev )
/*?*/           {
/*?*/               case SC_DAPI_LEVEL_YEAR:
/*?*/                   aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Year"));
/*?*/                   break;
/*?*/               case SC_DAPI_LEVEL_QUARTER:
/*?*/                   aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Quarter"));
/*?*/                   break;
/*?*/               case SC_DAPI_LEVEL_MONTH:
/*?*/                   aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Month"));
/*?*/                   break;
/*?*/               case SC_DAPI_LEVEL_DAY:
/*?*/                   aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Day"));
/*?*/                   break;
/*?*/           }
/*?*/       }
/*?*/       else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
/*?*/       {
/*?*/           switch ( nLev )
/*?*/           {
/*?*/               case SC_DAPI_LEVEL_YEAR:
/*?*/                   aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Year"));
/*?*/                   break;
/*?*/               case SC_DAPI_LEVEL_WEEK:
/*?*/                   aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Week"));
/*?*/                   break;
/*?*/               case SC_DAPI_LEVEL_WEEKDAY:
/*?*/                   aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Weekday"));
/*?*/                   break;
/*?*/           }
/*?*/       }
/*?*/       if (aRet.Len())
/*?*/           return aRet;
/*N*/   }
/*N*/
/*N*/   return pSource->GetData()->getDimensionName( nSrcDim );     // (original) dimension name
/*N*/ }

/*?*/ void SAL_CALL ScDPLevel::setName( const ::rtl::OUString& ) throw(uno::RuntimeException)
/*?*/ {
/*?*/   OSL_FAIL("not implemented");        //! exception?
/*?*/ }

/*N*/ uno::Sequence<sheet::GeneralFunction> ScDPLevel::getSubTotals() const
/*N*/ {
/*N*/   //! separate functions for settings and evaluation?
/*N*/
/*N*/   long nSrcDim = pSource->GetSourceDim( nDim );
/*N*/   if ( !pSource->SubTotalAllowed( nSrcDim ) )
/*N*/       return uno::Sequence<sheet::GeneralFunction>(0);
/*N*/
/*N*/   return aSubTotals;
/*N*/ }



/*N*/ void ScDPLevel::setShowEmpty(BOOL bSet)
/*N*/ {
/*N*/   bShowEmpty = bSet;
/*N*/ }

// XPropertySet

/*N*/ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPLevel::getPropertySetInfo()
/*N*/                                                       throw(uno::RuntimeException)
/*N*/ {
/*N*/   SolarMutexGuard aGuard;
/*N*/
/*N*/   static SfxItemPropertyMap aDPLevelMap_Impl[] =
/*N*/   {
/*N*/       {MAP_CHAR_LEN(SC_UNO_SHOWEMPT), 0,  &getBooleanCppuType(),                                   0, 0 },
/*N*/       {MAP_CHAR_LEN(SC_UNO_SUBTOTAL), 0,  &getCppuType((uno::Sequence<sheet::GeneralFunction>*)0), 0, 0 },
/*N*/       {0,0,0,0,0,0}
/*N*/   };
/*N*/   static uno::Reference<beans::XPropertySetInfo> aRef =
/*N*/       new SfxItemPropertySetInfo( aDPLevelMap_Impl );
/*N*/   return aRef;
/*N*/ }

/*N*/ void SAL_CALL ScDPLevel::setPropertyValue( const ::rtl::OUString& aPropertyName, const uno::Any& aValue )
/*N*/               throw(beans::UnknownPropertyException, beans::PropertyVetoException,
/*N*/                       lang::IllegalArgumentException, lang::WrappedTargetException,
/*N*/                       uno::RuntimeException)
/*N*/ {
/*N*/   String aNameStr = aPropertyName;
/*N*/   if ( aNameStr.EqualsAscii( SC_UNO_SHOWEMPT ) )
/*N*/       setShowEmpty( lcl_GetBoolFromAny( aValue ) );
/*N*/   else if ( aNameStr.EqualsAscii( SC_UNO_SUBTOTAL ) )
/*N*/   {
/*?*/       uno::Sequence<sheet::GeneralFunction> aSeq;
/*?*/       aValue >>= aSeq;
/*N*/   }
/*N*/   else
/*N*/   {
/*N*/       OSL_FAIL("unknown property");
/*N*/       //! THROW( UnknownPropertyException() );
/*N*/   }
/*N*/ }

/*N*/ uno::Any SAL_CALL ScDPLevel::getPropertyValue( const ::rtl::OUString& aPropertyName )
/*N*/               throw(beans::UnknownPropertyException, lang::WrappedTargetException,
/*N*/                       uno::RuntimeException)
/*N*/ {
/*N*/   uno::Any aRet;
/*N*/   String aNameStr = aPropertyName;
/*N*/   if ( aNameStr.EqualsAscii( SC_UNO_SUBTOTAL ) )
/*N*/   {
/*N*/       uno::Sequence<sheet::GeneralFunction> aSeq = getSubTotals();        //! avoid extra copy?
/*N*/       aRet <<= aSeq;
/*N*/   }
/*N*/   if ( !aNameStr.EqualsAscii( SC_UNO_SHOWEMPT ) )
/*N*/   {
/*N*/       OSL_FAIL("unknown property");
/*N*/       //! THROW( UnknownPropertyException() );
/*N*/   }
/*N*/   return aRet;
/*N*/ }

/*N*/ SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPLevel )

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
