LCOV - code coverage report
Current view: top level - libreoffice/sc/source/filter/oox - pivotcachebuffer.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 4 751 0.5 %
Date: 2012-12-27 Functions: 3 96 3.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "pivotcachebuffer.hxx"
      21             : 
      22             : #include <set>
      23             : #include <com/sun/star/container/XIndexAccess.hpp>
      24             : #include <com/sun/star/container/XNameAccess.hpp>
      25             : #include <com/sun/star/container/XNamed.hpp>
      26             : #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
      27             : #include <com/sun/star/sheet/DataPilotFieldGroupInfo.hpp>
      28             : #include <com/sun/star/sheet/XDataPilotFieldGrouping.hpp>
      29             : #include <rtl/ustrbuf.hxx>
      30             : #include "oox/core/filterbase.hxx"
      31             : #include "oox/helper/attributelist.hxx"
      32             : #include "oox/helper/containerhelper.hxx"
      33             : #include "oox/helper/propertyset.hxx"
      34             : #include "oox/token/properties.hxx"
      35             : #include "biffinputstream.hxx"
      36             : #include "defnamesbuffer.hxx"
      37             : #include "excelhandlers.hxx"
      38             : #include "pivotcachefragment.hxx"
      39             : #include "sheetdatabuffer.hxx"
      40             : #include "tablebuffer.hxx"
      41             : #include "unitconverter.hxx"
      42             : #include "worksheetbuffer.hxx"
      43             : 
      44             : namespace oox {
      45             : namespace xls {
      46             : 
      47             : // ============================================================================
      48             : 
      49             : using namespace ::com::sun::star::container;
      50             : using namespace ::com::sun::star::sheet;
      51             : using namespace ::com::sun::star::table;
      52             : using namespace ::com::sun::star::uno;
      53             : using namespace ::com::sun::star::util;
      54             : 
      55             : using ::oox::core::Relations;
      56             : using ::rtl::OUString;
      57             : using ::rtl::OUStringBuffer;
      58             : 
      59             : // ============================================================================
      60             : 
      61             : namespace {
      62             : 
      63             : const sal_uInt16 BIFF12_PCDFIELD_SERVERFIELD        = 0x0001;
      64             : const sal_uInt16 BIFF12_PCDFIELD_NOUNIQUEITEMS      = 0x0002;
      65             : const sal_uInt16 BIFF12_PCDFIELD_DATABASEFIELD      = 0x0004;
      66             : const sal_uInt16 BIFF12_PCDFIELD_HASCAPTION         = 0x0008;
      67             : const sal_uInt16 BIFF12_PCDFIELD_MEMBERPROPFIELD    = 0x0010;
      68             : const sal_uInt16 BIFF12_PCDFIELD_HASFORMULA         = 0x0100;
      69             : const sal_uInt16 BIFF12_PCDFIELD_HASPROPERTYNAME    = 0x0200;
      70             : 
      71             : const sal_uInt16 BIFF12_PCDFSITEMS_HASSEMIMIXED     = 0x0001;
      72             : const sal_uInt16 BIFF12_PCDFSITEMS_HASNONDATE       = 0x0002;
      73             : const sal_uInt16 BIFF12_PCDFSITEMS_HASDATE          = 0x0004;
      74             : const sal_uInt16 BIFF12_PCDFSITEMS_HASSTRING        = 0x0008;
      75             : const sal_uInt16 BIFF12_PCDFSITEMS_HASBLANK         = 0x0010;
      76             : const sal_uInt16 BIFF12_PCDFSITEMS_HASMIXED         = 0x0020;
      77             : const sal_uInt16 BIFF12_PCDFSITEMS_ISNUMERIC        = 0x0040;
      78             : const sal_uInt16 BIFF12_PCDFSITEMS_ISINTEGER        = 0x0080;
      79             : const sal_uInt16 BIFF12_PCDFSITEMS_HASMINMAX        = 0x0100;
      80             : const sal_uInt16 BIFF12_PCDFSITEMS_HASLONGTEXT      = 0x0200;
      81             : 
      82             : const sal_uInt16 BIFF12_PCITEM_ARRAY_DOUBLE         = 0x0001;
      83             : const sal_uInt16 BIFF12_PCITEM_ARRAY_STRING         = 0x0002;
      84             : const sal_uInt16 BIFF12_PCITEM_ARRAY_ERROR          = 0x0010;
      85             : const sal_uInt16 BIFF12_PCITEM_ARRAY_DATE           = 0x0020;
      86             : 
      87             : const sal_uInt8 BIFF12_PCDFRANGEPR_AUTOSTART        = 0x01;
      88             : const sal_uInt8 BIFF12_PCDFRANGEPR_AUTOEND          = 0x02;
      89             : const sal_uInt8 BIFF12_PCDFRANGEPR_DATEGROUP        = 0x04;
      90             : 
      91             : const sal_uInt8 BIFF12_PCDEFINITION_SAVEDATA        = 0x01;
      92             : const sal_uInt8 BIFF12_PCDEFINITION_INVALID         = 0x02;
      93             : const sal_uInt8 BIFF12_PCDEFINITION_REFRESHONLOAD   = 0x04;
      94             : const sal_uInt8 BIFF12_PCDEFINITION_OPTIMIZEMEMORY  = 0x08;
      95             : const sal_uInt8 BIFF12_PCDEFINITION_ENABLEREFRESH   = 0x10;
      96             : const sal_uInt8 BIFF12_PCDEFINITION_BACKGROUNDQUERY = 0x20;
      97             : const sal_uInt8 BIFF12_PCDEFINITION_UPGRADEONREFR   = 0x40;
      98             : const sal_uInt8 BIFF12_PCDEFINITION_TUPELCACHE      = 0x80;
      99             : 
     100             : const sal_uInt8 BIFF12_PCDEFINITION_HASUSERNAME     = 0x01;
     101             : const sal_uInt8 BIFF12_PCDEFINITION_HASRELID        = 0x02;
     102             : const sal_uInt8 BIFF12_PCDEFINITION_SUPPORTSUBQUERY = 0x04;
     103             : const sal_uInt8 BIFF12_PCDEFINITION_SUPPORTDRILL    = 0x08;
     104             : 
     105             : const sal_uInt8 BIFF12_PCDWBSOURCE_HASRELID         = 0x01;
     106             : const sal_uInt8 BIFF12_PCDWBSOURCE_HASSHEET         = 0x02;
     107             : 
     108             : // ----------------------------------------------------------------------------
     109             : 
     110             : const sal_uInt16 BIFF_PCDSOURCE_WORKSHEET           = 0x0001;
     111             : const sal_uInt16 BIFF_PCDSOURCE_EXTERNAL            = 0x0002;
     112             : const sal_uInt16 BIFF_PCDSOURCE_CONSOLIDATION       = 0x0004;
     113             : const sal_uInt16 BIFF_PCDSOURCE_SCENARIO            = 0x0010;
     114             : 
     115             : const sal_uInt16 BIFF_PC_NOSTRING                   = 0xFFFF;
     116             : 
     117             : const sal_uInt16 BIFF_PCDFIELD_HASITEMS             = 0x0001;
     118             : const sal_uInt16 BIFF_PCDFIELD_HASUNSHAREDITEMS     = 0x0002;
     119             : const sal_uInt16 BIFF_PCDFIELD_CALCULATED           = 0x0004;
     120             : const sal_uInt16 BIFF_PCDFIELD_HASPARENT            = 0x0008;
     121             : const sal_uInt16 BIFF_PCDFIELD_RANGEGROUP           = 0x0010;
     122             : const sal_uInt16 BIFF_PCDFIELD_ISNUMERIC            = 0x0020;
     123             : const sal_uInt16 BIFF_PCDFIELD_HASSEMIMIXED         = 0x0080;
     124             : const sal_uInt16 BIFF_PCDFIELD_HASMINMAX            = 0x0100;
     125             : const sal_uInt16 BIFF_PCDFIELD_HASLONGINDEX         = 0x0200;
     126             : const sal_uInt16 BIFF_PCDFIELD_HASNONDATE           = 0x0400;
     127             : const sal_uInt16 BIFF_PCDFIELD_HASDATE              = 0x0800;
     128             : const sal_uInt16 BIFF_PCDFIELD_SERVERFIELD          = 0x2000;
     129             : const sal_uInt16 BIFF_PCDFIELD_NOUNIQUEITEMS        = 0x4000;
     130             : 
     131             : const sal_uInt16 BIFF_PCDFRANGEPR_AUTOSTART         = 0x0001;
     132             : const sal_uInt16 BIFF_PCDFRANGEPR_AUTOEND           = 0x0002;
     133             : 
     134             : const sal_uInt16 BIFF_PCDEFINITION_SAVEDATA         = 0x0001;
     135             : const sal_uInt16 BIFF_PCDEFINITION_INVALID          = 0x0002;
     136             : const sal_uInt16 BIFF_PCDEFINITION_REFRESHONLOAD    = 0x0004;
     137             : const sal_uInt16 BIFF_PCDEFINITION_OPTIMIZEMEMORY   = 0x0008;
     138             : const sal_uInt16 BIFF_PCDEFINITION_BACKGROUNDQUERY  = 0x0010;
     139             : const sal_uInt16 BIFF_PCDEFINITION_ENABLEREFRESH    = 0x0020;
     140             : 
     141             : // ----------------------------------------------------------------------------
     142             : 
     143             : /** Adjusts the weird date format read from binary streams.
     144             : 
     145             :     Dates before 1900-Mar-01 are stored including the non-existing leap day
     146             :     1900-02-29. Time values (without date) are stored as times of day
     147             :     1900-Jan-00. Nothing has to be done when the workbook is stored in 1904
     148             :     date mode (dates before 1904-Jan-01 will not occur in this case).
     149             :  */
     150           0 : void lclAdjustBinDateTime( DateTime& orDateTime )
     151             : {
     152           0 :     if( (orDateTime.Year == 1900) && (orDateTime.Month <= 2) )
     153             :     {
     154             :         OSL_ENSURE( (orDateTime.Month == 1) || ((orDateTime.Month == 2) && (orDateTime.Day > 0)), "lclAdjustBinDateTime - invalid date" );
     155           0 :         switch( orDateTime.Month )
     156             :         {
     157           0 :             case 2: if( orDateTime.Day > 1 ) --orDateTime.Day; else { orDateTime.Day += 30; --orDateTime.Month; }                       break;
     158           0 :             case 1: if( orDateTime.Day > 1 ) --orDateTime.Day; else { orDateTime.Day += 30; orDateTime.Month = 12; --orDateTime.Year; } break;
     159             :         }
     160             :     }
     161           0 : }
     162             : 
     163             : } // namespace
     164             : 
     165             : // ============================================================================
     166             : 
     167           0 : PivotCacheItem::PivotCacheItem() :
     168           0 :     mnType( XML_m ), mbUnused( false )
     169             : {
     170           0 : }
     171             : 
     172           0 : void PivotCacheItem::readString( const AttributeList& rAttribs )
     173             : {
     174           0 :     maValue <<= rAttribs.getXString( XML_v, OUString() );
     175           0 :     mnType = XML_s;
     176           0 : }
     177             : 
     178           0 : void PivotCacheItem::readNumeric( const AttributeList& rAttribs )
     179             : {
     180           0 :     maValue <<= rAttribs.getDouble( XML_v, 0.0 );
     181           0 :     mnType = XML_n;
     182           0 :     mbUnused = rAttribs.getBool( XML_u, false );
     183           0 : }
     184             : 
     185           0 : void PivotCacheItem::readDate( const AttributeList& rAttribs )
     186             : {
     187           0 :     maValue <<= rAttribs.getDateTime( XML_v, DateTime() );
     188           0 :     mnType = XML_d;
     189           0 : }
     190             : 
     191           0 : void PivotCacheItem::readBool( const AttributeList& rAttribs )
     192             : {
     193           0 :     maValue <<= rAttribs.getBool( XML_v, false );
     194           0 :     mnType = XML_b;
     195           0 : }
     196             : 
     197           0 : void PivotCacheItem::readError( const AttributeList& rAttribs, const UnitConverter& rUnitConverter )
     198             : {
     199           0 :     maValue <<= static_cast< sal_Int32 >( rUnitConverter.calcBiffErrorCode( rAttribs.getXString( XML_v, OUString() ) ) );
     200           0 :     mnType = XML_e;
     201           0 : }
     202             : 
     203           0 : void PivotCacheItem::readIndex( const AttributeList& rAttribs )
     204             : {
     205           0 :     maValue <<= rAttribs.getInteger( XML_v, -1 );
     206           0 :     mnType = XML_x;
     207           0 : }
     208             : 
     209           0 : void PivotCacheItem::readString( SequenceInputStream& rStrm )
     210             : {
     211           0 :     maValue <<= BiffHelper::readString( rStrm );
     212           0 :     mnType = XML_s;
     213           0 : }
     214             : 
     215           0 : void PivotCacheItem::readDouble( SequenceInputStream& rStrm )
     216             : {
     217           0 :     maValue <<= rStrm.readDouble();
     218           0 :     mnType = XML_n;
     219           0 : }
     220             : 
     221           0 : void PivotCacheItem::readDate( SequenceInputStream& rStrm )
     222             : {
     223           0 :     DateTime aDateTime;
     224           0 :     aDateTime.Year = rStrm.readuInt16();
     225           0 :     aDateTime.Month = rStrm.readuInt16();
     226           0 :     aDateTime.Day = rStrm.readuInt8();
     227           0 :     aDateTime.Hours = rStrm.readuInt8();
     228           0 :     aDateTime.Minutes = rStrm.readuInt8();
     229           0 :     aDateTime.Seconds = rStrm.readuInt8();
     230           0 :     lclAdjustBinDateTime( aDateTime );
     231           0 :     maValue <<= aDateTime;
     232           0 :     mnType = XML_d;
     233           0 : }
     234             : 
     235           0 : void PivotCacheItem::readBool( SequenceInputStream& rStrm )
     236             : {
     237           0 :     maValue <<= (rStrm.readuInt8() != 0);
     238           0 :     mnType = XML_b;
     239           0 : }
     240             : 
     241           0 : void PivotCacheItem::readError( SequenceInputStream& rStrm )
     242             : {
     243           0 :     maValue <<= static_cast< sal_Int32 >( rStrm.readuInt8() );
     244           0 :     mnType = XML_e;
     245           0 : }
     246             : 
     247           0 : void PivotCacheItem::readIndex( SequenceInputStream& rStrm )
     248             : {
     249           0 :     maValue <<= rStrm.readInt32();
     250           0 :     mnType = XML_x;
     251           0 : }
     252             : 
     253           0 : void PivotCacheItem::readString( BiffInputStream& rStrm, const WorkbookHelper& rHelper )
     254             : {
     255           0 :     maValue <<= (rHelper.getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( true, rHelper.getTextEncoding() );
     256           0 :     mnType = XML_s;
     257           0 : }
     258             : 
     259           0 : void PivotCacheItem::readDouble( BiffInputStream& rStrm )
     260             : {
     261           0 :     maValue <<= rStrm.readDouble();
     262           0 :     mnType = XML_n;
     263           0 : }
     264             : 
     265           0 : void PivotCacheItem::readInteger( BiffInputStream& rStrm )
     266             : {
     267           0 :     maValue <<= rStrm.readInt16();
     268           0 :     mnType = XML_i;                 // fake, used for BIFF only
     269           0 : }
     270             : 
     271           0 : void PivotCacheItem::readDate( BiffInputStream& rStrm )
     272             : {
     273           0 :     DateTime aDateTime;
     274           0 :     aDateTime.Year = rStrm.readuInt16();
     275           0 :     aDateTime.Month = rStrm.readuInt16();
     276           0 :     aDateTime.Day = rStrm.readuInt8();
     277           0 :     aDateTime.Hours = rStrm.readuInt8();
     278           0 :     aDateTime.Minutes = rStrm.readuInt8();
     279           0 :     aDateTime.Seconds = rStrm.readuInt8();
     280           0 :     lclAdjustBinDateTime( aDateTime );
     281           0 :     maValue <<= aDateTime;
     282           0 :     mnType = XML_d;
     283           0 : }
     284             : 
     285           0 : void PivotCacheItem::readBool( BiffInputStream& rStrm )
     286             : {
     287           0 :     maValue <<= (rStrm.readuInt8() != 0);
     288           0 :     mnType = XML_b;
     289           0 : }
     290             : 
     291           0 : void PivotCacheItem::readError( BiffInputStream& rStrm )
     292             : {
     293           0 :     maValue <<= static_cast< sal_Int32 >( rStrm.readuInt8() );
     294           0 :     mnType = XML_e;
     295           0 : }
     296             : 
     297           0 : void PivotCacheItem::setStringValue( const OUString& sString )
     298             : {
     299           0 :     mnType = XML_s;
     300           0 :     maValue <<= sString;
     301           0 : }
     302             : 
     303           0 : OUString PivotCacheItem::getName() const
     304             : {
     305           0 :     switch( mnType )
     306             :     {
     307           0 :         case XML_m: return OUString();
     308           0 :         case XML_s: return maValue.get< OUString >();
     309           0 :         case XML_n: return OUString::valueOf( maValue.get< double >() );                            // !TODO
     310           0 :         case XML_i: return OUString::valueOf( maValue.get< sal_Int32 >() );
     311           0 :         case XML_d: return OUString();                                                              // !TODO
     312           0 :         case XML_b: return OUString::valueOf( static_cast< sal_Bool >( maValue.get< bool >() ) );   // !TODO
     313           0 :         case XML_e: return OUString();                                                              // !TODO
     314             :     }
     315             :     OSL_FAIL( "PivotCacheItem::getName - invalid data type" );
     316           0 :     return OUString();
     317             : }
     318             : 
     319             : // ----------------------------------------------------------------------------
     320             : 
     321           0 : PivotCacheItemList::PivotCacheItemList( const WorkbookHelper& rHelper ) :
     322           0 :     WorkbookHelper( rHelper )
     323             : {
     324           0 : }
     325             : 
     326           0 : void PivotCacheItemList::importItem( sal_Int32 nElement, const AttributeList& rAttribs )
     327             : {
     328           0 :     PivotCacheItem& rItem = createItem();
     329           0 :     switch( nElement )
     330             :     {
     331           0 :         case XLS_TOKEN( m ):                                                        break;
     332           0 :         case XLS_TOKEN( s ):    rItem.readString( rAttribs );                       break;
     333           0 :         case XLS_TOKEN( n ):    rItem.readNumeric( rAttribs );                      break;
     334           0 :         case XLS_TOKEN( d ):    rItem.readDate( rAttribs );                         break;
     335           0 :         case XLS_TOKEN( b ):    rItem.readBool( rAttribs );                         break;
     336           0 :         case XLS_TOKEN( e ):    rItem.readError( rAttribs, getUnitConverter() );    break;
     337             :         default:    OSL_FAIL( "PivotCacheItemList::importItem - unknown element type" );
     338             :     }
     339           0 : }
     340             : 
     341           0 : void PivotCacheItemList::importItem( sal_Int32 nRecId, SequenceInputStream& rStrm )
     342             : {
     343           0 :     if( nRecId == BIFF12_ID_PCITEM_ARRAY )
     344             :     {
     345           0 :         importArray( rStrm );
     346           0 :         return;
     347             :     }
     348             : 
     349           0 :     PivotCacheItem& rItem = createItem();
     350           0 :     switch( nRecId )
     351             :     {
     352             :         case BIFF12_ID_PCITEM_MISSING:
     353           0 :         case BIFF12_ID_PCITEMA_MISSING:                             break;
     354             :         case BIFF12_ID_PCITEM_STRING:
     355           0 :         case BIFF12_ID_PCITEMA_STRING:  rItem.readString( rStrm );  break;
     356             :         case BIFF12_ID_PCITEM_DOUBLE:
     357           0 :         case BIFF12_ID_PCITEMA_DOUBLE:  rItem.readDouble( rStrm );  break;
     358             :         case BIFF12_ID_PCITEM_DATE:
     359           0 :         case BIFF12_ID_PCITEMA_DATE:    rItem.readDate( rStrm );    break;
     360             :         case BIFF12_ID_PCITEM_BOOL:
     361           0 :         case BIFF12_ID_PCITEMA_BOOL:    rItem.readBool( rStrm );    break;
     362             :         case BIFF12_ID_PCITEM_ERROR:
     363           0 :         case BIFF12_ID_PCITEMA_ERROR:   rItem.readError( rStrm );   break;
     364             :         default:    OSL_FAIL( "PivotCacheItemList::importItem - unknown record type" );
     365             :     }
     366             : }
     367             : 
     368           0 : void PivotCacheItemList::importItemList( BiffInputStream& rStrm, sal_uInt16 nCount )
     369             : {
     370           0 :     bool bLoop = true;
     371           0 :     for( sal_uInt16 nItemIdx = 0; bLoop && (nItemIdx < nCount); ++nItemIdx )
     372             :     {
     373           0 :         bLoop = rStrm.startNextRecord();
     374           0 :         if( bLoop ) switch( rStrm.getRecId() )
     375             :         {
     376           0 :             case BIFF_ID_PCITEM_MISSING:    createItem();                               break;
     377           0 :             case BIFF_ID_PCITEM_STRING:     createItem().readString( rStrm, *this );    break;
     378           0 :             case BIFF_ID_PCITEM_DOUBLE:     createItem().readDouble( rStrm );           break;
     379           0 :             case BIFF_ID_PCITEM_INTEGER:    createItem().readInteger( rStrm );          break;
     380           0 :             case BIFF_ID_PCITEM_DATE:       createItem().readDate( rStrm );             break;
     381           0 :             case BIFF_ID_PCITEM_BOOL:       createItem().readBool( rStrm );             break;
     382           0 :             case BIFF_ID_PCITEM_ERROR:      createItem().readError( rStrm );            break;
     383           0 :             default:                        rStrm.rewindRecord(); bLoop = false;
     384             :         }
     385             :     }
     386             :     OSL_ENSURE( bLoop, "PivotCacheItemList::importItemList - could not read all cache item records" );
     387           0 : }
     388             : 
     389           0 : const PivotCacheItem* PivotCacheItemList::getCacheItem( sal_Int32 nItemIdx ) const
     390             : {
     391           0 :     return ContainerHelper::getVectorElement( maItems, nItemIdx );
     392             : }
     393             : 
     394           0 : void PivotCacheItemList::applyItemCaptions( const IdCaptionPairList& vCaptions )
     395             : {
     396           0 :     for( IdCaptionPairList::const_iterator aIt = vCaptions.begin(), aEnd = vCaptions.end(); aIt != aEnd; ++aIt )
     397             :     {
     398           0 :         if ( static_cast<sal_uInt32>( aIt->first ) < maItems.size() )
     399           0 :             maItems[ aIt->first ].setStringValue( aIt->second );
     400             :     }
     401           0 : }
     402             : 
     403           0 : void PivotCacheItemList::getCacheItemNames( ::std::vector< OUString >& orItemNames ) const
     404             : {
     405           0 :     orItemNames.clear();
     406           0 :     orItemNames.reserve( maItems.size() );
     407           0 :     for( CacheItemVector::const_iterator aIt = maItems.begin(), aEnd = maItems.end(); aIt != aEnd; ++aIt )
     408           0 :         orItemNames.push_back( aIt->getName() );
     409           0 : }
     410             : 
     411             : // private --------------------------------------------------------------------
     412             : 
     413           0 : PivotCacheItem& PivotCacheItemList::createItem()
     414             : {
     415           0 :     maItems.resize( maItems.size() + 1 );
     416           0 :     return maItems.back();
     417             : }
     418             : 
     419           0 : void PivotCacheItemList::importArray( SequenceInputStream& rStrm )
     420             : {
     421           0 :     sal_uInt16 nType = rStrm.readuInt16();
     422           0 :     sal_Int32 nCount = rStrm.readInt32();
     423           0 :     for( sal_Int32 nIdx = 0; !rStrm.isEof() && (nIdx < nCount); ++nIdx )
     424             :     {
     425           0 :         switch( nType )
     426             :         {
     427           0 :             case BIFF12_PCITEM_ARRAY_DOUBLE: createItem().readDouble( rStrm );   break;
     428           0 :             case BIFF12_PCITEM_ARRAY_STRING: createItem().readString( rStrm );   break;
     429           0 :             case BIFF12_PCITEM_ARRAY_ERROR:  createItem().readError( rStrm );    break;
     430           0 :             case BIFF12_PCITEM_ARRAY_DATE:   createItem().readDate( rStrm );     break;
     431             :             default:
     432             :                 OSL_FAIL( "PivotCacheItemList::importArray - unknown data type" );
     433           0 :                 nIdx = nCount;
     434             :         }
     435             :     }
     436           0 : }
     437             : 
     438             : // ============================================================================
     439             : 
     440           0 : PCFieldModel::PCFieldModel() :
     441             :     mnNumFmtId( 0 ),
     442             :     mnSqlType( 0 ),
     443             :     mnHierarchy( 0 ),
     444             :     mnLevel( 0 ),
     445             :     mnMappingCount( 0 ),
     446             :     mbDatabaseField( true ),
     447             :     mbServerField( false ),
     448             :     mbUniqueList( true ),
     449           0 :     mbMemberPropField( false )
     450             : {
     451           0 : }
     452             : 
     453             : // ----------------------------------------------------------------------------
     454             : 
     455           0 : PCSharedItemsModel::PCSharedItemsModel() :
     456             :     mbHasSemiMixed( true ),
     457             :     mbHasNonDate( true ),
     458             :     mbHasDate( false ),
     459             :     mbHasString( true ),
     460             :     mbHasBlank( false ),
     461             :     mbHasMixed( false ),
     462             :     mbIsNumeric( false ),
     463             :     mbIsInteger( false ),
     464             :     mbHasLongText( false ),
     465           0 :     mbHasLongIndexes( false )
     466             : {
     467           0 : }
     468             : 
     469             : // ----------------------------------------------------------------------------
     470             : 
     471           0 : PCFieldGroupModel::PCFieldGroupModel() :
     472             :     mfStartValue( 0.0 ),
     473             :     mfEndValue( 0.0 ),
     474             :     mfInterval( 1.0 ),
     475             :     mnParentField( -1 ),
     476             :     mnBaseField( -1 ),
     477             :     mnGroupBy( XML_range ),
     478             :     mbRangeGroup( false ),
     479             :     mbDateGroup( false ),
     480             :     mbAutoStart( true ),
     481           0 :     mbAutoEnd( true )
     482             : {
     483           0 : }
     484             : 
     485           0 : void PCFieldGroupModel::setBiffGroupBy( sal_uInt8 nGroupBy )
     486             : {
     487             :     static const sal_Int32 spnGroupBy[] = { XML_range,
     488             :         XML_seconds, XML_minutes, XML_hours, XML_days, XML_months, XML_quarters, XML_years };
     489           0 :     mnGroupBy = STATIC_ARRAY_SELECT( spnGroupBy, nGroupBy, XML_range );
     490           0 : }
     491             : 
     492             : // ----------------------------------------------------------------------------
     493             : 
     494           0 : PivotCacheField::PivotCacheField( const WorkbookHelper& rHelper, bool bIsDatabaseField ) :
     495             :     WorkbookHelper( rHelper ),
     496             :     maSharedItems( rHelper ),
     497           0 :     maGroupItems( rHelper )
     498             : {
     499           0 :     maFieldModel.mbDatabaseField = bIsDatabaseField;
     500           0 : }
     501             : 
     502           0 : void PivotCacheField::importCacheField( const AttributeList& rAttribs )
     503             : {
     504           0 :     maFieldModel.maName            = rAttribs.getXString( XML_name, OUString() );
     505           0 :     maFieldModel.maCaption         = rAttribs.getXString( XML_caption, OUString() );
     506           0 :     maFieldModel.maPropertyName    = rAttribs.getXString( XML_propertyName, OUString() );
     507           0 :     maFieldModel.maFormula         = rAttribs.getXString( XML_formula, OUString() );
     508           0 :     maFieldModel.mnNumFmtId        = rAttribs.getInteger( XML_numFmtId, 0 );
     509           0 :     maFieldModel.mnSqlType         = rAttribs.getInteger( XML_sqlType, 0 );
     510           0 :     maFieldModel.mnHierarchy       = rAttribs.getInteger( XML_hierarchy, 0 );
     511           0 :     maFieldModel.mnLevel           = rAttribs.getInteger( XML_level, 0 );
     512           0 :     maFieldModel.mnMappingCount    = rAttribs.getInteger( XML_mappingCount, 0 );
     513           0 :     maFieldModel.mbDatabaseField   = rAttribs.getBool( XML_databaseField, true );
     514           0 :     maFieldModel.mbServerField     = rAttribs.getBool( XML_serverField, false );
     515           0 :     maFieldModel.mbUniqueList      = rAttribs.getBool( XML_uniqueList, true );
     516           0 :     maFieldModel.mbMemberPropField = rAttribs.getBool( XML_memberPropertyField, false );
     517           0 : }
     518             : 
     519           0 : void PivotCacheField::importSharedItems( const AttributeList& rAttribs )
     520             : {
     521             :     OSL_ENSURE( maSharedItems.empty(), "PivotCacheField::importSharedItems - multiple shared items elements" );
     522           0 :     maSharedItemsModel.mbHasSemiMixed = rAttribs.getBool( XML_containsSemiMixedTypes, true );
     523           0 :     maSharedItemsModel.mbHasNonDate   = rAttribs.getBool( XML_containsNonDate, true );
     524           0 :     maSharedItemsModel.mbHasDate      = rAttribs.getBool( XML_containsDate, false );
     525           0 :     maSharedItemsModel.mbHasString    = rAttribs.getBool( XML_containsString, true );
     526           0 :     maSharedItemsModel.mbHasBlank     = rAttribs.getBool( XML_containsBlank, false );
     527           0 :     maSharedItemsModel.mbHasMixed     = rAttribs.getBool( XML_containsMixedTypes, false );
     528           0 :     maSharedItemsModel.mbIsNumeric    = rAttribs.getBool( XML_containsNumber, false );
     529           0 :     maSharedItemsModel.mbIsInteger    = rAttribs.getBool( XML_containsInteger, false );
     530           0 :     maSharedItemsModel.mbHasLongText  = rAttribs.getBool( XML_longText, false );
     531           0 : }
     532             : 
     533           0 : void PivotCacheField::importSharedItem( sal_Int32 nElement, const AttributeList& rAttribs )
     534             : {
     535           0 :     maSharedItems.importItem( nElement, rAttribs );
     536           0 : }
     537             : 
     538           0 : void PivotCacheField::importFieldGroup( const AttributeList& rAttribs )
     539             : {
     540           0 :     maFieldGroupModel.mnParentField = rAttribs.getInteger( XML_par, -1 );
     541           0 :     maFieldGroupModel.mnBaseField   = rAttribs.getInteger( XML_base, -1 );
     542           0 : }
     543             : 
     544           0 : void PivotCacheField::importRangePr( const AttributeList& rAttribs )
     545             : {
     546           0 :     maFieldGroupModel.maStartDate    = rAttribs.getDateTime( XML_startDate, DateTime() );
     547           0 :     maFieldGroupModel.maEndDate      = rAttribs.getDateTime( XML_endDate, DateTime() );
     548           0 :     maFieldGroupModel.mfStartValue   = rAttribs.getDouble( XML_startNum, 0.0 );
     549           0 :     maFieldGroupModel.mfEndValue     = rAttribs.getDouble( XML_endNum, 0.0 );
     550           0 :     maFieldGroupModel.mfInterval     = rAttribs.getDouble( XML_groupInterval, 1.0 );
     551           0 :     maFieldGroupModel.mnGroupBy      = rAttribs.getToken( XML_groupBy, XML_range );
     552           0 :     maFieldGroupModel.mbRangeGroup   = true;
     553           0 :     maFieldGroupModel.mbDateGroup    = maFieldGroupModel.mnGroupBy != XML_range;
     554           0 :     maFieldGroupModel.mbAutoStart    = rAttribs.getBool( XML_autoStart, true );
     555           0 :     maFieldGroupModel.mbAutoEnd      = rAttribs.getBool( XML_autoEnd, true );
     556           0 : }
     557             : 
     558           0 : void PivotCacheField::importDiscretePrItem( sal_Int32 nElement, const AttributeList& rAttribs )
     559             : {
     560             :     OSL_ENSURE( nElement == XLS_TOKEN( x ), "PivotCacheField::importDiscretePrItem - unexpected element" );
     561           0 :     if( nElement == XLS_TOKEN( x ) )
     562           0 :         maDiscreteItems.push_back( rAttribs.getInteger( XML_v, -1 ) );
     563           0 : }
     564             : 
     565           0 : void PivotCacheField::importGroupItem( sal_Int32 nElement, const AttributeList& rAttribs )
     566             : {
     567           0 :     maGroupItems.importItem( nElement, rAttribs );
     568           0 : }
     569             : 
     570           0 : void PivotCacheField::importPCDField( SequenceInputStream& rStrm )
     571             : {
     572             :     sal_uInt16 nFlags;
     573           0 :     rStrm >> nFlags >> maFieldModel.mnNumFmtId;
     574           0 :     maFieldModel.mnSqlType = rStrm.readInt16();
     575           0 :     rStrm >> maFieldModel.mnHierarchy >> maFieldModel.mnLevel >> maFieldModel.mnMappingCount >> maFieldModel.maName;
     576           0 :     if( getFlag( nFlags, BIFF12_PCDFIELD_HASCAPTION ) )
     577           0 :         rStrm >> maFieldModel.maCaption;
     578           0 :     if( getFlag( nFlags, BIFF12_PCDFIELD_HASFORMULA ) )
     579           0 :         rStrm.skip( ::std::max< sal_Int32 >( rStrm.readInt32(), 0 ) );
     580           0 :     if( maFieldModel.mnMappingCount > 0 )
     581           0 :         rStrm.skip( ::std::max< sal_Int32 >( rStrm.readInt32(), 0 ) );
     582           0 :     if( getFlag( nFlags, BIFF12_PCDFIELD_HASPROPERTYNAME ) )
     583           0 :         rStrm >> maFieldModel.maPropertyName;
     584             : 
     585           0 :     maFieldModel.mbDatabaseField   = getFlag( nFlags, BIFF12_PCDFIELD_DATABASEFIELD );
     586           0 :     maFieldModel.mbServerField     = getFlag( nFlags, BIFF12_PCDFIELD_SERVERFIELD );
     587           0 :     maFieldModel.mbUniqueList      = !getFlag( nFlags, BIFF12_PCDFIELD_NOUNIQUEITEMS );
     588           0 :     maFieldModel.mbMemberPropField = getFlag( nFlags, BIFF12_PCDFIELD_MEMBERPROPFIELD );
     589           0 : }
     590             : 
     591           0 : void PivotCacheField::importPCDFSharedItems( SequenceInputStream& rStrm )
     592             : {
     593             :     sal_uInt16 nFlags;
     594           0 :     rStrm >> nFlags;
     595           0 :     maSharedItemsModel.mbHasSemiMixed = getFlag( nFlags, BIFF12_PCDFSITEMS_HASSEMIMIXED );
     596           0 :     maSharedItemsModel.mbHasNonDate   = getFlag( nFlags, BIFF12_PCDFSITEMS_HASNONDATE );
     597           0 :     maSharedItemsModel.mbHasDate      = getFlag( nFlags, BIFF12_PCDFSITEMS_HASDATE );
     598           0 :     maSharedItemsModel.mbHasString    = getFlag( nFlags, BIFF12_PCDFSITEMS_HASSTRING );
     599           0 :     maSharedItemsModel.mbHasBlank     = getFlag( nFlags, BIFF12_PCDFSITEMS_HASBLANK );
     600           0 :     maSharedItemsModel.mbHasMixed     = getFlag( nFlags, BIFF12_PCDFSITEMS_HASMIXED );
     601           0 :     maSharedItemsModel.mbIsNumeric    = getFlag( nFlags, BIFF12_PCDFSITEMS_ISNUMERIC );
     602           0 :     maSharedItemsModel.mbIsInteger    = getFlag( nFlags, BIFF12_PCDFSITEMS_ISINTEGER );
     603           0 :     maSharedItemsModel.mbHasLongText  = getFlag( nFlags, BIFF12_PCDFSITEMS_HASLONGTEXT );
     604           0 : }
     605             : 
     606           0 : void PivotCacheField::importPCDFSharedItem( sal_Int32 nRecId, SequenceInputStream& rStrm )
     607             : {
     608           0 :     maSharedItems.importItem( nRecId, rStrm );
     609           0 : }
     610             : 
     611           0 : void PivotCacheField::importPCDFieldGroup( SequenceInputStream& rStrm )
     612             : {
     613           0 :     rStrm >> maFieldGroupModel.mnParentField >> maFieldGroupModel.mnBaseField;
     614           0 : }
     615             : 
     616           0 : void PivotCacheField::importPCDFRangePr( SequenceInputStream& rStrm )
     617             : {
     618             :     sal_uInt8 nGroupBy, nFlags;
     619           0 :     rStrm >> nGroupBy >> nFlags >> maFieldGroupModel.mfStartValue >> maFieldGroupModel.mfEndValue >> maFieldGroupModel.mfInterval;
     620             : 
     621           0 :     maFieldGroupModel.setBiffGroupBy( nGroupBy );
     622           0 :     maFieldGroupModel.mbRangeGroup   = true;
     623           0 :     maFieldGroupModel.mbDateGroup    = getFlag( nFlags, BIFF12_PCDFRANGEPR_DATEGROUP );
     624           0 :     maFieldGroupModel.mbAutoStart    = getFlag( nFlags, BIFF12_PCDFRANGEPR_AUTOSTART );
     625           0 :     maFieldGroupModel.mbAutoEnd      = getFlag( nFlags, BIFF12_PCDFRANGEPR_AUTOEND );
     626             : 
     627             :     OSL_ENSURE( maFieldGroupModel.mbDateGroup == (maFieldGroupModel.mnGroupBy != XML_range), "PivotCacheField::importPCDFRangePr - wrong date flag" );
     628           0 :     if( maFieldGroupModel.mbDateGroup )
     629             :     {
     630           0 :         maFieldGroupModel.maStartDate = getUnitConverter().calcDateTimeFromSerial( maFieldGroupModel.mfStartValue );
     631           0 :         maFieldGroupModel.maEndDate   = getUnitConverter().calcDateTimeFromSerial( maFieldGroupModel.mfEndValue );
     632             :     }
     633           0 : }
     634             : 
     635           0 : void PivotCacheField::importPCDFDiscretePrItem( sal_Int32 nRecId, SequenceInputStream& rStrm )
     636             : {
     637             :     OSL_ENSURE( nRecId == BIFF12_ID_PCITEM_INDEX, "PivotCacheField::importPCDFDiscretePrItem - unexpected record" );
     638           0 :     if( nRecId == BIFF12_ID_PCITEM_INDEX )
     639           0 :         maDiscreteItems.push_back( rStrm.readInt32() );
     640           0 : }
     641             : 
     642           0 : void PivotCacheField::importPCDFGroupItem( sal_Int32 nRecId, SequenceInputStream& rStrm )
     643             : {
     644           0 :     maGroupItems.importItem( nRecId, rStrm );
     645           0 : }
     646             : 
     647           0 : void PivotCacheField::importPCDField( BiffInputStream& rStrm )
     648             : {
     649             :     sal_uInt16 nFlags, nGroupItems, nBaseItems, nSharedItems;
     650           0 :     rStrm >> nFlags;
     651           0 :     maFieldGroupModel.mnParentField  = rStrm.readuInt16();
     652           0 :     maFieldGroupModel.mnBaseField    = rStrm.readuInt16();
     653           0 :     rStrm.skip( 2 );    // number of unique items (either shared or group)
     654           0 :     rStrm >> nGroupItems >> nBaseItems >> nSharedItems;
     655           0 :     maFieldModel.maName = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( true, getTextEncoding() );
     656             : 
     657           0 :     maFieldModel.mbServerField          = getFlag( nFlags, BIFF_PCDFIELD_SERVERFIELD );
     658           0 :     maFieldModel.mbUniqueList           = !getFlag( nFlags, BIFF_PCDFIELD_NOUNIQUEITEMS );
     659           0 :     maSharedItemsModel.mbHasSemiMixed   = getFlag( nFlags, BIFF_PCDFIELD_HASSEMIMIXED );
     660           0 :     maSharedItemsModel.mbHasNonDate     = getFlag( nFlags, BIFF_PCDFIELD_HASNONDATE );
     661           0 :     maSharedItemsModel.mbHasDate        = getFlag( nFlags, BIFF_PCDFIELD_HASDATE );
     662           0 :     maSharedItemsModel.mbIsNumeric      = getFlag( nFlags, BIFF_PCDFIELD_ISNUMERIC );
     663           0 :     maSharedItemsModel.mbHasLongIndexes = getFlag( nFlags, BIFF_PCDFIELD_HASLONGINDEX );
     664           0 :     maFieldGroupModel.mbRangeGroup      = getFlag( nFlags, BIFF_PCDFIELD_RANGEGROUP );
     665             : 
     666             :     // in BIFF, presence of parent group field is denoted by a flag
     667           0 :     if( !getFlag( nFlags, BIFF_PCDFIELD_HASPARENT ) )
     668           0 :         maFieldGroupModel.mnParentField = -1;
     669             : 
     670             :     // following PCDFSQLTYPE record contains SQL type
     671           0 :     if( (rStrm.getNextRecId() == BIFF_ID_PCDFSQLTYPE) && rStrm.startNextRecord() )
     672           0 :         maFieldModel.mnSqlType = rStrm.readInt16();
     673             : 
     674             :     // read group items, if any
     675           0 :     if( nGroupItems > 0 )
     676             :     {
     677             :         OSL_ENSURE( getFlag( nFlags, BIFF_PCDFIELD_HASITEMS ), "PivotCacheField::importPCDField - missing items flag" );
     678           0 :         maGroupItems.importItemList( rStrm, nGroupItems );
     679             : 
     680           0 :         sal_uInt16 nNextRecId = rStrm.getNextRecId();
     681           0 :         bool bHasRangePr = nNextRecId == BIFF_ID_PCDFRANGEPR;
     682           0 :         bool bHasDiscretePr = nNextRecId == BIFF_ID_PCDFDISCRETEPR;
     683             : 
     684             :         OSL_ENSURE( bHasRangePr || bHasDiscretePr, "PivotCacheField::importPCDField - missing group properties record" );
     685             :         OSL_ENSURE( bHasRangePr == maFieldGroupModel.mbRangeGroup, "PivotCacheField::importPCDField - invalid range grouping flag" );
     686           0 :         if( bHasRangePr && rStrm.startNextRecord() )
     687           0 :             importPCDFRangePr( rStrm );
     688           0 :         else if( bHasDiscretePr && rStrm.startNextRecord() )
     689           0 :             importPCDFDiscretePr( rStrm );
     690             :     }
     691             : 
     692             :     // read the shared items, if any
     693           0 :     if( nSharedItems > 0 )
     694             :     {
     695             :         OSL_ENSURE( getFlag( nFlags, BIFF_PCDFIELD_HASITEMS ), "PivotCacheField::importPCDField - missing items flag" );
     696           0 :         maSharedItems.importItemList( rStrm, nSharedItems );
     697             :     }
     698           0 : }
     699             : 
     700           0 : void PivotCacheField::importPCDFRangePr( BiffInputStream& rStrm )
     701             : {
     702             :     sal_uInt16 nFlags;
     703           0 :     rStrm >> nFlags;
     704           0 :     maFieldGroupModel.setBiffGroupBy( extractValue< sal_uInt8 >( nFlags, 2, 3 ) );
     705           0 :     maFieldGroupModel.mbRangeGroup = true;
     706           0 :     maFieldGroupModel.mbDateGroup  = maFieldGroupModel.mnGroupBy != XML_range;
     707           0 :     maFieldGroupModel.mbAutoStart  = getFlag( nFlags, BIFF_PCDFRANGEPR_AUTOSTART );
     708           0 :     maFieldGroupModel.mbAutoEnd    = getFlag( nFlags, BIFF_PCDFRANGEPR_AUTOEND );
     709             : 
     710             :     /*  Start, end, and interval are stored in 3 separate item records. Type of
     711             :         the items is dependent on numeric/date mode. Numeric groups expect
     712             :         three PCITEM_DOUBLE records, date groups expect two PCITEM_DATE records
     713             :         and one PCITEM_INT record. */
     714           0 :     PivotCacheItemList aLimits( *this );
     715           0 :     aLimits.importItemList( rStrm, 3 );
     716             :     OSL_ENSURE( aLimits.size() == 3, "PivotCacheField::importPCDFRangePr - missing grouping records" );
     717           0 :     const PivotCacheItem* pStartValue = aLimits.getCacheItem( 0 );
     718           0 :     const PivotCacheItem* pEndValue = aLimits.getCacheItem( 1 );
     719           0 :     const PivotCacheItem* pInterval = aLimits.getCacheItem( 2 );
     720           0 :     if( pStartValue && pEndValue && pInterval )
     721             :     {
     722           0 :         if( maFieldGroupModel.mbDateGroup )
     723             :         {
     724           0 :             bool bHasTypes = (pStartValue->getType() == XML_d) && (pEndValue->getType() == XML_d) && (pInterval->getType() == XML_i);
     725             :             OSL_ENSURE( bHasTypes, "PivotCacheField::importPCDFRangePr - wrong data types in grouping items" );
     726           0 :             if( bHasTypes )
     727             :             {
     728           0 :                 maFieldGroupModel.maStartDate = pStartValue->getValue().get< DateTime >();
     729           0 :                 maFieldGroupModel.maEndDate   = pEndValue->getValue().get< DateTime >();
     730           0 :                 maFieldGroupModel.mfInterval  = pInterval->getValue().get< sal_Int16 >();
     731             :             }
     732             :         }
     733             :         else
     734             :         {
     735           0 :             bool bHasTypes = (pStartValue->getType() == XML_n) && (pEndValue->getType() == XML_n) && (pInterval->getType() == XML_n);
     736             :             OSL_ENSURE( bHasTypes, "PivotCacheField::importPCDFRangePr - wrong data types in grouping items" );
     737           0 :             if( bHasTypes )
     738             :             {
     739           0 :                 maFieldGroupModel.mfStartValue = pStartValue->getValue().get< double >();
     740           0 :                 maFieldGroupModel.mfEndValue   = pEndValue->getValue().get< double >();
     741           0 :                 maFieldGroupModel.mfInterval   = pInterval->getValue().get< double >();
     742             :             }
     743             :         }
     744           0 :     }
     745           0 : }
     746             : 
     747           0 : void PivotCacheField::importPCDFDiscretePr( BiffInputStream& rStrm )
     748             : {
     749           0 :     sal_Int32 nCount = static_cast< sal_Int32 >( rStrm.size() / 2 );
     750           0 :     for( sal_Int32 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex )
     751           0 :         maDiscreteItems.push_back( rStrm.readuInt16() );
     752           0 : }
     753             : 
     754           0 : const PivotCacheItem* PivotCacheField::getCacheItem( sal_Int32 nItemIdx ) const
     755             : {
     756           0 :     if( hasGroupItems() )
     757           0 :         return maGroupItems.getCacheItem( nItemIdx );
     758           0 :     if( hasSharedItems() )
     759           0 :         return maSharedItems.getCacheItem( nItemIdx );
     760           0 :     return 0;
     761             : }
     762             : 
     763           0 : void PivotCacheField::applyItemCaptions( const IdCaptionPairList& vCaptions )
     764             : {
     765           0 :     if( hasGroupItems() )
     766           0 :         maGroupItems.applyItemCaptions( vCaptions );
     767           0 :     if( hasSharedItems() )
     768           0 :         maSharedItems.applyItemCaptions( vCaptions );
     769           0 : }
     770             : 
     771           0 : void PivotCacheField::getCacheItemNames( ::std::vector< OUString >& orItemNames ) const
     772             : {
     773           0 :     if( hasGroupItems() )
     774           0 :         maGroupItems.getCacheItemNames( orItemNames );
     775           0 :     else if( hasSharedItems() )
     776           0 :         maSharedItems.getCacheItemNames( orItemNames );
     777           0 : }
     778             : 
     779           0 : PivotCacheItemList PivotCacheField::getCacheItems() const
     780             : {
     781           0 :     if( hasGroupItems() )
     782           0 :         return maGroupItems;
     783           0 :     return maSharedItems;
     784             : }
     785             : 
     786           0 : void PivotCacheField::convertNumericGrouping( const Reference< XDataPilotField >& rxDPField ) const
     787             : {
     788             :     OSL_ENSURE( hasGroupItems() && hasNumericGrouping(), "PivotCacheField::convertNumericGrouping - not a numeric group field" );
     789           0 :     PropertySet aPropSet( rxDPField );
     790           0 :     if( hasGroupItems() && hasNumericGrouping() && aPropSet.is() )
     791             :     {
     792           0 :         DataPilotFieldGroupInfo aGroupInfo;
     793           0 :         aGroupInfo.HasAutoStart  = maFieldGroupModel.mbAutoStart;
     794           0 :         aGroupInfo.HasAutoEnd    = maFieldGroupModel.mbAutoEnd;
     795           0 :         aGroupInfo.HasDateValues = sal_False;
     796           0 :         aGroupInfo.Start         = maFieldGroupModel.mfStartValue;
     797           0 :         aGroupInfo.End           = maFieldGroupModel.mfEndValue;
     798           0 :         aGroupInfo.Step          = maFieldGroupModel.mfInterval;
     799           0 :         aGroupInfo.GroupBy       = 0;
     800           0 :         aPropSet.setProperty( PROP_GroupInfo, aGroupInfo );
     801           0 :     }
     802           0 : }
     803             : 
     804           0 : OUString PivotCacheField::createDateGroupField( const Reference< XDataPilotField >& rxBaseDPField ) const
     805             : {
     806             :     OSL_ENSURE( hasGroupItems() && hasDateGrouping(), "PivotCacheField::createDateGroupField - not a numeric group field" );
     807           0 :     Reference< XDataPilotField > xDPGroupField;
     808           0 :     PropertySet aPropSet( rxBaseDPField );
     809           0 :     if( hasGroupItems() && hasDateGrouping() && aPropSet.is() )
     810             :     {
     811           0 :         bool bDayRanges = (maFieldGroupModel.mnGroupBy == XML_days) && (maFieldGroupModel.mfInterval >= 2.0);
     812             : 
     813           0 :         DataPilotFieldGroupInfo aGroupInfo;
     814           0 :         aGroupInfo.HasAutoStart  = maFieldGroupModel.mbAutoStart;
     815           0 :         aGroupInfo.HasAutoEnd    = maFieldGroupModel.mbAutoEnd;
     816           0 :         aGroupInfo.HasDateValues = sal_True;
     817           0 :         aGroupInfo.Start         = getUnitConverter().calcSerialFromDateTime( maFieldGroupModel.maStartDate );
     818           0 :         aGroupInfo.End           = getUnitConverter().calcSerialFromDateTime( maFieldGroupModel.maEndDate );
     819           0 :         aGroupInfo.Step          = bDayRanges ? maFieldGroupModel.mfInterval : 0.0;
     820             : 
     821             :         using namespace ::com::sun::star::sheet::DataPilotFieldGroupBy;
     822           0 :         switch( maFieldGroupModel.mnGroupBy )
     823             :         {
     824           0 :             case XML_years:     aGroupInfo.GroupBy = YEARS;     break;
     825           0 :             case XML_quarters:  aGroupInfo.GroupBy = QUARTERS;  break;
     826           0 :             case XML_months:    aGroupInfo.GroupBy = MONTHS;    break;
     827           0 :             case XML_days:      aGroupInfo.GroupBy = DAYS;      break;
     828           0 :             case XML_hours:     aGroupInfo.GroupBy = HOURS;     break;
     829           0 :             case XML_minutes:   aGroupInfo.GroupBy = MINUTES;   break;
     830           0 :             case XML_seconds:   aGroupInfo.GroupBy = SECONDS;   break;
     831             :             default:    OSL_FAIL( "PivotCacheField::convertRangeGrouping - unknown date/time interval" );
     832             :         }
     833             : 
     834             :         try
     835             :         {
     836           0 :             Reference< XDataPilotFieldGrouping > xDPGrouping( rxBaseDPField, UNO_QUERY_THROW );
     837           0 :             xDPGroupField = xDPGrouping->createDateGroup( aGroupInfo );
     838             :         }
     839           0 :         catch( Exception& )
     840             :         {
     841           0 :         }
     842             :     }
     843             : 
     844           0 :     Reference< XNamed > xFieldName( xDPGroupField, UNO_QUERY );
     845           0 :     return xFieldName.is() ? xFieldName->getName() : OUString();
     846             : }
     847             : 
     848           0 : OUString PivotCacheField::createParentGroupField( const Reference< XDataPilotField >& rxBaseDPField, const PivotCacheField& rBaseCacheField, PivotCacheGroupItemVector& orItemNames ) const
     849             : {
     850             :     OSL_ENSURE( hasGroupItems() && !maDiscreteItems.empty(), "PivotCacheField::createParentGroupField - not a group field" );
     851             :     OSL_ENSURE( maDiscreteItems.size() == orItemNames.size(), "PivotCacheField::createParentGroupField - number of item names does not match grouping info" );
     852           0 :     Reference< XDataPilotFieldGrouping > xDPGrouping( rxBaseDPField, UNO_QUERY );
     853           0 :     if( !xDPGrouping.is() ) return OUString();
     854             : 
     855             :     // map the group item indexes from maGroupItems to all item indexes from maDiscreteItems
     856             :     typedef ::std::vector< sal_Int32 > GroupItemList;
     857             :     typedef ::std::vector< GroupItemList > GroupItemMap;
     858           0 :     GroupItemMap aItemMap( maGroupItems.size() );
     859           0 :     for( IndexVector::const_iterator aBeg = maDiscreteItems.begin(), aIt = aBeg, aEnd = maDiscreteItems.end(); aIt != aEnd; ++aIt )
     860             :     {
     861           0 :         if( GroupItemList* pItems = ContainerHelper::getVectorElementAccess( aItemMap, *aIt ) )
     862             :         {
     863           0 :             if ( const PivotCacheItem* pItem = rBaseCacheField.getCacheItems().getCacheItem( aIt - aBeg ) )
     864             :             {
     865             :                 // Skip unspecified or ununsed entries or errors
     866           0 :                 if ( pItem->isUnused() || ( pItem->getType() == XML_m ) ||  ( pItem->getType() == XML_e ) )
     867           0 :                     continue;
     868             :             }
     869           0 :             pItems->push_back( static_cast< sal_Int32 >( aIt - aBeg ) );
     870             :         }
     871             :     }
     872             : 
     873             :     // process all groups
     874           0 :     Reference< XDataPilotField > xDPGroupField;
     875           0 :     for( GroupItemMap::iterator aBeg = aItemMap.begin(), aIt = aBeg, aEnd = aItemMap.end(); aIt != aEnd; ++aIt )
     876             :     {
     877             :         OSL_ENSURE( !aIt->empty(), "PivotCacheField::createParentGroupField - item/group should not be empty" );
     878           0 :         if( !aIt->empty() )
     879             :         {
     880             :             /*  Insert the names of the items that are part of this group. Calc
     881             :                 expects the names of the members of the field whose members are
     882             :                 grouped (which may be the names of groups too). Excel provides
     883             :                 the names of the base field items instead (no group names
     884             :                 involved). Therefore, the passed collection of current item
     885             :                 names as they are already grouped is used here to resolve the
     886             :                 item names. */
     887           0 :             ::std::vector< OUString > aMembers;
     888           0 :             for( GroupItemList::iterator aBeg2 = aIt->begin(), aIt2 = aBeg2, aEnd2 = aIt->end(); aIt2 != aEnd2; ++aIt2 )
     889           0 :                 if( const PivotCacheGroupItem* pName = ContainerHelper::getVectorElement( orItemNames, *aIt2 ) )
     890           0 :                     if( ::std::find( aMembers.begin(), aMembers.end(), pName->maGroupName ) == aMembers.end() )
     891           0 :                         aMembers.push_back( pName->maGroupName );
     892             : 
     893             :             /*  Check again, that this is not just a group that is not grouped
     894             :                 further with other items. */
     895           0 :             if( !aMembers.empty() ) try
     896             :             {
     897             :                 // only the first call of createNameGroup() returns the new field
     898           0 :                 Reference< XDataPilotField > xDPNewField = xDPGrouping->createNameGroup( ContainerHelper::vectorToSequence( aMembers ) );
     899             :                 OSL_ENSURE( xDPGroupField.is() != xDPNewField.is(), "PivotCacheField::createParentGroupField - missing group field" );
     900           0 :                 if( !xDPGroupField.is() )
     901           0 :                     xDPGroupField = xDPNewField;
     902             : 
     903             :                 // get current grouping info
     904           0 :                 DataPilotFieldGroupInfo aGroupInfo;
     905           0 :                 PropertySet aPropSet( xDPGroupField );
     906           0 :                 aPropSet.getProperty( aGroupInfo, PROP_GroupInfo );
     907             : 
     908             :                 /*  Find the group object and the auto-generated group name.
     909             :                     The returned field contains all groups derived from the
     910             :                     previous field if that is grouped too. To find the correct
     911             :                     group, the first item used to create the group is serached.
     912             :                     Calc provides the original item names of the base field
     913             :                     when the group is querried for its members. Its does not
     914             :                     provide the names of members that are already groups in the
     915             :                     field used to create the new groups. (Is this a bug?)
     916             :                     Therefore, a name from the passed list of original item
     917             :                     names is used to find the correct group. */
     918           0 :                 OUString aFirstItem;
     919           0 :                 if( const PivotCacheGroupItem* pName = ContainerHelper::getVectorElement( orItemNames, aIt->front() ) )
     920           0 :                     aFirstItem = pName->maOrigName;
     921           0 :                 Reference< XNamed > xGroupName;
     922           0 :                 OUString aAutoName;
     923           0 :                 Reference< XIndexAccess > xGroupsIA( aGroupInfo.Groups, UNO_QUERY_THROW );
     924           0 :                 for( sal_Int32 nIdx = 0, nCount = xGroupsIA->getCount(); (nIdx < nCount) && (aAutoName.isEmpty()); ++nIdx ) try
     925             :                 {
     926           0 :                     Reference< XNameAccess > xItemsNA( xGroupsIA->getByIndex( nIdx ), UNO_QUERY_THROW );
     927           0 :                     if( xItemsNA->hasByName( aFirstItem ) )
     928             :                     {
     929           0 :                         xGroupName.set( xGroupsIA->getByIndex( nIdx ), UNO_QUERY_THROW );
     930           0 :                         aAutoName = xGroupName->getName();
     931           0 :                     }
     932             :                 }
     933           0 :                 catch( Exception& )
     934             :                 {
     935             :                 }
     936             :                 OSL_ENSURE( !aAutoName.isEmpty(), "PivotCacheField::createParentGroupField - cannot find auto-generated group name" );
     937             : 
     938             :                 // get the real group name from the list of group items
     939           0 :                 OUString aGroupName;
     940           0 :                 if( const PivotCacheItem* pGroupItem = maGroupItems.getCacheItem( static_cast< sal_Int32 >( aIt - aBeg ) ) )
     941           0 :                     aGroupName = pGroupItem->getName();
     942             :                 OSL_ENSURE( !aGroupName.isEmpty(), "PivotCacheField::createParentGroupField - cannot find group name" );
     943           0 :                 if( aGroupName.isEmpty() )
     944           0 :                     aGroupName = aAutoName;
     945             : 
     946           0 :                 if( xGroupName.is() && !aGroupName.isEmpty() )
     947             :                 {
     948             :                     // replace the auto-generated group name with the real name
     949           0 :                     if( aAutoName != aGroupName )
     950             :                     {
     951           0 :                         xGroupName->setName( aGroupName );
     952           0 :                         aPropSet.setProperty( PROP_GroupInfo, aGroupInfo );
     953             :                     }
     954             :                     // replace original item names in passed vector with group name
     955           0 :                     for( GroupItemList::iterator aIt2 = aIt->begin(), aEnd2 = aIt->end(); aIt2 != aEnd2; ++aIt2 )
     956           0 :                         if( PivotCacheGroupItem* pName = ContainerHelper::getVectorElementAccess( orItemNames, *aIt2 ) )
     957           0 :                             pName->maGroupName = aGroupName;
     958           0 :                 }
     959             :             }
     960           0 :             catch( Exception& )
     961             :             {
     962           0 :             }
     963             :         }
     964             :     }
     965             : 
     966           0 :     Reference< XNamed > xFieldName( xDPGroupField, UNO_QUERY );
     967           0 :     return xFieldName.is() ? xFieldName->getName() : OUString();
     968             : }
     969             : 
     970           0 : void PivotCacheField::writeSourceHeaderCell( WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow ) const
     971             : {
     972           0 :     CellModel aModel;
     973           0 :     aModel.maCellAddr = CellAddress( rSheetHelper.getSheetIndex(), nCol, nRow );
     974           0 :     rSheetHelper.getSheetData().setStringCell( aModel, maFieldModel.maName );
     975           0 : }
     976             : 
     977           0 : void PivotCacheField::writeSourceDataCell( WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow, const PivotCacheItem& rItem ) const
     978             : {
     979           0 :     bool bHasIndex = rItem.getType() == XML_x;
     980             :     OSL_ENSURE( bHasIndex != maSharedItems.empty(), "PivotCacheField::writeSourceDataCell - shared items missing or not expected" );
     981           0 :     if( bHasIndex )
     982           0 :         writeSharedItemToSourceDataCell( rSheetHelper, nCol, nRow, rItem.getValue().get< sal_Int32 >() );
     983             :     else
     984           0 :         writeItemToSourceDataCell( rSheetHelper, nCol, nRow, rItem );
     985           0 : }
     986             : 
     987           0 : void PivotCacheField::importPCRecordItem( SequenceInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow ) const
     988             : {
     989           0 :     if( hasSharedItems() )
     990             :     {
     991           0 :         writeSharedItemToSourceDataCell( rSheetHelper, nCol, nRow, rStrm.readInt32() );
     992             :     }
     993             :     else
     994             :     {
     995           0 :         PivotCacheItem aItem;
     996           0 :         if( maSharedItemsModel.mbIsNumeric )
     997           0 :            aItem.readDouble( rStrm );
     998           0 :         else if( maSharedItemsModel.mbHasDate && !maSharedItemsModel.mbHasString )
     999           0 :            aItem.readDate( rStrm );
    1000             :         else
    1001           0 :            aItem.readString( rStrm );
    1002           0 :         writeItemToSourceDataCell( rSheetHelper, nCol, nRow, aItem );
    1003             :     }
    1004           0 : }
    1005             : 
    1006           0 : void PivotCacheField::importPCItemIndex( BiffInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow ) const
    1007             : {
    1008             :     OSL_ENSURE( hasSharedItems(), "PivotCacheField::importPCItemIndex - invalid call, no shared items found" );
    1009           0 :     sal_Int32 nIndex = maSharedItemsModel.mbHasLongIndexes ? rStrm.readuInt16() : rStrm.readuInt8();
    1010           0 :     writeSharedItemToSourceDataCell( rSheetHelper, nCol, nRow, nIndex );
    1011           0 : }
    1012             : 
    1013             : // private --------------------------------------------------------------------
    1014             : 
    1015           0 : void PivotCacheField::writeItemToSourceDataCell( WorksheetHelper& rSheetHelper,
    1016             :         sal_Int32 nCol, sal_Int32 nRow, const PivotCacheItem& rItem ) const
    1017             : {
    1018           0 :     if( rItem.getType() != XML_m )
    1019             :     {
    1020           0 :         CellModel aModel;
    1021           0 :         aModel.maCellAddr = CellAddress( rSheetHelper.getSheetIndex(), nCol, nRow );
    1022           0 :         SheetDataBuffer& rSheetData = rSheetHelper.getSheetData();
    1023           0 :         switch( rItem.getType() )
    1024             :         {
    1025           0 :             case XML_s: rSheetData.setStringCell( aModel, rItem.getValue().get< OUString >() );                             break;
    1026           0 :             case XML_n: rSheetData.setValueCell( aModel, rItem.getValue().get< double >() );                                break;
    1027           0 :             case XML_i: rSheetData.setValueCell( aModel, rItem.getValue().get< sal_Int16 >() );                             break;
    1028           0 :             case XML_d: rSheetData.setDateTimeCell( aModel, rItem.getValue().get< DateTime >() );                           break;
    1029           0 :             case XML_b: rSheetData.setBooleanCell( aModel, rItem.getValue().get< bool >() );                                break;
    1030           0 :             case XML_e: rSheetData.setErrorCell( aModel, static_cast< sal_uInt8 >( rItem.getValue().get< sal_Int32 >() ) ); break;
    1031             :             default:    OSL_FAIL( "PivotCacheField::writeItemToSourceDataCell - unexpected item data type" );
    1032             :         }
    1033             :     }
    1034           0 : }
    1035             : 
    1036           0 : void PivotCacheField::writeSharedItemToSourceDataCell(
    1037             :         WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nItemIdx ) const
    1038             : {
    1039           0 :     if( const PivotCacheItem* pCacheItem = maSharedItems.getCacheItem( nItemIdx ) )
    1040           0 :         writeItemToSourceDataCell( rSheetHelper, nCol, nRow, *pCacheItem );
    1041           0 : }
    1042             : 
    1043             : // ============================================================================
    1044             : 
    1045           0 : PCDefinitionModel::PCDefinitionModel() :
    1046             :     mfRefreshedDate( 0.0 ),
    1047             :     mnRecords( 0 ),
    1048             :     mnMissItemsLimit( 0 ),
    1049             :     mnDatabaseFields( 0 ),
    1050             :     mbInvalid( false ),
    1051             :     mbSaveData( true ),
    1052             :     mbRefreshOnLoad( false ),
    1053             :     mbOptimizeMemory( false ),
    1054             :     mbEnableRefresh( true ),
    1055             :     mbBackgroundQuery( false ),
    1056             :     mbUpgradeOnRefresh( false ),
    1057             :     mbTupleCache( false ),
    1058             :     mbSupportSubquery( false ),
    1059           0 :     mbSupportDrill( false )
    1060             : {
    1061           0 : }
    1062             : 
    1063             : // ----------------------------------------------------------------------------
    1064             : 
    1065           0 : PCSourceModel::PCSourceModel() :
    1066             :     mnSourceType( XML_TOKEN_INVALID ),
    1067           0 :     mnConnectionId( 0 )
    1068             : {
    1069           0 : }
    1070             : 
    1071             : // ----------------------------------------------------------------------------
    1072             : 
    1073           0 : PCWorksheetSourceModel::PCWorksheetSourceModel()
    1074             : {
    1075           0 :     maRange.StartColumn = maRange.StartRow = maRange.EndColumn = maRange.EndRow = -1;
    1076           0 : }
    1077             : 
    1078             : // ----------------------------------------------------------------------------
    1079             : 
    1080           0 : PivotCache::PivotCache( const WorkbookHelper& rHelper ) :
    1081             :     WorkbookHelper( rHelper ),
    1082             :     mnCurrRow( -1 ),
    1083             :     mbValidSource( false ),
    1084           0 :     mbDummySheet( false )
    1085             : {
    1086           0 : }
    1087             : 
    1088           0 : void PivotCache::importPivotCacheDefinition( const AttributeList& rAttribs )
    1089             : {
    1090           0 :     maDefModel.maRelId            = rAttribs.getString( R_TOKEN( id ), OUString() );
    1091           0 :     maDefModel.maRefreshedBy      = rAttribs.getXString( XML_refreshedBy, OUString() );
    1092           0 :     maDefModel.mfRefreshedDate    = rAttribs.getDouble( XML_refreshedDate, 0.0 );
    1093           0 :     maDefModel.mnRecords          = rAttribs.getInteger( XML_recordCount, 0 );
    1094           0 :     maDefModel.mnMissItemsLimit   = rAttribs.getInteger( XML_missingItemsLimit, 0 );
    1095           0 :     maDefModel.mbInvalid          = rAttribs.getBool( XML_invalid, false );
    1096           0 :     maDefModel.mbSaveData         = rAttribs.getBool( XML_saveData, true );
    1097           0 :     maDefModel.mbRefreshOnLoad    = rAttribs.getBool( XML_refreshOnLoad, false );
    1098           0 :     maDefModel.mbOptimizeMemory   = rAttribs.getBool( XML_optimizeMemory, false );
    1099           0 :     maDefModel.mbEnableRefresh    = rAttribs.getBool( XML_enableRefresh, true );
    1100           0 :     maDefModel.mbBackgroundQuery  = rAttribs.getBool( XML_backgroundQuery, false );
    1101           0 :     maDefModel.mbUpgradeOnRefresh = rAttribs.getBool( XML_upgradeOnRefresh, false );
    1102           0 :     maDefModel.mbTupleCache       = rAttribs.getBool( XML_tupleCache, false );
    1103           0 :     maDefModel.mbSupportSubquery  = rAttribs.getBool( XML_supportSubquery, false );
    1104           0 :     maDefModel.mbSupportDrill     = rAttribs.getBool( XML_supportAdvancedDrill, false );
    1105           0 : }
    1106             : 
    1107           0 : void PivotCache::importCacheSource( const AttributeList& rAttribs )
    1108             : {
    1109           0 :     maSourceModel.mnSourceType   = rAttribs.getToken( XML_type, XML_TOKEN_INVALID );
    1110           0 :     maSourceModel.mnConnectionId = rAttribs.getInteger( XML_connectionId, 0 );
    1111           0 : }
    1112             : 
    1113           0 : void PivotCache::importWorksheetSource( const AttributeList& rAttribs, const Relations& rRelations )
    1114             : {
    1115           0 :     maSheetSrcModel.maRelId   = rAttribs.getString( R_TOKEN( id ), OUString() );
    1116           0 :     maSheetSrcModel.maSheet   = rAttribs.getXString( XML_sheet, OUString() );
    1117           0 :     maSheetSrcModel.maDefName = rAttribs.getXString( XML_name, OUString() );
    1118             : 
    1119             :     // resolve URL of external document
    1120           0 :     maTargetUrl = rRelations.getExternalTargetFromRelId( maSheetSrcModel.maRelId );
    1121             :     // store range address unchecked with sheet index 0, will be resolved/checked later
    1122           0 :     getAddressConverter().convertToCellRangeUnchecked( maSheetSrcModel.maRange, rAttribs.getString( XML_ref, OUString() ), 0 );
    1123           0 : }
    1124             : 
    1125           0 : void PivotCache::importPCDefinition( SequenceInputStream& rStrm )
    1126             : {
    1127             :     sal_uInt8 nFlags1, nFlags2;
    1128           0 :     rStrm.skip( 3 );    // create/refresh version id's
    1129           0 :     rStrm >> nFlags1 >> maDefModel.mnMissItemsLimit >> maDefModel.mfRefreshedDate >> nFlags2 >> maDefModel.mnRecords;
    1130           0 :     if( getFlag( nFlags2, BIFF12_PCDEFINITION_HASUSERNAME ) )
    1131           0 :         rStrm >> maDefModel.maRefreshedBy;
    1132           0 :     if( getFlag( nFlags2, BIFF12_PCDEFINITION_HASRELID ) )
    1133           0 :         rStrm >> maDefModel.maRelId;
    1134             : 
    1135           0 :     maDefModel.mbInvalid          = getFlag( nFlags1, BIFF12_PCDEFINITION_INVALID );
    1136           0 :     maDefModel.mbSaveData         = getFlag( nFlags1, BIFF12_PCDEFINITION_SAVEDATA );
    1137           0 :     maDefModel.mbRefreshOnLoad    = getFlag( nFlags1, BIFF12_PCDEFINITION_REFRESHONLOAD );
    1138           0 :     maDefModel.mbOptimizeMemory   = getFlag( nFlags1, BIFF12_PCDEFINITION_OPTIMIZEMEMORY );
    1139           0 :     maDefModel.mbEnableRefresh    = getFlag( nFlags1, BIFF12_PCDEFINITION_ENABLEREFRESH );
    1140           0 :     maDefModel.mbBackgroundQuery  = getFlag( nFlags1, BIFF12_PCDEFINITION_BACKGROUNDQUERY );
    1141           0 :     maDefModel.mbUpgradeOnRefresh = getFlag( nFlags1, BIFF12_PCDEFINITION_UPGRADEONREFR );
    1142           0 :     maDefModel.mbTupleCache       = getFlag( nFlags1, BIFF12_PCDEFINITION_TUPELCACHE );
    1143           0 :     maDefModel.mbSupportSubquery  = getFlag( nFlags2, BIFF12_PCDEFINITION_SUPPORTSUBQUERY );
    1144           0 :     maDefModel.mbSupportDrill     = getFlag( nFlags2, BIFF12_PCDEFINITION_SUPPORTDRILL );
    1145           0 : }
    1146             : 
    1147           0 : void PivotCache::importPCDSource( SequenceInputStream& rStrm )
    1148             : {
    1149             :     sal_Int32 nSourceType;
    1150           0 :     rStrm >> nSourceType >> maSourceModel.mnConnectionId;
    1151             :     static const sal_Int32 spnSourceTypes[] = { XML_worksheet, XML_external, XML_consolidation, XML_scenario };
    1152           0 :     maSourceModel.mnSourceType = STATIC_ARRAY_SELECT( spnSourceTypes, nSourceType, XML_TOKEN_INVALID );
    1153           0 : }
    1154             : 
    1155           0 : void PivotCache::importPCDSheetSource( SequenceInputStream& rStrm, const Relations& rRelations )
    1156             : {
    1157             :     sal_uInt8 nIsDefName, nIsBuiltinName, nFlags;
    1158           0 :     rStrm >> nIsDefName >> nIsBuiltinName >> nFlags;
    1159           0 :     if( getFlag( nFlags, BIFF12_PCDWBSOURCE_HASSHEET ) )
    1160           0 :         rStrm >> maSheetSrcModel.maSheet;
    1161           0 :     if( getFlag( nFlags, BIFF12_PCDWBSOURCE_HASRELID ) )
    1162           0 :         rStrm >> maSheetSrcModel.maRelId;
    1163             : 
    1164             :     // read cell range or defined name
    1165           0 :     if( nIsDefName == 0 )
    1166             :     {
    1167           0 :         BinRange aBinRange;
    1168           0 :         rStrm >> aBinRange;
    1169             :         // store range address unchecked with sheet index 0, will be resolved/checked later
    1170           0 :         getAddressConverter().convertToCellRangeUnchecked( maSheetSrcModel.maRange, aBinRange, 0 );
    1171             :     }
    1172             :     else
    1173             :     {
    1174           0 :         rStrm >> maSheetSrcModel.maDefName;
    1175           0 :         if( nIsBuiltinName != 0 )
    1176           0 :             maSheetSrcModel.maDefName = "_xlnm." + maSheetSrcModel.maDefName;
    1177             :     }
    1178             : 
    1179             :     // resolve URL of external document
    1180           0 :     maTargetUrl = rRelations.getExternalTargetFromRelId( maSheetSrcModel.maRelId );
    1181           0 : }
    1182             : 
    1183           0 : void PivotCache::importPCDefinition( BiffInputStream& rStrm )
    1184             : {
    1185             :     sal_uInt16 nFlags, nUserNameLen;
    1186           0 :     rStrm >> maDefModel.mnRecords;
    1187           0 :     rStrm.skip( 2 );    // repeated cache ID
    1188           0 :     rStrm >> nFlags;
    1189           0 :     rStrm.skip( 2 );    // unused
    1190           0 :     rStrm >> maDefModel.mnDatabaseFields;
    1191           0 :     rStrm.skip( 6 );    // total field count, report record count, (repeated) cache type
    1192           0 :     rStrm >> nUserNameLen;
    1193           0 :     if( nUserNameLen != BIFF_PC_NOSTRING )
    1194           0 :         maDefModel.maRefreshedBy = (getBiff() == BIFF8) ?
    1195             :             rStrm.readUniString( nUserNameLen ) :
    1196           0 :             rStrm.readCharArrayUC( nUserNameLen, getTextEncoding() );
    1197             : 
    1198           0 :     maDefModel.mbInvalid          = getFlag( nFlags, BIFF_PCDEFINITION_INVALID );
    1199           0 :     maDefModel.mbSaveData         = getFlag( nFlags, BIFF_PCDEFINITION_SAVEDATA );
    1200           0 :     maDefModel.mbRefreshOnLoad    = getFlag( nFlags, BIFF_PCDEFINITION_REFRESHONLOAD );
    1201           0 :     maDefModel.mbOptimizeMemory   = getFlag( nFlags, BIFF_PCDEFINITION_OPTIMIZEMEMORY );
    1202           0 :     maDefModel.mbEnableRefresh    = getFlag( nFlags, BIFF_PCDEFINITION_ENABLEREFRESH );
    1203           0 :     maDefModel.mbBackgroundQuery  = getFlag( nFlags, BIFF_PCDEFINITION_BACKGROUNDQUERY );
    1204             : 
    1205           0 :     if( (rStrm.getNextRecId() == BIFF_ID_PCDEFINITION2) && rStrm.startNextRecord() )
    1206           0 :         rStrm >> maDefModel.mfRefreshedDate;
    1207           0 : }
    1208             : 
    1209           0 : PivotCacheField& PivotCache::createCacheField( bool bInitDatabaseField )
    1210             : {
    1211           0 :     bool bIsDatabaseField = !bInitDatabaseField || (maFields.size() < maDefModel.mnDatabaseFields);
    1212           0 :     PivotCacheFieldVector::value_type xCacheField( new PivotCacheField( *this, bIsDatabaseField ) );
    1213           0 :     maFields.push_back( xCacheField );
    1214           0 :     return *xCacheField;
    1215             : }
    1216             : 
    1217           0 : void PivotCache::finalizeImport()
    1218             : {
    1219             :     // collect all fields that are based on source data (needed to finalize source data below)
    1220             :     OSL_ENSURE( !maFields.empty(), "PivotCache::finalizeImport - no pivot cache fields found" );
    1221           0 :     for( PivotCacheFieldVector::const_iterator aIt = maFields.begin(), aEnd = maFields.end(); aIt != aEnd; ++aIt )
    1222             :     {
    1223           0 :         if( (*aIt)->isDatabaseField() )
    1224             :         {
    1225             :             OSL_ENSURE( (aIt == maFields.begin()) || (*(aIt - 1))->isDatabaseField(),
    1226             :                 "PivotCache::finalizeImport - database field follows a calculated field" );
    1227           0 :             maDatabaseIndexes.push_back( static_cast< sal_Int32 >( maDatabaseFields.size() ) );
    1228           0 :             maDatabaseFields.push_back( *aIt );
    1229             :         }
    1230             :         else
    1231             :         {
    1232           0 :             maDatabaseIndexes.push_back( -1 );
    1233             :         }
    1234             :     }
    1235             :     OSL_ENSURE( !maDatabaseFields.empty(), "PivotCache::finalizeImport - no pivot cache source fields found" );
    1236             : 
    1237             :     // finalize source data depending on source type
    1238           0 :     switch( maSourceModel.mnSourceType )
    1239             :     {
    1240             :         case XML_worksheet:
    1241             :         {
    1242             :             // decide whether an external document is used
    1243           0 :             bool bInternal = maTargetUrl.isEmpty() && maSheetSrcModel.maRelId.isEmpty();
    1244           0 :             bool bExternal = !maTargetUrl.isEmpty();   // relation ID may be empty, e.g. BIFF import
    1245             :             OSL_ENSURE( bInternal || bExternal, "PivotCache::finalizeImport - invalid external document URL" );
    1246           0 :             if( bInternal )
    1247           0 :                 finalizeInternalSheetSource();
    1248           0 :             else if( bExternal )
    1249           0 :                 finalizeExternalSheetSource();
    1250             :         }
    1251           0 :         break;
    1252             : 
    1253             :         // currently, we only support worksheet data sources
    1254             :         case XML_external:
    1255           0 :         break;
    1256             :         case XML_consolidation:
    1257           0 :         break;
    1258             :         case XML_scenario:
    1259           0 :         break;
    1260             :     }
    1261           0 : }
    1262             : 
    1263           0 : sal_Int32 PivotCache::getCacheFieldCount() const
    1264             : {
    1265           0 :     return static_cast< sal_Int32 >( maFields.size() );
    1266             : }
    1267             : 
    1268           0 : const PivotCacheField* PivotCache::getCacheField( sal_Int32 nFieldIdx ) const
    1269             : {
    1270           0 :     return maFields.get( nFieldIdx ).get();
    1271             : }
    1272             : 
    1273           0 : sal_Int32 PivotCache::getCacheDatabaseIndex( sal_Int32 nFieldIdx ) const
    1274             : {
    1275           0 :     return ContainerHelper::getVectorElement( maDatabaseIndexes, nFieldIdx, -1 );
    1276             : }
    1277             : 
    1278           0 : void PivotCache::writeSourceHeaderCells( WorksheetHelper& rSheetHelper ) const
    1279             : {
    1280             :     OSL_ENSURE( static_cast< size_t >( maSheetSrcModel.maRange.EndColumn - maSheetSrcModel.maRange.StartColumn + 1 ) == maDatabaseFields.size(),
    1281             :         "PivotCache::writeSourceHeaderCells - source cell range width does not match number of source fields" );
    1282           0 :     sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn;
    1283           0 :     sal_Int32 nMaxCol = getAddressConverter().getMaxApiAddress().Column;
    1284           0 :     sal_Int32 nRow = maSheetSrcModel.maRange.StartRow;
    1285           0 :     mnCurrRow = -1;
    1286           0 :     updateSourceDataRow( rSheetHelper, nRow );
    1287           0 :     for( PivotCacheFieldVector::const_iterator aIt = maDatabaseFields.begin(), aEnd = maDatabaseFields.end(); (aIt != aEnd) && (nCol <= nMaxCol); ++aIt, ++nCol )
    1288           0 :         (*aIt)->writeSourceHeaderCell( rSheetHelper, nCol, nRow );
    1289           0 : }
    1290             : 
    1291           0 : void PivotCache::writeSourceDataCell( WorksheetHelper& rSheetHelper, sal_Int32 nColIdx, sal_Int32 nRowIdx, const PivotCacheItem& rItem ) const
    1292             : {
    1293           0 :     sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn + nColIdx;
    1294             :     OSL_ENSURE( (maSheetSrcModel.maRange.StartColumn <= nCol) && (nCol <= maSheetSrcModel.maRange.EndColumn), "PivotCache::writeSourceDataCell - invalid column index" );
    1295           0 :     sal_Int32 nRow = maSheetSrcModel.maRange.StartRow + nRowIdx;
    1296             :     OSL_ENSURE( (maSheetSrcModel.maRange.StartRow < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow), "PivotCache::writeSourceDataCell - invalid row index" );
    1297           0 :     updateSourceDataRow( rSheetHelper, nRow );
    1298           0 :     if( const PivotCacheField* pCacheField = maDatabaseFields.get( nColIdx ).get() )
    1299           0 :         pCacheField->writeSourceDataCell( rSheetHelper, nCol, nRow, rItem );
    1300           0 : }
    1301             : 
    1302           0 : void PivotCache::importPCRecord( SequenceInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nRowIdx ) const
    1303             : {
    1304           0 :     sal_Int32 nRow = maSheetSrcModel.maRange.StartRow + nRowIdx;
    1305             :     OSL_ENSURE( (maSheetSrcModel.maRange.StartRow < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow), "PivotCache::importPCRecord - invalid row index" );
    1306           0 :     sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn;
    1307           0 :     sal_Int32 nMaxCol = getAddressConverter().getMaxApiAddress().Column;
    1308           0 :     for( PivotCacheFieldVector::const_iterator aIt = maDatabaseFields.begin(), aEnd = maDatabaseFields.end(); !rStrm.isEof() && (aIt != aEnd) && (nCol <= nMaxCol); ++aIt, ++nCol )
    1309           0 :         (*aIt)->importPCRecordItem( rStrm, rSheetHelper, nCol, nRow );
    1310           0 : }
    1311             : 
    1312           0 : void PivotCache::importPCItemIndexList( BiffInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nRowIdx ) const
    1313             : {
    1314           0 :     sal_Int32 nRow = maSheetSrcModel.maRange.StartRow + nRowIdx;
    1315             :     OSL_ENSURE( (maSheetSrcModel.maRange.StartRow < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow), "PivotCache::importPCItemIndexList - invalid row index" );
    1316           0 :     sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn;
    1317           0 :     sal_Int32 nMaxCol = getAddressConverter().getMaxApiAddress().Column;
    1318           0 :     for( PivotCacheFieldVector::const_iterator aIt = maDatabaseFields.begin(), aEnd = maDatabaseFields.end(); !rStrm.isEof() && (aIt != aEnd) && (nCol <= nMaxCol); ++aIt, ++nCol )
    1319           0 :         if( (*aIt)->hasSharedItems() )
    1320           0 :             (*aIt)->importPCItemIndex( rStrm, rSheetHelper, nCol, nRow );
    1321           0 : }
    1322             : 
    1323             : // private --------------------------------------------------------------------
    1324             : 
    1325           0 : void PivotCache::finalizeInternalSheetSource()
    1326             : {
    1327             :     // resolve sheet name to sheet index
    1328           0 :     sal_Int16 nSheet = getWorksheets().getCalcSheetIndex( maSheetSrcModel.maSheet );
    1329             : 
    1330             :     // if cache is based on a defined name or table, try to resolve to cell range
    1331           0 :     if( !maSheetSrcModel.maDefName.isEmpty() )
    1332             :     {
    1333             :         // local or global defined name
    1334           0 :         if( const DefinedName* pDefName = getDefinedNames().getByModelName( maSheetSrcModel.maDefName, nSheet ).get() )
    1335             :         {
    1336           0 :             mbValidSource = pDefName->getAbsoluteRange( maSheetSrcModel.maRange );
    1337             :         }
    1338             :         // table
    1339           0 :         else if( const Table* pTable = getTables().getTable( maSheetSrcModel.maDefName ).get() )
    1340             :         {
    1341             :             // get original range from table, but exclude the totals row(s)
    1342           0 :             maSheetSrcModel.maRange = pTable->getOriginalRange();
    1343           0 :             mbValidSource = (pTable->getHeight() - pTable->getTotalsRows()) > 1;
    1344           0 :             if( mbValidSource )
    1345           0 :                 maSheetSrcModel.maRange.EndRow -= pTable->getTotalsRows();
    1346             :         }
    1347             :     }
    1348             :     // else try the cell range (if the sheet exists)
    1349           0 :     else if( nSheet >= 0 )
    1350             :     {
    1351             :         // insert sheet index into the range, range address will be checked below
    1352           0 :         maSheetSrcModel.maRange.Sheet = nSheet;
    1353           0 :         mbValidSource = true;
    1354             :     }
    1355             :     // else sheet has been deleted, generate the source data from cache
    1356           0 :     else if( !maSheetSrcModel.maSheet.isEmpty() )
    1357             :     {
    1358           0 :         prepareSourceDataSheet();
    1359             :         // return here to skip the source range check below
    1360           0 :         return;
    1361             :     }
    1362             : 
    1363             :     // check range location, do not allow ranges that overflow the sheet partly
    1364             :     mbValidSource = mbValidSource &&
    1365           0 :         getAddressConverter().checkCellRange( maSheetSrcModel.maRange, false, true ) &&
    1366           0 :         (maSheetSrcModel.maRange.StartRow < maSheetSrcModel.maRange.EndRow);
    1367             : }
    1368             : 
    1369           0 : void PivotCache::finalizeExternalSheetSource()
    1370             : {
    1371             :     /*  If pivot cache is based on external sheet data, try to restore sheet
    1372             :         data from cache records. No support for external defined names or tables,
    1373             :         sheet name and path to cache records fragment (OOXML only) are required. */
    1374           0 :     bool bHasRelation = (getFilterType() == FILTER_BIFF) || !maDefModel.maRelId.isEmpty();
    1375           0 :     if( bHasRelation && maSheetSrcModel.maDefName.isEmpty() && !maSheetSrcModel.maSheet.isEmpty() )
    1376           0 :         prepareSourceDataSheet();
    1377           0 : }
    1378             : 
    1379           0 : void PivotCache::prepareSourceDataSheet()
    1380             : {
    1381           0 :     CellRangeAddress& rRange = maSheetSrcModel.maRange;
    1382             :     // data will be inserted in top-left cell, sheet index is still set to 0 (will be set below)
    1383           0 :     rRange.EndColumn -= rRange.StartColumn;
    1384           0 :     rRange.StartColumn = 0;
    1385           0 :     rRange.EndRow -= rRange.StartRow;
    1386           0 :     rRange.StartRow = 0;
    1387             :     // check range location, do not allow ranges that overflow the sheet partly
    1388           0 :     if( getAddressConverter().checkCellRange( rRange, false, true ) )
    1389             :     {
    1390           0 :         maColSpans.insert( ValueRange( rRange.StartColumn, rRange.EndColumn ) );
    1391           0 :         OUString aSheetName = "DPCache_" + maSheetSrcModel.maSheet;
    1392           0 :         rRange.Sheet = getWorksheets().insertEmptySheet( aSheetName, false );
    1393           0 :         mbValidSource = mbDummySheet = rRange.Sheet >= 0;
    1394             :     }
    1395           0 : }
    1396             : 
    1397           0 : void PivotCache::updateSourceDataRow( WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const
    1398             : {
    1399           0 :     if( mnCurrRow != nRow )
    1400             :     {
    1401           0 :         rSheetHelper.getSheetData().setColSpans( nRow, maColSpans );
    1402           0 :         mnCurrRow = nRow;
    1403             :     }
    1404           0 : }
    1405             : 
    1406             : // ============================================================================
    1407             : 
    1408          11 : PivotCacheBuffer::PivotCacheBuffer( const WorkbookHelper& rHelper ) :
    1409          11 :     WorkbookHelper( rHelper )
    1410             : {
    1411          11 : }
    1412             : 
    1413           0 : void PivotCacheBuffer::registerPivotCacheFragment( sal_Int32 nCacheId, const OUString& rFragmentPath )
    1414             : {
    1415             :     OSL_ENSURE( nCacheId >= 0, "PivotCacheBuffer::registerPivotCacheFragment - invalid pivot cache identifier" );
    1416             :     OSL_ENSURE( maFragmentPaths.count( nCacheId ) == 0, "PivotCacheBuffer::registerPivotCacheFragment - fragment path exists already" );
    1417           0 :     if( (nCacheId >= 0) && !rFragmentPath.isEmpty() )
    1418           0 :         maFragmentPaths[ nCacheId ] = rFragmentPath;
    1419           0 : }
    1420             : 
    1421           0 : PivotCache* PivotCacheBuffer::importPivotCacheFragment( sal_Int32 nCacheId )
    1422             : {
    1423           0 :     switch( getFilterType() )
    1424             :     {
    1425             :         /*  OOXML/BIFF12 filter: On first call for the cache ID, the pivot
    1426             :             cache object is created and inserted into maCaches. Then, the cache
    1427             :             definition fragment is read and the cache is returned. On
    1428             :             subsequent calls, the created cache will be found in maCaches and
    1429             :             returned immediately. */
    1430             :         case FILTER_OOXML:
    1431             :         {
    1432             :             // try to find an imported pivot cache
    1433           0 :             if( PivotCache* pCache = maCaches.get( nCacheId ).get() )
    1434           0 :                 return pCache;
    1435             : 
    1436             :             // check if a fragment path exists for the passed cache identifier
    1437           0 :             FragmentPathMap::iterator aIt = maFragmentPaths.find( nCacheId );
    1438           0 :             if( aIt == maFragmentPaths.end() )
    1439           0 :                 return 0;
    1440             : 
    1441             :             /*  Import the cache fragment. This may create a dummy data sheet
    1442             :                 for external sheet sources. */
    1443           0 :             PivotCache& rCache = createPivotCache( nCacheId );
    1444           0 :             importOoxFragment( new PivotCacheDefinitionFragment( *this, aIt->second, rCache ) );
    1445           0 :             return &rCache;
    1446             :         }
    1447             : 
    1448             :         /*  BIFF filter: Pivot table provides 0-based index into list of pivot
    1449             :             cache source links (PIVOTCACHE/PCDSOURCE/... record blocks in
    1450             :             workbook stream). First, this index has to be resolved to the cache
    1451             :             identifier that is used to manage the cache stream names (the
    1452             :             maFragmentPaths member). The cache object itself exists already
    1453             :             before the first call for the cache source index, because source data
    1454             :             link is part of workbook data, not of the cache stream. To detect
    1455             :             subsequent calls with an already initialized cache, the entry in
    1456             :             maFragmentPaths will be removed after reading the cache stream. */
    1457             :         case FILTER_BIFF:
    1458             :         {
    1459             :             /*  Resolve cache index to cache identifier and try to find pivot
    1460             :                 cache. Cache must exist already for a valid cache index. */
    1461           0 :             nCacheId = ContainerHelper::getVectorElement( maCacheIds, nCacheId, -1 );
    1462           0 :             PivotCache* pCache = maCaches.get( nCacheId ).get();
    1463           0 :             if( !pCache )
    1464           0 :                 return 0;
    1465             : 
    1466             :             /*  Try to find fragment path entry (stream name). If missing, the
    1467             :                 stream has been read already, and the cache can be returned. */
    1468           0 :             FragmentPathMap::iterator aIt = maFragmentPaths.find( nCacheId );
    1469           0 :             if( aIt != maFragmentPaths.end() )
    1470             :             {
    1471             :                 /*  Import the cache stream. This may create a dummy data sheet
    1472             :                     for external sheet sources. */
    1473           0 :                 BiffPivotCacheFragment( *this, aIt->second, *pCache ).importFragment();
    1474             :                 // remove the fragment entry to mark that the cache is initialized
    1475           0 :                 maFragmentPaths.erase( aIt );
    1476             :             }
    1477           0 :             return pCache;
    1478             :         }
    1479             : 
    1480             :         case FILTER_UNKNOWN:
    1481             :             OSL_FAIL( "PivotCacheBuffer::importPivotCacheFragment - unknown filter type" );
    1482             :     }
    1483           0 :     return 0;
    1484             : }
    1485             : 
    1486           0 : PivotCache& PivotCacheBuffer::createPivotCache( sal_Int32 nCacheId )
    1487             : {
    1488           0 :     maCacheIds.push_back( nCacheId );
    1489           0 :     PivotCacheMap::mapped_type& rxCache = maCaches[ nCacheId ];
    1490           0 :     rxCache.reset( new PivotCache( *this ) );
    1491           0 :     return *rxCache;
    1492             : }
    1493             : 
    1494             : // ============================================================================
    1495             : 
    1496             : } // namespace xls
    1497           9 : } // namespace oox
    1498             : 
    1499             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10