1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: externalrefmgr.hxx,v $
10 * $Revision: 1.1.2.23 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #ifndef SC_EXTERNALREFMGR_HXX
32 #define SC_EXTERNALREFMGR_HXX
35 #include "address.hxx"
36 #include "sfx2/objsh.hxx"
37 #include "sfx2/lnkbase.hxx"
38 #include "tools/time.hxx"
39 #include "vcl/timer.hxx"
40 #include "svtools/zforlist.hxx"
41 #include "scmatrix.hxx"
45 #include <boost/shared_ptr.hpp>
48 #include <formula/ExternalReferenceHelper.hxx>
59 class SfxObjectShellRef
;
62 class ScExternalRefCache
;
64 class ScExternalRefLink
: public ::sfx2::SvBaseLink
67 ScExternalRefLink(ScDocument
* pDoc
, sal_uInt16 nFileId
, const String
& rFilter
);
68 virtual ~ScExternalRefLink();
70 virtual void Closed();
71 virtual void DataChanged(const String
& rMimeType
, const ::com::sun::star::uno::Any
& rValue
);
72 virtual void Edit(Window
* pParent
, const Link
& rEndEditHdl
);
74 void SetDoReferesh(bool b
);
77 ScExternalRefLink(); // disabled
78 ScExternalRefLink(const ScExternalRefLink
&); // disabled
80 DECL_LINK( ExternalRefEndEditHdl
, ::sfx2::SvBaseLink
* );
88 // ============================================================================
91 * Cache table for external reference data.
93 class ScExternalRefCache
96 typedef ::boost::shared_ptr
< formula::FormulaToken
> TokenRef
;
97 typedef ::boost::shared_ptr
<ScTokenArray
> TokenArrayRef
;
104 explicit TableName(const String
& rUppper
, const String
& rReal
);
113 explicit CellFormat();
117 /** individual cell within cached external ref table. */
121 sal_uInt32 mnFmtIndex
;
123 typedef ::std::hash_map
<SCCOL
, Cell
> RowDataType
;
124 typedef ::std::hash_map
<SCROW
, RowDataType
> RowsDataType
;
127 // SUNWS needs a forward declared friend, otherwise types and members
128 // of the outer class are not accessible.
130 friend class ScExternalRefCache::Table
;
138 SC_DLLPUBLIC
void setCell(SCCOL nCol
, SCROW nRow
, TokenRef pToken
, sal_uInt32 nFmtIndex
= 0);
139 TokenRef
getCell(SCCOL nCol
, SCROW nRow
, sal_uInt32
* pnFmtIndex
= NULL
) const;
140 bool hasRow( SCROW nRow
) const;
141 /// A temporary state used only during store to file.
142 bool isReferenced() const;
143 void setReferenced( bool bReferenced
);
144 /// Obtain a sorted vector of rows.
145 void getAllRows(::std::vector
<SCROW
>& rRows
) const;
146 /// Obtain a sorted vector of columns.
147 void getAllCols(SCROW nRow
, ::std::vector
<SCCOL
>& rCols
) const;
148 void getAllNumberFormats(::std::vector
<sal_uInt32
>& rNumFmts
) const;
155 typedef ::boost::shared_ptr
<Table
> TableTypeRef
;
156 typedef ::std::hash_map
<String
, size_t, ScStringHashCode
> TableNameIndexMap
;
158 ScExternalRefCache();
159 ~ScExternalRefCache();
161 const String
* getRealTableName(sal_uInt16 nFileId
, const String
& rTabName
) const;
162 const String
* getRealRangeName(sal_uInt16 nFileId
, const String
& rRangeName
) const;
165 * Get a cached cell data at specified cell location.
167 * @param nFileId file ID of an external document
168 * @param rTabName sheet name
172 * @return pointer to the token instance in the cache.
174 ScExternalRefCache::TokenRef
getCellData(
175 sal_uInt16 nFileId
, const String
& rTabName
, SCCOL nCol
, SCROW nRow
,
176 bool bEmptyCellOnNull
, bool bWriteEmpty
, sal_uInt32
* pnFmtIndex
);
179 * Get a cached cell range data.
181 * @return a new token array instance. Note that <i>the caller must
182 * manage the life cycle of the returned instance</i>, which is
183 * guaranteed if the TokenArrayRef is properly used..
185 ScExternalRefCache::TokenArrayRef
getCellRangeData(
186 sal_uInt16 nFileId
, const String
& rTabName
, const ScRange
& rRange
, bool bEmptyCellOnNull
, bool bWriteEmpty
);
188 ScExternalRefCache::TokenArrayRef
getRangeNameTokens(sal_uInt16 nFileId
, const String
& rName
);
189 void setRangeNameTokens(sal_uInt16 nFileId
, const String
& rName
, TokenArrayRef pArray
);
191 void setCellData(sal_uInt16 nFileId
, const String
& rTabName
, SCROW nRow
, SCCOL nCol
, TokenRef pToken
, sal_uInt32 nFmtIndex
);
193 struct SingleRangeData
195 /** This name must be in upper-case. */
197 ScMatrixRef mpRangeData
;
199 void setCellRangeData(sal_uInt16 nFileId
, const ScRange
& rRange
, const ::std::vector
<SingleRangeData
>& rData
,
200 TokenArrayRef pArray
);
202 bool isDocInitialized(sal_uInt16 nFileId
);
203 void initializeDoc(sal_uInt16 nFileId
, const ::std::vector
<String
>& rTabNames
);
204 String
getTableName(sal_uInt16 nFileId
, size_t nCacheId
) const;
205 void getAllTableNames(sal_uInt16 nFileId
, ::std::vector
<String
>& rTabNames
) const;
206 SCsTAB
getTabSpan( sal_uInt16 nFileId
, const String
& rStartTabName
, const String
& rEndTabName
) const;
207 void getAllNumberFormats(::std::vector
<sal_uInt32
>& rNumFmts
) const;
208 bool hasCacheTable(sal_uInt16 nFileId
, const String
& rTabName
) const;
209 size_t getCacheTableCount(sal_uInt16 nFileId
) const;
212 * Set all tables of a document as referenced, used only during
214 * @returns <TRUE/> if ALL tables of ALL documents are marked.
216 bool setCacheDocReferenced( sal_uInt16 nFileId
);
219 * Set a table as referenced, used only during store-to-file.
220 * @returns <TRUE/> if ALL tables of ALL documents are marked.
222 bool setCacheTableReferenced( sal_uInt16 nFileId
, const String
& rTabName
);
223 void setAllCacheTableReferencedStati( bool bReferenced
);
224 bool areAllCacheTablesReferenced() const;
226 struct ReferencedStatus
230 ::std::vector
<bool> maTables
;
231 bool mbAllTablesReferenced
;
232 // Initially, documents have no tables but all referenced.
233 DocReferenced() : mbAllTablesReferenced(true) {}
235 typedef ::std::vector
<DocReferenced
> DocReferencedVec
;
237 DocReferencedVec maDocs
;
238 bool mbAllReferenced
;
241 explicit ReferencedStatus( size_t nDocs
);
242 void reset( size_t nDocs
);
246 void addCacheTableToReferenced( sal_uInt16 nFileId
, size_t nIndex
);
247 void addCacheDocToReferenced( sal_uInt16 nFileId
);
250 ScExternalRefCache::TableTypeRef
getCacheTable(sal_uInt16 nFileId
, size_t nTabIndex
) const;
251 ScExternalRefCache::TableTypeRef
getCacheTable(sal_uInt16 nFileId
, const String
& rTabName
, bool bCreateNew
, size_t* pnIndex
);
253 void clearCache(sal_uInt16 nFileId
);
258 size_t operator()(const ScRange
& rRange
) const
260 const ScAddress
& s
= rRange
.aStart
;
261 const ScAddress
& e
= rRange
.aEnd
;
262 return s
.Tab() + s
.Col() + s
.Row() + e
.Tab() + e
.Col() + e
.Row();
266 typedef ::std::hash_map
<String
, TokenArrayRef
, ScStringHashCode
> RangeNameMap
;
267 typedef ::std::hash_map
<ScRange
, TokenArrayRef
, RangeHash
> RangeArrayMap
;
268 typedef ::std::hash_map
<String
, String
, ScStringHashCode
> NamePairMap
;
270 // SUNWS needs a forward declared friend, otherwise types and members
271 // of the outer class are not accessible.
273 friend struct ScExternalRefCache::DocItem
;
275 /** Represents data cached for a single external document. */
278 /** The raw cache tables. */
279 ::std::vector
<TableTypeRef
> maTables
;
280 /** Table name list in correct order, in both upper- and real-case. */
281 ::std::vector
<TableName
> maTableNames
;
282 /** Table name to index map. The names must be stored upper-case. */
283 TableNameIndexMap maTableNameIndex
;
284 /** Range name cache. */
285 RangeNameMap maRangeNames
;
286 /** Token array cache for cell ranges. */
287 RangeArrayMap maRangeArrays
;
288 /** Upper- to real-case mapping for range names. */
289 NamePairMap maRealRangeNameMap
;
291 bool mbInitFromSource
;
293 DocItem() : mbInitFromSource(false) {}
295 typedef ::std::hash_map
<sal_uInt16
, DocItem
> DocDataType
;
296 DocItem
* getDocItem(sal_uInt16 nFileId
) const;
299 mutable DocDataType maDocs
;
302 // ============================================================================
304 class SC_DLLPUBLIC ScExternalRefManager
: public formula::ExternalReferenceHelper
308 // SUNWS needs a forward declared friend, otherwise types and members
309 // of the outer class are not accessible.
311 friend class ScExternalRefManager::RefCells
;
314 * Collection of cell addresses that contain external references. This
315 * data is used for link updates.
323 void insertCell(const ScAddress
& rAddr
);
324 void removeCell(const ScAddress
& rAddr
);
325 void moveTable(SCTAB nOldTab
, SCTAB nNewTab
, bool bCopy
);
326 void insertTable(SCTAB nPos
);
327 void removeTable(SCTAB nPos
);
328 void refreshAllCells(ScExternalRefManager
& rRefMgr
);
331 typedef ::std::hash_set
<SCROW
> RowSet
;
332 typedef ::std::hash_map
<SCCOL
, RowSet
> ColSet
;
334 // SUNWS needs a forward declared friend, otherwise types and members
335 // of the outer class are not accessible.
337 friend struct ScExternalRefManager::RefCells::TabItem
;
343 explicit TabItem(SCTAB nIndex
);
344 explicit TabItem(const TabItem
& r
);
346 typedef ::boost::shared_ptr
<TabItem
> TabItemRef
;
349 * Return the position that points either to the specified table
350 * position or to the position where a new table would be inserted in
351 * case the specified table is not present.
353 * @param nTab index of the desired table
355 ::std::list
<TabItemRef
>::iterator
getTabPos(SCTAB nTab
);
357 // This list must be sorted by the table index at all times.
358 ::std::list
<TabItemRef
> maTables
;
361 enum LinkUpdateType
{ LINK_MODIFIED
, LINK_BROKEN
};
364 * Base class for objects that need to listen to link updates. When a
365 * link to a certain external file is updated, the notify() method gets
372 virtual ~LinkListener() = 0;
373 virtual void notify(sal_uInt16 nFileId
, LinkUpdateType eType
) = 0;
377 size_t operator() (const LinkListener
* p
) const
379 return reinterpret_cast<size_t>(p
);
385 /** Shell instance for a source document. */
388 SfxObjectShellRef maShell
;
392 typedef ::std::hash_map
<sal_uInt16
, SrcShell
> DocShellMap
;
393 typedef ::std::hash_map
<sal_uInt16
, bool> LinkedDocMap
;
395 typedef ::std::hash_map
<sal_uInt16
, RefCells
> RefCellMap
;
396 typedef ::std::hash_map
<sal_uInt16
, SvNumberFormatterMergeMap
> NumFmtMap
;
399 typedef ::std::hash_set
<LinkListener
*, LinkListener::Hash
> LinkListeners
;
400 typedef ::std::hash_map
<sal_uInt16
, LinkListeners
> LinkListenerMap
;
403 /** Source document meta-data container. */
406 String maFileName
; /// original file name as loaded from the file.
407 String maRealFileName
; /// file name created from the relative name.
408 String maRelativeName
;
410 String maFilterOptions
;
412 void maybeCreateRealFileName(const String
& rOwnDocName
);
416 explicit ScExternalRefManager(ScDocument
* pDoc
);
417 virtual ~ScExternalRefManager();
419 virtual String
getCacheTableName(sal_uInt16 nFileId
, size_t nTabIndex
) const;
422 * Get a cache table instance for specified table and table index. Unlike
423 * the other method that takes a table name, this method does not create a
424 * new table when a table is not available for specified index.
426 * @param nFileId file ID
427 * @param nTabIndex cache table index
429 * @return shared_ptr to the cache table instance
431 ScExternalRefCache::TableTypeRef
getCacheTable(sal_uInt16 nFileId
, size_t nTabIndex
) const;
434 * Get a cache table instance for specified file and table name. If the
435 * table instance is not already present, it'll instantiate a new one and
436 * append it to the end of the table array. <I>It's important to be
437 * aware of this fact especially for multi-table ranges for which
438 * table orders are critical.</I>
440 * Excel filter calls this method to populate the cache table from the
443 * @param nFileId file ID
444 * @param rTabName table name
445 * @param bCreateNew if true, create a new table instance if it's not
446 * already present. If false, it returns NULL if the
447 * specified table's cache doesn't exist.
448 * @param pnIndex if non-NULL pointer is passed, it stores the internal
449 * index of a cache table instance.
451 * @return shared_ptr to the cache table instance
453 ScExternalRefCache::TableTypeRef
getCacheTable(sal_uInt16 nFileId
, const String
& rTabName
, bool bCreateNew
, size_t* pnIndex
= 0);
454 void getAllCachedTableNames(sal_uInt16 nFileId
, ::std::vector
<String
>& rTabNames
) const;
457 * Get the span (distance+sign(distance)) of two sheets of a specified
460 * @param nFileId file ID
461 * @param rStartTabName name of first sheet (sheet1)
462 * @param rEndTabName name of second sheet (sheet2)
465 * 1 if sheet2 == sheet1
466 * > 1 if sheet2 > sheet1
467 * < -1 if sheet2 < sheet1
468 * -1 if nFileId or rStartTabName not found
469 * 0 if rEndTabName not found
471 SCsTAB
getCachedTabSpan( sal_uInt16 nFileId
, const String
& rStartTabName
, const String
& rEndTabName
) const;
474 * Get all unique number format indices that are used in the cache tables.
475 * The retrieved indices are sorted in ascending order.
477 * @param rNumFmts (reference) all unique number format indices.
479 void getAllCachedNumberFormats(::std::vector
<sal_uInt32
>& rNumFmts
) const;
481 bool hasCacheTable(sal_uInt16 nFileId
, const String
& rTabName
) const;
482 size_t getCacheTableCount(sal_uInt16 nFileId
) const;
483 sal_uInt16
getExternalFileCount() const;
486 * Mark all tables as referenced that are used by any LinkListener, used
487 * only during store-to-file.
488 * @returns <TRUE/> if ALL tables of ALL external documents are marked.
490 bool markUsedByLinkListeners();
493 * Set all tables of a document as referenced, used only during
495 * @returns <TRUE/> if ALL tables of ALL external documents are marked.
497 bool setCacheDocReferenced( sal_uInt16 nFileId
);
500 * Set a table as referenced, used only during store-to-file.
501 * @returns <TRUE/> if ALL tables of ALL external documents are marked.
503 bool setCacheTableReferenced( sal_uInt16 nFileId
, const String
& rTabName
);
504 void setAllCacheTableReferencedStati( bool bReferenced
);
507 * @returns <TRUE/> if setAllCacheTableReferencedStati(false) was called,
508 * <FALSE/> if setAllCacheTableReferencedStati(true) was called.
510 bool isInReferenceMarking() const { return bInReferenceMarking
; }
512 void storeRangeNameTokens(sal_uInt16 nFileId
, const String
& rName
, const ScTokenArray
& rArray
);
514 ScExternalRefCache::TokenRef
getSingleRefToken(
515 sal_uInt16 nFileId
, const String
& rTabName
, const ScAddress
& rCell
,
516 const ScAddress
* pCurPos
, SCTAB
* pTab
, ScExternalRefCache::CellFormat
* pFmt
= NULL
);
519 * Get an array of tokens that consist of the specified external cell
522 * @param nFileId file ID for an external document
523 * @param rTabName referenced sheet name
524 * @param rRange referenced cell range
525 * @param pCurPos current cursor position to keep track of cells that
526 * reference an external data.
528 * @return shared_ptr to a token array instance. <i>The caller must not
529 * delete the instance returned by this method.</i>
531 ScExternalRefCache::TokenArrayRef
getDoubleRefTokens(sal_uInt16 nFileId
, const String
& rTabName
, const ScRange
& rRange
, const ScAddress
* pCurPos
);
534 * Get an array of tokens corresponding with a specified name in a
537 * @param pCurPos currnet cell address where this name token is used.
538 * This is purely to keep track of all cells containing
539 * external names for refreshing purposes. If this is
540 * NULL, then the cell will not be added to the list.
542 * @return shared_ptr to array of tokens composing the name
544 ScExternalRefCache::TokenArrayRef
getRangeNameTokens(sal_uInt16 nFileId
, const String
& rName
, const ScAddress
* pCurPos
= NULL
);
546 const String
& getOwnDocumentName() const;
547 bool isOwnDocument(const String
& rFile
) const;
550 * Takes a flat file name, and convert it to an absolute URL path. An
551 * absolute URL path begines with 'file:///.
553 * @param rFile file name to convert
555 void convertToAbsName(String
& rFile
) const;
556 sal_uInt16
getExternalFileId(const String
& rFile
);
557 const String
* getExternalFileName(sal_uInt16 nFileId
);
558 bool hasExternalFile(sal_uInt16 nFileId
) const;
559 bool hasExternalFile(const String
& rFile
) const;
560 const SrcFileData
* getExternalFileData(sal_uInt16 nFileId
) const;
562 const String
* getRealTableName(sal_uInt16 nFileId
, const String
& rTabName
) const;
563 const String
* getRealRangeName(sal_uInt16 nFileId
, const String
& rRangeName
) const;
564 void refreshNames(sal_uInt16 nFileId
);
565 void breakLink(sal_uInt16 nFileId
);
566 void switchSrcFile(sal_uInt16 nFileId
, const String
& rNewFile
, const String
& rNewFilter
);
569 * Set a relative file path for the specified file ID. Note that the
570 * caller must ensure that the passed URL is a valid relative URL.
572 * @param nFileId file ID for an external document
573 * @param rRelUrl relative URL
575 void setRelativeFileName(sal_uInt16 nFileId
, const String
& rRelUrl
);
578 * Set the filter name and options if any for a given source document.
579 * These values get reset when the source document ever gets reloaded.
585 void setFilterData(sal_uInt16 nFileId
, const String
& rFilterName
, const String
& rOptions
);
589 bool hasExternalData() const;
592 * Re-generates relative names for all stored source files. This is
593 * necessary when exporting to an ods document, to ensure that all source
594 * files have their respective relative names for xlink:href export.
596 * @param rBaseFileUrl Absolute URL of the content.xml fragment of the
597 * document being exported.
599 void resetSrcFileData(const String
& rBaseFileUrl
);
602 * Update a single referencing cell position.
604 * @param rOldPos old position
605 * @param rNewPos new position
607 void updateRefCell(const ScAddress
& rOldPos
, const ScAddress
& rNewPos
, bool bCopy
);
610 * Update referencing cells affected by sheet movement.
612 * @param nOldTab old sheet position
613 * @param nNewTab new sheet position
614 * @param bCopy whether this is a sheet move (false) or sheet copy (true)
616 void updateRefMoveTable(SCTAB nOldTab
, SCTAB nNewTab
, bool bCopy
);
619 * Update referencing cells affected by sheet insertion.
621 * @param nPos sheet insertion position. All sheets to the right
622 * including the one at the insertion poistion shift to the
625 void updateRefInsertTable(SCTAB nPos
);
627 void updateRefDeleteTable(SCTAB nPos
);
630 * Register a new link listener to a specified external document. Note
631 * that the caller is responsible for managing the life cycle of the
634 void addLinkListener(sal_uInt16 nFileId
, LinkListener
* pListener
);
637 * Remove an existing link listener. Note that removing a listener
638 * pointer here does not delete the listener object instance.
640 void removeLinkListener(sal_uInt16 nFileId
, LinkListener
* pListener
);
642 void removeLinkListener(LinkListener
* pListener
);
645 * Notify all listeners that are listening to a specified external
648 * @param nFileId file ID for an external document.
650 void notifyAllLinkListeners(sal_uInt16 nFileId
, LinkUpdateType eType
);
653 ScExternalRefManager();
654 ScExternalRefManager(const ScExternalRefManager
&);
656 void refreshAllRefCells(sal_uInt16 nFileId
);
658 void insertRefCell(sal_uInt16 nFileId
, const ScAddress
& rCell
);
660 ScDocument
* getSrcDocument(sal_uInt16 nFileId
);
661 SfxObjectShellRef
loadSrcDocument(sal_uInt16 nFileId
, String
& rFilter
);
662 bool isFileLoadable(const String
& rFile
) const;
664 void maybeLinkExternalFile(sal_uInt16 nFileId
);
667 * Try to create a "real" file name from the relative path. The original
668 * file name may not point to the real document when the referencing and
669 * referenced documents have been moved.
671 * For the real file name to be created, the relative name should not be
672 * empty before calling this method, or the real file name will not be
675 * @param nFileId file ID for an external document
677 void maybeCreateRealFileName(sal_uInt16 nFileId
);
679 bool compileTokensByCell(const ScAddress
& rCell
);
682 * Purge those source document instances that have not been accessed for
683 * the specified duration.
685 * @param nTimeOut time out value in 100th of a second
687 void purgeStaleSrcDocument(sal_Int32 nTimeOut
);
689 sal_uInt32
getMappedNumberFormat(sal_uInt16 nFileId
, sal_uInt32 nNumFmt
, ScDocument
* pSrcDoc
);
692 /** cache of referenced ranges and names from source documents. */
693 ScExternalRefCache maRefCache
;
698 * Source document cache. This stores the original source document shell
699 * instances. They get purged after a certain period of time.
701 DocShellMap maDocShells
;
703 /** list of source documents that are managed by the link manager. */
704 LinkedDocMap maLinkedDocs
;
707 * List of referencing cells that may contain external names. There is
708 * one list per source document.
710 RefCellMap maRefCells
;
712 LinkListenerMap maLinkListeners
;
714 NumFmtMap maNumFormatMap
;
716 /** original source file index. */
717 ::std::vector
<SrcFileData
> maSrcFiles
;
719 /** Status whether in reference marking state. See isInReferenceMarking(). */
720 bool bInReferenceMarking
;
722 AutoTimer maSrcDocTimer
;
723 DECL_LINK(TimeOutHdl
, AutoTimer
*);