LCOV - code coverage report
Current view: top level - sfx2/source/doc - Metadatable.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 395 465 84.9 %
Date: 2012-08-25 Functions: 78 94 83.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 442 934 47.3 %

           Branch data     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                 :            : 
      21                 :            : #include <sfx2/Metadatable.hxx>
      22                 :            : #include <sfx2/XmlIdRegistry.hxx>
      23                 :            : 
      24                 :            : #include <osl/mutex.hxx>
      25                 :            : #include <vcl/svapp.hxx> // solarmutex
      26                 :            : 
      27                 :            : #include <rtl/random.h>
      28                 :            : 
      29                 :            : #include <boost/bind.hpp>
      30                 :            : 
      31                 :            : #include <memory>
      32                 :            : #include <boost/unordered_map.hpp>
      33                 :            : #include <list>
      34                 :            : #include <algorithm>
      35                 :            : #if OSL_DEBUG_LEVEL > 0
      36                 :            : #include <typeinfo>
      37                 :            : #endif
      38                 :            : 
      39                 :            : 
      40                 :            : /** XML ID handling.
      41                 :            : 
      42                 :            :     There is an abstract base class <type>XmlIdRegistry</type>, with
      43                 :            :     2 subclasses <type>XmlIdRegistryDocument</type> for "normal" documents,
      44                 :            :     and <type>XmlIdRegistryClipboard</type> for clipboard documents.
      45                 :            :     These classes are responsible for managing XML IDs for all elements
      46                 :            :     of the model. Only the implementation of the <type>Metadatable</type>
      47                 :            :     base class needs to know the registries, so they are not in the header.
      48                 :            : 
      49                 :            :     The handling of XML IDs differs between clipboard and non-clipboard
      50                 :            :     documents in several aspects. Most importantly, non-clipboard documents
      51                 :            :     can have several elements associated with one XML ID.
      52                 :            :     This is necessary because of the weird undo implementation:
      53                 :            :     deleting a text node moves the deleted node to the undo array, but
      54                 :            :     executing undo will then create a <em>copy</em> of that node in the
      55                 :            :     document array. These 2 nodes must have the same XML ID, because
      56                 :            :     we cannot know whether the user will do a redo next, or something else.
      57                 :            : 
      58                 :            :     Because we need to have a mechanism for several objects per XML ID anyway,
      59                 :            :     we use that also to enable some usability features:
      60                 :            :     The document registry has a list of Metadatables per XML ID.
      61                 :            :     This list is sorted by priority, i.e., the first element has highest
      62                 :            :     priority. When inserting copies, care must be taken that they are inserted
      63                 :            :     at the right position: either before or after the source.
      64                 :            :     This is done by <method>Metadatable::RegisterAsCopyOf</method>.
      65                 :            :     When a text node is split, then both resulting text nodes are inserted
      66                 :            :     into the list. If the user then deletes one text node, the other one
      67                 :            :     will have the XML ID.
      68                 :            :     Also, when a Metadatable is copied to the clipboard and then pasted,
      69                 :            :     the copy is inserted into the list. If the user then deletes the source,
      70                 :            :     the XML ID is not lost.
      71                 :            :     The goal is that it should be hard to lose an XML ID by accident, which
      72                 :            :     is especially important as long as we do not have an UI that displays them.
      73                 :            : 
      74                 :            :     There are two subclasses of <type>Metadatable</type>:
      75                 :            :     <ul><li><type>MetadatableClipboard</type>: for copies in the clipboard</li>
      76                 :            :         <li><type>MetadatableUndo</type>: for undo, because a Metadatable
      77                 :            :         may be destroyed on delete and a new one created on undo.</li></ul>
      78                 :            :     These serve only to track the position in an XML ID list in a document
      79                 :            :     registry, so that future actions can insert objects at the right position.
      80                 :            :     Unfortunately, inserting dummy objects seems to be necessary:
      81                 :            :     <ul><li>it is not sufficent to just remember the saved id, because then
      82                 :            :             the relative priorities might change when executing the undo</li>
      83                 :            :         <li>it is not sufficient to record the position as an integer, because
      84                 :            :             if we delete a text node and then undo, the node will be copied(!),
      85                 :            :             and we will have one more node in the list.<li>
      86                 :            :         <li>it is not sufficient to record the pointer of the previous/next
      87                 :            :             Metadatable, because if we delete a text node, undo, and then
      88                 :            :             do something to clear the redo array, the original text node is
      89                 :            :             destroyed, and is replaced by the copy created by undo</li></ul>
      90                 :            : 
      91                 :            :     If content from a non-clipboard document is copied into a clipboard
      92                 :            :     document, a dummy <type>MetadatableClipboard</type> is inserted into the
      93                 :            :     non-clipboard document registry in order to track the position of the
      94                 :            :     source element.  When the clipboard content is pasted back into the source
      95                 :            :     document, this dummy object is used to associate the pasted element with
      96                 :            :     that same XML ID.
      97                 :            : 
      98                 :            :     If a <type>Metadatable</type> is deleted or merged,
      99                 :            :     <method>Metadatable::CreateUndo</method> is called, and returns a
     100                 :            :     <type>MetadatableUndo<type> instance, which can be used to undo the action
     101                 :            :     by passing it to <method>Metadatable::RestoreMetadata</method>.
     102                 :            : 
     103                 :            :     @author mst
     104                 :            :  */
     105                 :            : 
     106                 :            : 
     107                 :            : using namespace ::com::sun::star;
     108                 :            : 
     109                 :            : using ::sfx2::isValidXmlId;
     110                 :            : 
     111                 :            : 
     112                 :            : namespace sfx2 {
     113                 :            : 
     114                 :            : static const char s_content [] = "content.xml";
     115                 :            : static const char s_styles  [] = "styles.xml";
     116                 :            : static const char s_prefix  [] = "id";  // prefix for generated xml:id
     117                 :            : 
     118                 :       2531 : static bool isContentFile(::rtl::OUString const & i_rPath)
     119                 :            : {
     120                 :       2531 :     return i_rPath == s_content;
     121                 :            : }
     122                 :            : 
     123                 :          3 : static bool isStylesFile (::rtl::OUString const & i_rPath)
     124                 :            : {
     125                 :          3 :     return i_rPath == s_styles;
     126                 :            : }
     127                 :            : 
     128                 :            : 
     129                 :            : //=============================================================================
     130                 :            : // XML ID handling ---------------------------------------------------
     131                 :            : 
     132                 :            : /** handles registration of XMetadatable.
     133                 :            : 
     134                 :            :     This class is responsible for guaranteeing that XMetadatable objects
     135                 :            :     always have XML IDs that are unique within a stream.
     136                 :            : 
     137                 :            :     This is an abstract base class; see subclasses XmlIdRegistryDocument and
     138                 :            :     XmlIdRegistryClipboard.
     139                 :            : 
     140                 :            :     @see SwDoc::GetXmlIdRegistry
     141                 :            :     @see SwDocShell::GetXmlIdRegistry
     142                 :            :  */
     143                 :            : class XmlIdRegistry : public sfx2::IXmlIdRegistry
     144                 :            : {
     145                 :            : 
     146                 :            : public:
     147                 :            :     XmlIdRegistry();
     148                 :            : 
     149                 :            :     virtual ~XmlIdRegistry();
     150                 :            : 
     151                 :            :     /** get the ODF element with the given metadata reference. */
     152                 :            :     virtual ::com::sun::star::uno::Reference<
     153                 :            :             ::com::sun::star::rdf::XMetadatable > SAL_CALL
     154                 :            :         GetElementByMetadataReference(
     155                 :            :             const ::com::sun::star::beans::StringPair & i_rReference) const;
     156                 :            : 
     157                 :            :     /** register an ODF element at a newly generated, unique metadata reference.
     158                 :            : 
     159                 :            :         <p>
     160                 :            :         Find a fresh XML ID, and register it for the element.
     161                 :            :         The generated ID does not occur in any stream of the document.
     162                 :            :         </p>
     163                 :            :      */
     164                 :            :     virtual void RegisterMetadatableAndCreateID(Metadatable& i_xObject) = 0;
     165                 :            : 
     166                 :            :     /** try to register an ODF element at a given XML ID, or update its
     167                 :            :         registation to a different XML ID.
     168                 :            : 
     169                 :            :         <p>
     170                 :            :         If the given new metadata reference is not already occupied in the
     171                 :            :         document, unregister the element at its old metadata reference if
     172                 :            :         it has one, and register the new metadata reference for the element.
     173                 :            :         Note that this method only ensures that XML IDs are unique per stream,
     174                 :            :         so using the same XML ID in both content.xml and styles.xml is allowed.
     175                 :            :         </p>
     176                 :            : 
     177                 :            :         @returns
     178                 :            :             true iff the element has successfully been registered
     179                 :            :      */
     180                 :            :     virtual bool TryRegisterMetadatable(Metadatable& i_xObject,
     181                 :            :         ::rtl::OUString const& i_rStreamName, ::rtl::OUString const& i_rIdref)
     182                 :            :         = 0;
     183                 :            : 
     184                 :            :     /** unregister an ODF element.
     185                 :            : 
     186                 :            :         <p>
     187                 :            :         Unregister the element at its metadata reference.
     188                 :            :         Does not remove the metadata reference from the element.
     189                 :            :         </p>
     190                 :            : 
     191                 :            :         @see RemoveXmlIdForElement
     192                 :            :      */
     193                 :            :     virtual void UnregisterMetadatable(Metadatable const&) = 0;
     194                 :            : 
     195                 :            :     /** get the metadata reference for the given element. */
     196                 :            :     ::com::sun::star::beans::StringPair
     197                 :            :         GetXmlIdForElement(Metadatable const&) const;
     198                 :            : 
     199                 :            :     /** remove the metadata reference for the given element. */
     200                 :            :     virtual void RemoveXmlIdForElement(Metadatable const&) = 0;
     201                 :            : 
     202                 :            : protected:
     203                 :            : 
     204                 :            :     virtual bool LookupXmlId(const Metadatable& i_xObject,
     205                 :            :         ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const = 0;
     206                 :            : 
     207                 :            :     virtual Metadatable* LookupElement(const ::rtl::OUString & i_rStreamName,
     208                 :            :         const ::rtl::OUString & i_rIdref) const = 0;
     209                 :            : };
     210                 :            : 
     211                 :            : // XmlIdRegistryDocument ---------------------------------------------
     212                 :            : 
     213                 :            : /** non-clipboard documents */
     214                 :            : class XmlIdRegistryDocument : public XmlIdRegistry
     215                 :            : {
     216                 :            : 
     217                 :            : public:
     218                 :            :     XmlIdRegistryDocument();
     219                 :            : 
     220                 :            :     virtual ~XmlIdRegistryDocument();
     221                 :            : 
     222                 :            :     virtual void RegisterMetadatableAndCreateID(Metadatable& i_xObject);
     223                 :            : 
     224                 :            :     virtual bool TryRegisterMetadatable(Metadatable& i_xObject,
     225                 :            :         ::rtl::OUString const& i_rStreamName, ::rtl::OUString const& i_rIdref);
     226                 :            : 
     227                 :            :     virtual void UnregisterMetadatable(Metadatable const&);
     228                 :            : 
     229                 :            :     virtual void RemoveXmlIdForElement(Metadatable const&);
     230                 :            : 
     231                 :            :     /** register i_rCopy as a copy of i_rSource,
     232                 :            :         with precedence iff i_bCopyPrecedesSource is true */
     233                 :            :     void RegisterCopy(Metadatable const& i_rSource, Metadatable & i_rCopy,
     234                 :            :         const bool i_bCopyPrecedesSource);
     235                 :            : 
     236                 :            :     /** create a Undo Metadatable for i_rObject. */
     237                 :            :     ::boost::shared_ptr<MetadatableUndo> CreateUndo(
     238                 :            :         Metadatable const& i_rObject);
     239                 :            : 
     240                 :            :     /** merge i_rMerged and i_rOther into i_rMerged. */
     241                 :            :     void JoinMetadatables(Metadatable & i_rMerged, Metadatable const& i_rOther);
     242                 :            : 
     243                 :            :     // unfortunately public, Metadatable::RegisterAsCopyOf needs this
     244                 :            :     virtual bool LookupXmlId(const Metadatable& i_xObject,
     245                 :            :         ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const;
     246                 :            : 
     247                 :            : private:
     248                 :            : 
     249                 :            :     virtual Metadatable* LookupElement(const ::rtl::OUString & i_rStreamName,
     250                 :            :         const ::rtl::OUString & i_rIdref) const;
     251                 :            : 
     252                 :            :     struct XmlIdRegistry_Impl;
     253                 :            :     ::std::auto_ptr<XmlIdRegistry_Impl> m_pImpl;
     254                 :            : };
     255                 :            : 
     256                 :            : // MetadatableUndo ---------------------------------------------------
     257                 :            : 
     258                 :            : /** the horrible Undo Metadatable: is inserted into lists to track position */
     259         [ #  # ]:          0 : class MetadatableUndo : public Metadatable
     260                 :            : {
     261                 :            :     /// as determined by the stream of the source in original document
     262                 :            :     const bool m_isInContent;
     263                 :            : public:
     264                 :          0 :     MetadatableUndo(const bool i_isInContent)
     265                 :          0 :         : m_isInContent(i_isInContent) { }
     266                 :          0 :     virtual ::sfx2::XmlIdRegistry& GetRegistry()
     267                 :            :     {
     268                 :            :         // N.B. for Undo, m_pReg is initialized by registering this as copy in
     269                 :            :         // CreateUndo; it is never cleared
     270                 :            :         OSL_ENSURE(m_pReg, "no m_pReg in MetadatableUndo ?");
     271                 :          0 :         return *m_pReg;
     272                 :            :     }
     273                 :          0 :     virtual bool IsInClipboard() const { return false; }
     274                 :          0 :     virtual bool IsInUndo() const { return true; }
     275                 :          0 :     virtual bool IsInContent() const { return m_isInContent; }
     276                 :            :     virtual ::com::sun::star::uno::Reference<
     277                 :          0 :         ::com::sun::star::rdf::XMetadatable > MakeUnoObject()
     278                 :          0 :     { OSL_FAIL("MetadatableUndo::MakeUnoObject"); throw; }
     279                 :            : };
     280                 :            : 
     281                 :            : // MetadatableClipboard ----------------------------------------------
     282                 :            : 
     283                 :            : /** the horrible Clipboard Metadatable: inserted into lists to track position */
     284         [ -  + ]:         12 : class MetadatableClipboard : public Metadatable
     285                 :            : {
     286                 :            :     /// as determined by the stream of the source in original document
     287                 :            :     const bool m_isInContent;
     288                 :            : public:
     289                 :          6 :     MetadatableClipboard(const bool i_isInContent)
     290                 :          6 :         : m_isInContent(i_isInContent) { }
     291                 :          6 :     virtual ::sfx2::XmlIdRegistry& GetRegistry()
     292                 :            :     {
     293                 :            :     // N.B. for Clipboard, m_pReg is initialized by registering this as copy in
     294                 :            :     // RegisterAsCopyOf; it is only cleared by OriginNoLongerInBusinessAnymore
     295                 :            :         OSL_ENSURE(m_pReg, "no m_pReg in MetadatableClipboard ?");
     296                 :          6 :         return *m_pReg;
     297                 :            :     }
     298                 :          6 :     virtual bool IsInClipboard() const { return true; }
     299                 :          6 :     virtual bool IsInUndo() const { return false; }
     300                 :          6 :     virtual bool IsInContent() const { return m_isInContent; }
     301                 :            :     virtual ::com::sun::star::uno::Reference<
     302                 :          0 :         ::com::sun::star::rdf::XMetadatable > MakeUnoObject()
     303                 :          0 :     { OSL_FAIL("MetadatableClipboard::MakeUnoObject"); throw; }
     304                 :          0 :     void OriginNoLongerInBusinessAnymore() { m_pReg = 0; }
     305                 :            : };
     306                 :            : 
     307                 :            : // XmlIdRegistryClipboard --------------------------------------------
     308                 :            : 
     309                 :            : class XmlIdRegistryClipboard : public XmlIdRegistry
     310                 :            : {
     311                 :            : 
     312                 :            : public:
     313                 :            :     XmlIdRegistryClipboard();
     314                 :            :     virtual ~XmlIdRegistryClipboard();
     315                 :            : 
     316                 :            :     virtual void RegisterMetadatableAndCreateID(Metadatable& i_xObject);
     317                 :            : 
     318                 :            :     virtual bool TryRegisterMetadatable(Metadatable& i_xObject,
     319                 :            :         ::rtl::OUString const& i_rStreamName, ::rtl::OUString const& i_rIdref);
     320                 :            : 
     321                 :            :     virtual void UnregisterMetadatable(Metadatable const&);
     322                 :            : 
     323                 :            :     virtual void RemoveXmlIdForElement(Metadatable const&);
     324                 :            : 
     325                 :            :     /** register i_rCopy as a copy of i_rSource */
     326                 :            :     MetadatableClipboard & RegisterCopyClipboard(Metadatable & i_rCopy,
     327                 :            :         beans::StringPair const & i_rReference,
     328                 :            :         const bool i_isLatent);
     329                 :            : 
     330                 :            :     /** get the Metadatable that links i_rObject to its origin registry */
     331                 :            :     MetadatableClipboard const* SourceLink(Metadatable const& i_rObject);
     332                 :            : 
     333                 :            : private:
     334                 :            :     virtual bool LookupXmlId(const Metadatable& i_xObject,
     335                 :            :         ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const;
     336                 :            : 
     337                 :            :     virtual Metadatable* LookupElement(const ::rtl::OUString & i_rStreamName,
     338                 :            :         const ::rtl::OUString & i_rIdref) const;
     339                 :            : 
     340                 :            :     /** create a Clipboard Metadatable for i_rObject. */
     341                 :            :     ::boost::shared_ptr<MetadatableClipboard> CreateClipboard(
     342                 :            :         const bool i_isInContent);
     343                 :            : 
     344                 :            :     struct XmlIdRegistry_Impl;
     345                 :            :     ::std::auto_ptr<XmlIdRegistry_Impl> m_pImpl;
     346                 :            : };
     347                 :            : 
     348                 :            : 
     349                 :            : //=============================================================================
     350                 :            : // XmlIdRegistry
     351                 :            : 
     352                 :         74 : ::sfx2::IXmlIdRegistry * createXmlIdRegistry(const bool i_DocIsClipboard)
     353                 :            : {
     354                 :            :     return i_DocIsClipboard
     355         [ +  - ]:          3 :         ? static_cast<XmlIdRegistry*>( new XmlIdRegistryClipboard )
     356 [ +  + ][ +  - ]:         77 :         : static_cast<XmlIdRegistry*>( new XmlIdRegistryDocument );
     357                 :            : }
     358                 :            : 
     359                 :         74 : XmlIdRegistry::XmlIdRegistry()
     360                 :            : {
     361                 :         74 : }
     362                 :            : 
     363                 :         74 : XmlIdRegistry::~XmlIdRegistry()
     364                 :            : {
     365         [ -  + ]:         74 : }
     366                 :            : 
     367                 :            : ::com::sun::star::uno::Reference< ::com::sun::star::rdf::XMetadatable > SAL_CALL
     368                 :          2 : XmlIdRegistry::GetElementByMetadataReference(
     369                 :            :     const beans::StringPair & i_rReference) const
     370                 :            : {
     371                 :            :     Metadatable* pObject( LookupElement(i_rReference.First,
     372                 :          2 :         i_rReference.Second) );
     373         [ +  - ]:          2 :     return pObject ? pObject->MakeUnoObject() : 0;
     374                 :            : }
     375                 :            : 
     376                 :            : beans::StringPair
     377                 :       1372 : XmlIdRegistry::GetXmlIdForElement(const Metadatable& i_rObject) const
     378                 :            : {
     379                 :       1372 :     ::rtl::OUString path;
     380                 :       1372 :     ::rtl::OUString idref;
     381 [ +  - ][ +  - ]:       1372 :     if (LookupXmlId(i_rObject, path, idref))
     382                 :            :     {
     383 [ +  - ][ +  + ]:       1372 :         if (LookupElement(path, idref) == &i_rObject)
     384                 :            :         {
     385                 :       1336 :             return beans::StringPair(path, idref);
     386                 :            :         }
     387                 :            :     }
     388                 :       1372 :     return beans::StringPair();
     389                 :            : }
     390                 :            : 
     391                 :            : 
     392                 :            : /// generate unique xml:id
     393                 :            : template< typename T >
     394                 :         47 : /*static*/ ::rtl::OUString create_id(const
     395                 :            :     ::boost::unordered_map< ::rtl::OUString, T, ::rtl::OUStringHash > & i_rXmlIdMap)
     396                 :            : {
     397 [ +  - ][ +  - ]:         47 :     static rtlRandomPool s_Pool( rtl_random_createPool() );
         [ +  + ][ +  - ]
     398                 :         47 :     const ::rtl::OUString prefix(s_prefix);
     399                 :            :     typename ::boost::unordered_map< ::rtl::OUString, T, ::rtl::OUStringHash >
     400                 :         47 :         ::const_iterator iter;
     401                 :         47 :     ::rtl::OUString id;
     402 [ -  + ][ -  + ]:         47 :     do
     403                 :            :     {
     404                 :            :         sal_Int32 n;
     405                 :         47 :         rtl_random_getBytes(s_Pool, & n, sizeof(n));
     406                 :         47 :         id = prefix + ::rtl::OUString::valueOf(static_cast<sal_Int32>(abs(n)));
     407   [ +  -  +  - ]:         47 :         iter = i_rXmlIdMap.find(id);
         [ +  - ][ +  - ]
     408                 :            :     }
     409                 :            :     while (iter != i_rXmlIdMap.end());
     410                 :         47 :     return id;
     411                 :            : }
     412                 :            : 
     413                 :            : //=============================================================================
     414                 :            : // Document XML ID Registry (_Impl)
     415                 :            : 
     416                 :            : /// element list
     417                 :            : typedef ::std::list< Metadatable* > XmlIdList_t;
     418                 :            : 
     419                 :            : /// Idref -> (content.xml element list, styles.xml element list)
     420                 :            : typedef ::boost::unordered_map< ::rtl::OUString,
     421                 :            :     ::std::pair< XmlIdList_t, XmlIdList_t >, ::rtl::OUStringHash > XmlIdMap_t;
     422                 :            : 
     423                 :            : /// pointer hash template
     424                 :            : template<typename T> struct PtrHash
     425                 :            : {
     426                 :       2931 :     size_t operator() (T const * i_pT) const
     427                 :            :     {
     428                 :       2931 :         return reinterpret_cast<size_t>(i_pT);
     429                 :            :     }
     430                 :            : };
     431                 :            : 
     432                 :            : /// element -> (stream name, idref)
     433                 :            : typedef ::boost::unordered_map< const Metadatable*,
     434                 :            :     ::std::pair< ::rtl::OUString, ::rtl::OUString>, PtrHash<Metadatable> >
     435                 :            :     XmlIdReverseMap_t;
     436                 :            : 
     437         [ +  - ]:         71 : struct XmlIdRegistryDocument::XmlIdRegistry_Impl
     438                 :            : {
     439                 :         71 :     XmlIdRegistry_Impl()
     440 [ +  - ][ +  - ]:         71 :         : m_XmlIdMap(), m_XmlIdReverseMap() { }
     441                 :            : 
     442                 :            :     bool TryInsertMetadatable(Metadatable& i_xObject,
     443                 :            :         const ::rtl::OUString & i_rStream, const ::rtl::OUString & i_rIdref);
     444                 :            : 
     445                 :            :     bool LookupXmlId(const Metadatable& i_xObject,
     446                 :            :         ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const;
     447                 :            : 
     448                 :            :     Metadatable* LookupElement(const ::rtl::OUString & i_rStreamName,
     449                 :            :         const ::rtl::OUString & i_rIdref) const;
     450                 :            : 
     451                 :            :     const XmlIdList_t * LookupElementList(
     452                 :            :         const ::rtl::OUString & i_rStreamName,
     453                 :            :         const ::rtl::OUString & i_rIdref) const;
     454                 :            : 
     455                 :        335 :           XmlIdList_t * LookupElementList(
     456                 :            :         const ::rtl::OUString & i_rStreamName,
     457                 :            :         const ::rtl::OUString & i_rIdref)
     458                 :            :     {
     459                 :            :         return const_cast<XmlIdList_t*>(
     460                 :            :             const_cast<const XmlIdRegistry_Impl*>(this)
     461                 :        335 :                 ->LookupElementList(i_rStreamName, i_rIdref));
     462                 :            :     }
     463                 :            : 
     464                 :            :     XmlIdMap_t m_XmlIdMap;
     465                 :            :     XmlIdReverseMap_t m_XmlIdReverseMap;
     466                 :            : };
     467                 :            : 
     468                 :            : // -------------------------------------------------------------------
     469                 :            : 
     470                 :            : static void
     471                 :        684 : rmIter(XmlIdMap_t & i_rXmlIdMap, XmlIdMap_t::iterator const& i_rIter,
     472                 :            :     ::rtl::OUString const & i_rStream, Metadatable const& i_rObject)
     473                 :            : {
     474         [ +  + ]:        684 :     if (i_rIter != i_rXmlIdMap.end())
     475                 :            :     {
     476                 :        376 :         XmlIdList_t & rList( isContentFile(i_rStream)
     477         [ +  + ]:        376 :             ? i_rIter->second.first : i_rIter->second.second );
     478         [ +  - ]:        376 :         rList.remove(&const_cast<Metadatable&>(i_rObject));
     479 [ +  + ][ +  - ]:        376 :         if (i_rIter->second.first.empty() && i_rIter->second.second.empty())
                 [ +  + ]
     480                 :            :         {
     481         [ +  - ]:        355 :             i_rXmlIdMap.erase(i_rIter);
     482                 :            :         }
     483                 :            :     }
     484                 :        684 : }
     485                 :            : 
     486                 :            : // -------------------------------------------------------------------
     487                 :            : 
     488                 :            : const XmlIdList_t *
     489                 :       1769 : XmlIdRegistryDocument::XmlIdRegistry_Impl::LookupElementList(
     490                 :            :     const ::rtl::OUString & i_rStreamName,
     491                 :            :     const ::rtl::OUString & i_rIdref) const
     492                 :            : {
     493         [ +  - ]:       1769 :     const XmlIdMap_t::const_iterator iter( m_XmlIdMap.find(i_rIdref) );
     494 [ +  - ][ +  + ]:       1769 :     if (iter != m_XmlIdMap.end())
     495                 :            :     {
     496                 :            :         OSL_ENSURE(!iter->second.first.empty() || !iter->second.second.empty(),
     497                 :            :             "null entry in m_XmlIdMap");
     498         [ +  - ]:       1458 :         return (isContentFile(i_rStreamName))
     499         [ +  - ]:       1455 :             ?  &iter->second.first
     500 [ +  + ][ +  - ]:       2913 :             :  &iter->second.second;
     501                 :            :     }
     502                 :            :     else
     503                 :            :     {
     504                 :       1769 :         return 0;
     505                 :            :     }
     506                 :            : }
     507                 :            : 
     508                 :            : Metadatable*
     509                 :       1434 : XmlIdRegistryDocument::XmlIdRegistry_Impl::LookupElement(
     510                 :            :     const ::rtl::OUString & i_rStreamName,
     511                 :            :     const ::rtl::OUString & i_rIdref) const
     512                 :            : {
     513         [ -  + ]:       1434 :     if (!isValidXmlId(i_rStreamName, i_rIdref))
     514                 :            :     {
     515                 :            :         throw lang::IllegalArgumentException(::rtl::OUString(
     516 [ #  # ][ #  # ]:          0 :             "illegal XmlId"), 0, 0);
     517                 :            :     }
     518                 :            : 
     519                 :       1434 :     const XmlIdList_t * pList( LookupElementList(i_rStreamName, i_rIdref) );
     520         [ +  - ]:       1434 :     if (pList)
     521                 :            :     {
     522                 :            :         const XmlIdList_t::const_iterator iter(
     523                 :            :             ::std::find_if(pList->begin(), pList->end(),
     524                 :            :                 ::boost::bind(
     525                 :            :                     ::std::logical_not<bool>(),
     526                 :            :                         ::boost::bind(
     527                 :            :                             ::std::logical_or<bool>(),
     528                 :            :                                 ::boost::bind( &Metadatable::IsInUndo, _1 ),
     529                 :            :                                 ::boost::bind( &Metadatable::IsInClipboard, _1 )
     530 [ +  - ][ +  - ]:       1434 :             ) ) ) );
         [ +  - ][ +  - ]
                 [ +  - ]
     531 [ +  - ][ +  + ]:       1434 :         if (iter != pList->end())
     532                 :            :         {
     533         [ +  - ]:       1434 :             return *iter;
     534                 :            :         }
     535                 :            :     }
     536                 :       1434 :     return 0;
     537                 :            : }
     538                 :            : 
     539                 :            : bool
     540                 :       2178 : XmlIdRegistryDocument::XmlIdRegistry_Impl::LookupXmlId(
     541                 :            :     const Metadatable& i_rObject,
     542                 :            :     ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const
     543                 :            : {
     544                 :            :     const XmlIdReverseMap_t::const_iterator iter(
     545         [ +  - ]:       2178 :         m_XmlIdReverseMap.find(&i_rObject) );
     546 [ +  - ][ +  + ]:       2178 :     if (iter != m_XmlIdReverseMap.end())
     547                 :            :     {
     548                 :            :         OSL_ENSURE(!iter->second.first.isEmpty(),
     549                 :            :             "null stream in m_XmlIdReverseMap");
     550                 :            :         OSL_ENSURE(!iter->second.second.isEmpty(),
     551                 :            :             "null id in m_XmlIdReverseMap");
     552         [ +  - ]:       1826 :         o_rStream = iter->second.first;
     553         [ +  - ]:       1826 :         o_rIdref  = iter->second.second;
     554                 :       1826 :         return true;
     555                 :            :     }
     556                 :            :     else
     557                 :            :     {
     558                 :       2178 :         return false;
     559                 :            :     }
     560                 :            : }
     561                 :            : 
     562                 :            : bool
     563                 :        317 : XmlIdRegistryDocument::XmlIdRegistry_Impl::TryInsertMetadatable(
     564                 :            :     Metadatable & i_rObject,
     565                 :            :     const ::rtl::OUString & i_rStreamName, const ::rtl::OUString & i_rIdref)
     566                 :            : {
     567                 :        317 :     const bool bContent( isContentFile(i_rStreamName) );
     568                 :            :     OSL_ENSURE(isContentFile(i_rStreamName) || isStylesFile(i_rStreamName),
     569                 :            :         "invalid stream");
     570                 :            : 
     571                 :        317 :     XmlIdList_t * pList( LookupElementList(i_rStreamName, i_rIdref) );
     572         [ +  + ]:        317 :     if (pList)
     573                 :            :     {
     574         [ -  + ]:          6 :         if (pList->empty())
     575                 :            :         {
     576         [ #  # ]:          0 :             pList->push_back( &i_rObject );
     577                 :          0 :             return true;
     578                 :            :         }
     579                 :            :         else
     580                 :            :         {
     581                 :            :             // this is only called from TryRegister now, so check
     582                 :            :             // if all elements in the list are deleted (in undo) or
     583                 :            :             // placeholders, then "steal" the id from them
     584 [ +  + ][ +  - ]:          6 :             if ( pList->end() == ::std::find_if(pList->begin(), pList->end(),
     585                 :            :                 ::boost::bind(
     586                 :            :                     ::std::logical_not<bool>(),
     587                 :            :                         ::boost::bind(
     588                 :            :                             ::std::logical_or<bool>(),
     589                 :            :                                 ::boost::bind( &Metadatable::IsInUndo, _1 ),
     590                 :            :                                 ::boost::bind( &Metadatable::IsInClipboard, _1 )
     591 [ +  - ][ +  - ]:          6 :                 ) ) ) )
                 [ +  - ]
     592                 :            :             {
     593         [ +  - ]:          3 :                 pList->push_front( &i_rObject );
     594                 :          3 :                 return true;
     595                 :            :             }
     596                 :            :             else
     597                 :            :             {
     598                 :          3 :                 return false;
     599                 :            :             }
     600                 :            :         }
     601                 :            :     }
     602                 :            :     else
     603                 :            :     {
     604                 :            :         m_XmlIdMap.insert(::std::make_pair(i_rIdref, bContent
     605                 :            :             ? ::std::make_pair( XmlIdList_t( 1, &i_rObject ), XmlIdList_t() )
     606 [ +  + ][ +  - ]:        311 :             : ::std::make_pair( XmlIdList_t(), XmlIdList_t( 1, &i_rObject ) )));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     607                 :        317 :         return true;
     608                 :            :     }
     609                 :            : }
     610                 :            : 
     611                 :            : //=============================================================================
     612                 :            : // Document XML ID Registry
     613                 :            : 
     614                 :            : 
     615                 :         71 : XmlIdRegistryDocument::XmlIdRegistryDocument()
     616 [ +  - ][ +  - ]:         71 :     :   m_pImpl( new XmlIdRegistry_Impl )
     617                 :            : {
     618                 :         71 : }
     619                 :            : 
     620                 :            : static void
     621                 :          0 : removeLink(Metadatable* i_pObject)
     622                 :            : {
     623                 :            :     OSL_ENSURE(i_pObject, "null in list ???");
     624         [ #  # ]:          0 :     if (!i_pObject) return;
     625         [ #  # ]:          0 :     if (i_pObject->IsInClipboard())
     626                 :            :     {
     627                 :            :         MetadatableClipboard* pLink(
     628         [ #  # ]:          0 :             dynamic_cast<MetadatableClipboard*>( i_pObject ) );
     629                 :            :         OSL_ENSURE(pLink, "IsInClipboard, but no MetadatableClipboard ?");
     630         [ #  # ]:          0 :         if (pLink)
     631                 :            :         {
     632                 :          0 :             pLink->OriginNoLongerInBusinessAnymore();
     633                 :            :         }
     634                 :            :     }
     635                 :            : }
     636                 :            : 
     637         [ +  - ]:         71 : XmlIdRegistryDocument::~XmlIdRegistryDocument()
     638                 :            : {
     639                 :            :     // notify all list elements that are actually in the clipboard
     640 [ +  - ][ -  + ]:        142 :     for (XmlIdMap_t::iterator iter(m_pImpl->m_XmlIdMap.begin());
     641         [ +  - ]:         71 :         iter != m_pImpl->m_XmlIdMap.end(); ++iter)
     642                 :            :     {
     643   [ #  #  #  # ]:          0 :         ::std::for_each(iter->second.first.begin(), iter->second.first.end(),
     644         [ #  # ]:          0 :             removeLink);
     645   [ #  #  #  # ]:          0 :         ::std::for_each(iter->second.second.begin(), iter->second.second.end(),
     646         [ #  # ]:          0 :             removeLink);
     647                 :            :     }
     648         [ -  + ]:        142 : }
     649                 :            : 
     650                 :            : bool
     651                 :       1351 : XmlIdRegistryDocument::LookupXmlId(
     652                 :            :     const Metadatable& i_rObject,
     653                 :            :     ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const
     654                 :            : {
     655                 :       1351 :     return m_pImpl->LookupXmlId(i_rObject, o_rStream, o_rIdref);
     656                 :            : }
     657                 :            : 
     658                 :            : Metadatable*
     659                 :       1350 : XmlIdRegistryDocument::LookupElement(
     660                 :            :     const ::rtl::OUString & i_rStreamName,
     661                 :            :     const ::rtl::OUString & i_rIdref) const
     662                 :            : {
     663                 :       1350 :     return m_pImpl->LookupElement(i_rStreamName, i_rIdref);
     664                 :            : }
     665                 :            : 
     666                 :            : bool
     667                 :        320 : XmlIdRegistryDocument::TryRegisterMetadatable(Metadatable & i_rObject,
     668                 :            :     ::rtl::OUString const& i_rStreamName, ::rtl::OUString const& i_rIdref)
     669                 :            : {
     670                 :            :     OSL_TRACE("TryRegisterMetadatable: %p (%s#%s)\n", &i_rObject,
     671                 :            :         ::rtl::OUStringToOString(i_rStreamName, RTL_TEXTENCODING_UTF8).getStr(),
     672                 :            :         ::rtl::OUStringToOString(i_rIdref, RTL_TEXTENCODING_UTF8).getStr());
     673                 :            : 
     674                 :            :     OSL_ENSURE(!dynamic_cast<MetadatableUndo*>(&i_rObject),
     675                 :            :         "TryRegisterMetadatable called for MetadatableUndo?");
     676                 :            :     OSL_ENSURE(!dynamic_cast<MetadatableClipboard*>(&i_rObject),
     677                 :            :         "TryRegisterMetadatable called for MetadatableClipboard?");
     678                 :            : 
     679 [ +  - ][ -  + ]:        320 :     if (!isValidXmlId(i_rStreamName, i_rIdref))
     680                 :            :     {
     681                 :            :         throw lang::IllegalArgumentException(::rtl::OUString(
     682 [ #  # ][ #  # ]:          0 :             "illegal XmlId"), 0, 0);
     683                 :            :     }
     684 [ +  - ][ +  + ]:        640 :     if (i_rObject.IsInContent()
                 [ -  + ]
     685         [ +  - ]:        317 :         ?   !isContentFile(i_rStreamName)
     686         [ +  - ]:          3 :         :   !isStylesFile(i_rStreamName))
     687                 :            :     {
     688                 :            :         throw lang::IllegalArgumentException(::rtl::OUString(
     689 [ #  # ][ #  # ]:          0 :             "illegal XmlId: wrong stream"), 0, 0);
     690                 :            :     }
     691                 :            : 
     692                 :        320 :     ::rtl::OUString old_path;
     693                 :        320 :     ::rtl::OUString old_idref;
     694         [ +  - ]:        320 :     m_pImpl->LookupXmlId(i_rObject, old_path, old_idref);
     695 [ +  + ][ +  + ]:        320 :     if (old_path  == i_rStreamName && old_idref == i_rIdref)
                 [ +  + ]
     696                 :            :     {
     697         [ +  - ]:          3 :         return (m_pImpl->LookupElement(old_path, old_idref) == &i_rObject);
     698                 :            :     }
     699         [ +  - ]:        317 :     XmlIdMap_t::iterator old_id( m_pImpl->m_XmlIdMap.end() );
     700         [ +  + ]:        317 :     if (!old_idref.isEmpty())
     701                 :            :     {
     702         [ +  - ]:          6 :         old_id = m_pImpl->m_XmlIdMap.find(old_idref);
     703                 :            :         OSL_ENSURE(old_id != m_pImpl->m_XmlIdMap.end(), "old id not found");
     704                 :            :     }
     705 [ +  - ][ +  + ]:        317 :     if (m_pImpl->TryInsertMetadatable(i_rObject, i_rStreamName, i_rIdref))
     706                 :            :     {
     707         [ +  - ]:        314 :         rmIter(m_pImpl->m_XmlIdMap, old_id, old_path, i_rObject);
     708         [ +  - ]:        314 :         m_pImpl->m_XmlIdReverseMap[&i_rObject] =
     709                 :        628 :             ::std::make_pair(i_rStreamName, i_rIdref);
     710                 :        314 :         return true;
     711                 :            :     }
     712                 :            :     else
     713                 :            :     {
     714                 :          3 :         return false;
     715                 :        320 :     }
     716                 :            : }
     717                 :            : 
     718                 :            : void
     719                 :        122 : XmlIdRegistryDocument::RegisterMetadatableAndCreateID(Metadatable & i_rObject)
     720                 :            : {
     721                 :            :     OSL_TRACE("RegisterMetadatableAndCreateID: %p", &i_rObject);
     722                 :            : 
     723                 :            :     OSL_ENSURE(!dynamic_cast<MetadatableUndo*>(&i_rObject),
     724                 :            :         "RegisterMetadatableAndCreateID called for MetadatableUndo?");
     725                 :            :     OSL_ENSURE(!dynamic_cast<MetadatableClipboard*>(&i_rObject),
     726                 :            :         "RegisterMetadatableAndCreateID called for MetadatableClipboard?");
     727                 :            : 
     728         [ +  - ]:        122 :     const bool isInContent( i_rObject.IsInContent() );
     729                 :            :     const ::rtl::OUString stream( ::rtl::OUString::createFromAscii(
     730         [ +  - ]:        122 :         isInContent ? s_content : s_styles ) );
     731                 :            :     // check if we have a latent xmlid, and if yes, remove it
     732                 :        122 :     ::rtl::OUString old_path;
     733                 :        122 :     ::rtl::OUString old_idref;
     734         [ +  - ]:        122 :     m_pImpl->LookupXmlId(i_rObject, old_path, old_idref);
     735                 :            : 
     736         [ +  - ]:        122 :     XmlIdMap_t::iterator old_id( m_pImpl->m_XmlIdMap.end() );
     737         [ +  + ]:        122 :     if (!old_idref.isEmpty())
     738                 :            :     {
     739         [ +  - ]:         81 :         old_id = m_pImpl->m_XmlIdMap.find(old_idref);
     740                 :            :         OSL_ENSURE(old_id != m_pImpl->m_XmlIdMap.end(), "old id not found");
     741 [ +  - ][ +  + ]:         81 :         if (m_pImpl->LookupElement(old_path, old_idref) == &i_rObject)
     742                 :            :         {
     743                 :        122 :             return;
     744                 :            :         }
     745                 :            :         else
     746                 :            :         {
     747                 :            :             // remove latent xmlid
     748         [ +  - ]:          3 :             rmIter(m_pImpl->m_XmlIdMap, old_id, old_path, i_rObject);
     749                 :            :         }
     750                 :            :     }
     751                 :            : 
     752                 :            :     // create id
     753         [ +  - ]:         44 :     const ::rtl::OUString id( create_id(m_pImpl->m_XmlIdMap) );
     754                 :            :     OSL_ENSURE(m_pImpl->m_XmlIdMap.find(id) == m_pImpl->m_XmlIdMap.end(),
     755                 :            :         "created id is in use");
     756                 :         44 :     m_pImpl->m_XmlIdMap.insert(::std::make_pair(id, isInContent
     757                 :            :         ? ::std::make_pair( XmlIdList_t( 1, &i_rObject ), XmlIdList_t() )
     758 [ +  - ][ +  - ]:         88 :         : ::std::make_pair( XmlIdList_t(), XmlIdList_t( 1, &i_rObject ) )));
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ -  + ]
         [ -  + ][ -  + ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     759 [ +  - ][ +  + ]:        122 :     m_pImpl->m_XmlIdReverseMap[&i_rObject] = ::std::make_pair(stream, id);
         [ +  + ][ +  + ]
     760                 :            : }
     761                 :            : 
     762                 :        367 : void XmlIdRegistryDocument::UnregisterMetadatable(const Metadatable& i_rObject)
     763                 :            : {
     764                 :            :     OSL_TRACE("UnregisterMetadatable: %p", &i_rObject);
     765                 :            : 
     766                 :        367 :     ::rtl::OUString path;
     767                 :        367 :     ::rtl::OUString idref;
     768 [ -  + ][ +  - ]:        367 :     if (!m_pImpl->LookupXmlId(i_rObject, path, idref))
     769                 :            :     {
     770                 :            :         OSL_FAIL("unregister: no xml id?");
     771                 :        367 :         return;
     772                 :            :     }
     773         [ +  - ]:        367 :     const XmlIdMap_t::iterator iter( m_pImpl->m_XmlIdMap.find(idref) );
     774 [ +  - ][ +  - ]:        367 :     if (iter != m_pImpl->m_XmlIdMap.end())
     775                 :            :     {
     776         [ +  - ]:        367 :         rmIter(m_pImpl->m_XmlIdMap, iter, path, i_rObject);
     777 [ -  + ][ +  - ]:        367 :     }
     778                 :            : }
     779                 :            : 
     780                 :        367 : void XmlIdRegistryDocument::RemoveXmlIdForElement(const Metadatable& i_rObject)
     781                 :            : {
     782                 :            :     OSL_TRACE("RemoveXmlIdForElement: %p", &i_rObject);
     783                 :            : 
     784                 :            :     const XmlIdReverseMap_t::iterator iter(
     785         [ +  - ]:        367 :         m_pImpl->m_XmlIdReverseMap.find(&i_rObject) );
     786 [ +  - ][ +  - ]:        367 :     if (iter != m_pImpl->m_XmlIdReverseMap.end())
     787                 :            :     {
     788                 :            :         OSL_ENSURE(!iter->second.second.isEmpty(),
     789                 :            :             "null id in m_XmlIdReverseMap");
     790         [ +  - ]:        367 :         m_pImpl->m_XmlIdReverseMap.erase(iter);
     791                 :            :     }
     792                 :        367 : }
     793                 :            : 
     794                 :            : // -------------------------------------------------------------------
     795                 :            : 
     796                 :         18 : void XmlIdRegistryDocument::RegisterCopy(Metadatable const& i_rSource,
     797                 :            :     Metadatable & i_rCopy, const bool i_bCopyPrecedesSource)
     798                 :            : {
     799                 :            :     OSL_TRACE("RegisterCopy: %p -> %p (%d)\n",
     800                 :            :         &i_rSource, &i_rCopy, i_bCopyPrecedesSource);
     801                 :            : 
     802                 :            :     // potential sources: clipboard, undo array, splitNode
     803                 :            :     // assumption: stream change can only happen via clipboard, and is handled
     804                 :            :     // by Metadatable::RegisterAsCopyOf
     805                 :            :     OSL_ENSURE(i_rSource.IsInUndo() || i_rCopy.IsInUndo() ||
     806                 :            :         (i_rSource.IsInContent() == i_rCopy.IsInContent()),
     807                 :            :         "RegisterCopy: not in same stream?");
     808                 :            : 
     809                 :         18 :     ::rtl::OUString path;
     810                 :         18 :     ::rtl::OUString idref;
     811 [ -  + ][ +  - ]:         18 :     if (!m_pImpl->LookupXmlId( i_rSource, path, idref ))
     812                 :            :     {
     813                 :            :         OSL_FAIL("no xml id?");
     814                 :            :         return;
     815                 :            :     }
     816         [ +  - ]:         18 :     XmlIdList_t * pList ( m_pImpl->LookupElementList(path, idref) );
     817                 :            :     OSL_ENSURE( ::std::find( pList->begin(), pList->end(), &i_rCopy )
     818                 :            :         == pList->end(), "copy already registered???");
     819                 :            :     XmlIdList_t::iterator srcpos(
     820         [ +  - ]:         18 :         ::std::find( pList->begin(), pList->end(), &i_rSource ) );
     821                 :            :     OSL_ENSURE(srcpos != pList->end(), "source not in list???");
     822 [ +  - ][ -  + ]:         18 :     if (srcpos == pList->end())
     823                 :            :     {
     824                 :            :         return;
     825                 :            :     }
     826         [ +  + ]:         18 :     if (i_bCopyPrecedesSource)
     827                 :            :     {
     828         [ +  - ]:          6 :         pList->insert( srcpos, &i_rCopy );
     829                 :            :     }
     830                 :            :     else
     831                 :            :     {
     832                 :            :         // for undo push_back does not work! must insert right after source
     833 [ +  - ][ +  - ]:         12 :         pList->insert( ++srcpos, &i_rCopy );
     834                 :            :     }
     835                 :         18 :     m_pImpl->m_XmlIdReverseMap.insert(::std::make_pair(&i_rCopy,
     836         [ +  - ]:         36 :         ::std::make_pair(path, idref)));
           [ +  -  +  - ]
         [ -  + ][ +  - ]
     837                 :            : }
     838                 :            : 
     839                 :            : ::boost::shared_ptr<MetadatableUndo>
     840                 :          0 : XmlIdRegistryDocument::CreateUndo(Metadatable const& i_rObject)
     841                 :            : {
     842                 :            :     OSL_TRACE("CreateUndo: %p", &i_rObject);
     843                 :            : 
     844                 :            :     return ::boost::shared_ptr<MetadatableUndo>(
     845         [ #  # ]:          0 :                 new MetadatableUndo(i_rObject.IsInContent()) );
     846                 :            : }
     847                 :            : 
     848                 :            : /*
     849                 :            : i_rMerged is both a source and the target node of the merge
     850                 :            : i_rOther is the other source, and will be deleted after the merge
     851                 :            : 
     852                 :            : dimensions: none|latent|actual empty|nonempty
     853                 :            : i_rMerged(1)    i_rOther(2)        result
     854                 :            :      *|empty         *|empty    => 1|2 (arbitrary)
     855                 :            :      *|empty         *|nonempty => 2
     856                 :            :      *|nonempty      *|empty    => 1
     857                 :            :   none|nonempty   none|nonempty => none
     858                 :            :   none|nonempty latent|nonempty => 2
     859                 :            : latent|nonempty   none|nonempty => 1
     860                 :            : latent|nonempty latent|nonempty => 1|2
     861                 :            :      *|nonempty actual|nonempty => 2
     862                 :            : actual|nonempty      *|nonempty => 1
     863                 :            : actual|nonempty actual|nonempty => 1|2
     864                 :            : */
     865                 :            : void
     866                 :          0 : XmlIdRegistryDocument::JoinMetadatables(
     867                 :            :     Metadatable & i_rMerged, Metadatable const & i_rOther)
     868                 :            : {
     869                 :            :     OSL_TRACE("JoinMetadatables: %p <- %p", &i_rMerged, &i_rOther);
     870                 :            : 
     871                 :            :     bool mergedOwnsRef;
     872                 :          0 :     ::rtl::OUString path;
     873                 :          0 :     ::rtl::OUString idref;
     874 [ #  # ][ #  # ]:          0 :     if (m_pImpl->LookupXmlId(i_rMerged, path, idref))
     875                 :            :     {
     876         [ #  # ]:          0 :         mergedOwnsRef = (m_pImpl->LookupElement(path, idref) == &i_rMerged);
     877                 :            :     }
     878                 :            :     else
     879                 :            :     {
     880                 :            :         OSL_FAIL("JoinMetadatables: no xmlid?");
     881                 :            :         return;
     882                 :            :     }
     883         [ #  # ]:          0 :     if (!mergedOwnsRef)
     884                 :            :     {
     885         [ #  # ]:          0 :         i_rMerged.RemoveMetadataReference();
     886         [ #  # ]:          0 :         i_rMerged.RegisterAsCopyOf(i_rOther, true);
     887                 :            :         return;
     888 [ #  # ][ #  # ]:          0 :     }
     889                 :            :     // other cases: merged has actual ref and is nonempty,
     890                 :            :     // other has latent/actual ref and is nonempty: other loses => nothing to do
     891                 :            : }
     892                 :            : 
     893                 :            : 
     894                 :            : //=============================================================================
     895                 :            : // Clipboard XML ID Registry (_Impl)
     896                 :            : 
     897 [ +  - ][ +  - ]:         60 : struct RMapEntry
     898                 :            : {
     899         [ +  - ]:          6 :     RMapEntry() : m_pLink() { }
     900                 :         12 :     RMapEntry(::rtl::OUString const& i_rStream,
     901                 :            :             ::rtl::OUString const& i_rXmlId,
     902                 :            :             ::boost::shared_ptr<MetadatableClipboard> const& i_pLink
     903                 :            :                 = ::boost::shared_ptr<MetadatableClipboard>())
     904         [ +  - ]:         12 :         :   m_Stream(i_rStream), m_XmlId(i_rXmlId), m_pLink(i_pLink)
     905                 :         12 :         {}
     906                 :            :     ::rtl::OUString m_Stream;
     907                 :            :     ::rtl::OUString m_XmlId;
     908                 :            :     // this would have been an auto_ptr, if only that would have compiled...
     909                 :            :     ::boost::shared_ptr<MetadatableClipboard> m_pLink;
     910                 :            : };
     911                 :            : 
     912                 :            : /// element -> (stream name, idref, source)
     913                 :            : typedef ::boost::unordered_map< const Metadatable*,
     914                 :            :     struct RMapEntry,
     915                 :            :     PtrHash<Metadatable> >
     916                 :            :     ClipboardXmlIdReverseMap_t;
     917                 :            : 
     918                 :            : /// Idref -> (content.xml element, styles.xml element)
     919                 :            : typedef ::boost::unordered_map< ::rtl::OUString,
     920                 :            :     ::std::pair< Metadatable*, Metadatable* >, ::rtl::OUStringHash >
     921                 :            :     ClipboardXmlIdMap_t;
     922                 :            : 
     923         [ +  - ]:          3 : struct XmlIdRegistryClipboard::XmlIdRegistry_Impl
     924                 :            : {
     925                 :          3 :     XmlIdRegistry_Impl()
     926 [ +  - ][ +  - ]:          3 :         : m_XmlIdMap(), m_XmlIdReverseMap() { }
     927                 :            : 
     928                 :            :     bool TryInsertMetadatable(Metadatable& i_xObject,
     929                 :            :         const ::rtl::OUString & i_rStream, const ::rtl::OUString & i_rIdref);
     930                 :            : 
     931                 :            :     bool LookupXmlId(const Metadatable& i_xObject,
     932                 :            :         ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref,
     933                 :            :         MetadatableClipboard const* &o_rpLink) const;
     934                 :            : 
     935                 :            :     Metadatable* LookupElement(const ::rtl::OUString & i_rStreamName,
     936                 :            :         const ::rtl::OUString & i_rIdref) const;
     937                 :            : 
     938                 :            :     Metadatable* const* LookupEntry(const ::rtl::OUString & i_rStreamName,
     939                 :            :         const ::rtl::OUString & i_rIdref) const;
     940                 :            : 
     941                 :          9 :     Metadatable*      * LookupEntry(const ::rtl::OUString & i_rStreamName,
     942                 :            :         const ::rtl::OUString & i_rIdref)
     943                 :            :     {
     944                 :            :         return const_cast<Metadatable**>(
     945                 :            :             const_cast<const XmlIdRegistry_Impl*>(this)
     946                 :          9 :                 ->LookupEntry(i_rStreamName, i_rIdref));
     947                 :            :     }
     948                 :            : 
     949                 :            :     ClipboardXmlIdMap_t m_XmlIdMap;
     950                 :            :     ClipboardXmlIdReverseMap_t m_XmlIdReverseMap;
     951                 :            : };
     952                 :            : 
     953                 :            : // -------------------------------------------------------------------
     954                 :            : 
     955                 :            : static void
     956                 :         12 : rmIter(ClipboardXmlIdMap_t & i_rXmlIdMap,
     957                 :            :     ClipboardXmlIdMap_t::iterator const& i_rIter,
     958                 :            :     ::rtl::OUString const & i_rStream, Metadatable const& i_rObject)
     959                 :            : {
     960         [ +  + ]:         12 :     if (i_rIter != i_rXmlIdMap.end())
     961                 :            :     {
     962                 :          9 :         Metadatable *& rMeta = isContentFile(i_rStream)
     963         [ +  - ]:          9 :             ? i_rIter->second.first : i_rIter->second.second;
     964         [ +  - ]:          9 :         if (rMeta == &i_rObject)
     965                 :            :         {
     966                 :          9 :             rMeta = 0;
     967                 :            :         }
     968 [ +  - ][ +  - ]:          9 :         if (!i_rIter->second.first && !i_rIter->second.second)
                 [ +  - ]
     969                 :            :         {
     970         [ +  - ]:          9 :             i_rXmlIdMap.erase(i_rIter);
     971                 :            :         }
     972                 :            :     }
     973                 :         12 : }
     974                 :            : 
     975                 :            : // -------------------------------------------------------------------
     976                 :            : 
     977                 :            : Metadatable* const*
     978                 :         42 : XmlIdRegistryClipboard::XmlIdRegistry_Impl::LookupEntry(
     979                 :            :     const ::rtl::OUString & i_rStreamName,
     980                 :            :     const ::rtl::OUString & i_rIdref) const
     981                 :            : {
     982 [ +  - ][ -  + ]:         42 :     if (!isValidXmlId(i_rStreamName, i_rIdref))
     983                 :            :     {
     984                 :            :         throw lang::IllegalArgumentException(::rtl::OUString(
     985 [ #  # ][ #  # ]:          0 :             "illegal XmlId"), 0, 0);
     986                 :            :     }
     987                 :            : 
     988         [ +  - ]:         42 :     const ClipboardXmlIdMap_t::const_iterator iter( m_XmlIdMap.find(i_rIdref) );
     989 [ +  - ][ +  + ]:         42 :     if (iter != m_XmlIdMap.end())
     990                 :            :     {
     991                 :            :         OSL_ENSURE(iter->second.first || iter->second.second,
     992                 :            :             "null entry in m_XmlIdMap");
     993         [ +  - ]:         30 :         return (isContentFile(i_rStreamName))
     994         [ +  - ]:         30 :             ?  &iter->second.first
     995 [ +  - ][ #  # ]:         60 :             :  &iter->second.second;
     996                 :            :     }
     997                 :            :     else
     998                 :            :     {
     999                 :         42 :         return 0;
    1000                 :            :     }
    1001                 :            : }
    1002                 :            : 
    1003                 :            : Metadatable*
    1004                 :         33 : XmlIdRegistryClipboard::XmlIdRegistry_Impl::LookupElement(
    1005                 :            :     const ::rtl::OUString & i_rStreamName,
    1006                 :            :     const ::rtl::OUString & i_rIdref) const
    1007                 :            : {
    1008                 :         33 :     Metadatable * const * ppEntry = LookupEntry(i_rStreamName, i_rIdref);
    1009         [ +  + ]:         33 :     return ppEntry ? *ppEntry : 0;
    1010                 :            : }
    1011                 :            : 
    1012                 :            : bool
    1013                 :         60 : XmlIdRegistryClipboard::XmlIdRegistry_Impl::LookupXmlId(
    1014                 :            :     const Metadatable& i_rObject,
    1015                 :            :     ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref,
    1016                 :            :     MetadatableClipboard const* &o_rpLink) const
    1017                 :            : {
    1018                 :            :     const ClipboardXmlIdReverseMap_t::const_iterator iter(
    1019         [ +  - ]:         60 :         m_XmlIdReverseMap.find(&i_rObject) );
    1020 [ +  - ][ +  + ]:         60 :     if (iter != m_XmlIdReverseMap.end())
    1021                 :            :     {
    1022                 :            :         OSL_ENSURE(!iter->second.m_Stream.isEmpty(),
    1023                 :            :             "null stream in m_XmlIdReverseMap");
    1024                 :            :         OSL_ENSURE(!iter->second.m_XmlId.isEmpty(),
    1025                 :            :             "null id in m_XmlIdReverseMap");
    1026         [ +  - ]:         51 :         o_rStream = iter->second.m_Stream;
    1027         [ +  - ]:         51 :         o_rIdref  = iter->second.m_XmlId;
    1028         [ +  - ]:         51 :         o_rpLink  = iter->second.m_pLink.get();
    1029                 :         51 :         return true;
    1030                 :            :     }
    1031                 :            :     else
    1032                 :            :     {
    1033                 :         60 :         return false;
    1034                 :            :     }
    1035                 :            : }
    1036                 :            : 
    1037                 :            : bool
    1038                 :          9 : XmlIdRegistryClipboard::XmlIdRegistry_Impl::TryInsertMetadatable(
    1039                 :            :     Metadatable & i_rObject,
    1040                 :            :     const ::rtl::OUString & i_rStreamName, const ::rtl::OUString & i_rIdref)
    1041                 :            : {
    1042                 :          9 :     bool bContent( isContentFile(i_rStreamName) );
    1043                 :            :     OSL_ENSURE(isContentFile(i_rStreamName) || isStylesFile(i_rStreamName),
    1044                 :            :         "invalid stream");
    1045                 :            : 
    1046                 :          9 :     Metadatable ** ppEntry = LookupEntry(i_rStreamName, i_rIdref);
    1047         [ +  + ]:          9 :     if (ppEntry)
    1048                 :            :     {
    1049         [ +  - ]:          3 :         if (*ppEntry)
    1050                 :            :         {
    1051                 :          3 :             return false;
    1052                 :            :         }
    1053                 :            :         else
    1054                 :            :         {
    1055                 :          0 :             *ppEntry = &i_rObject;
    1056                 :          0 :             return true;
    1057                 :            :         }
    1058                 :            :     }
    1059                 :            :     else
    1060                 :            :     {
    1061                 :            :         m_XmlIdMap.insert(::std::make_pair(i_rIdref, bContent
    1062                 :            :             ? ::std::make_pair( &i_rObject, static_cast<Metadatable*>(0) )
    1063 [ +  - ][ +  - ]:          6 :             : ::std::make_pair( static_cast<Metadatable*>(0), &i_rObject )));
         [ #  # ][ +  - ]
         [ +  - ][ -  + ]
         [ -  + ][ +  - ]
         [ +  - ][ #  #  
          #  #  #  #  #  
                      # ]
    1064                 :          9 :         return true;
    1065                 :            :     }
    1066                 :            : }
    1067                 :            : 
    1068                 :            : //=============================================================================
    1069                 :            : // Clipboard XML ID Registry
    1070                 :            : 
    1071                 :            : 
    1072                 :          3 : XmlIdRegistryClipboard::XmlIdRegistryClipboard()
    1073 [ +  - ][ +  - ]:          3 :     :   m_pImpl( new XmlIdRegistry_Impl )
    1074                 :            : {
    1075                 :          3 : }
    1076                 :            : 
    1077         [ +  - ]:          3 : XmlIdRegistryClipboard::~XmlIdRegistryClipboard()
    1078                 :            : {
    1079         [ -  + ]:          6 : }
    1080                 :            : 
    1081                 :            : bool
    1082                 :         33 : XmlIdRegistryClipboard::LookupXmlId(
    1083                 :            :     const Metadatable& i_rObject,
    1084                 :            :     ::rtl::OUString & o_rStream, ::rtl::OUString & o_rIdref) const
    1085                 :            : {
    1086                 :            :     const MetadatableClipboard * pLink;
    1087         [ +  - ]:         33 :     return m_pImpl->LookupXmlId(i_rObject, o_rStream, o_rIdref, pLink);
    1088                 :            : }
    1089                 :            : 
    1090                 :            : Metadatable*
    1091                 :         24 : XmlIdRegistryClipboard::LookupElement(
    1092                 :            :     const ::rtl::OUString & i_rStreamName,
    1093                 :            :     const ::rtl::OUString & i_rIdref) const
    1094                 :            : {
    1095                 :         24 :     return m_pImpl->LookupElement(i_rStreamName, i_rIdref);
    1096                 :            : }
    1097                 :            : 
    1098                 :            : bool
    1099                 :          9 : XmlIdRegistryClipboard::TryRegisterMetadatable(Metadatable & i_rObject,
    1100                 :            :     ::rtl::OUString const& i_rStreamName, ::rtl::OUString const& i_rIdref)
    1101                 :            : {
    1102                 :            :     OSL_TRACE("TryRegisterMetadatable: %p (%s#%s)\n", &i_rObject,
    1103                 :            :         ::rtl::OUStringToOString(i_rStreamName, RTL_TEXTENCODING_UTF8).getStr(),
    1104                 :            :         ::rtl::OUStringToOString(i_rIdref, RTL_TEXTENCODING_UTF8).getStr());
    1105                 :            : 
    1106                 :            :     OSL_ENSURE(!dynamic_cast<MetadatableUndo*>(&i_rObject),
    1107                 :            :         "TryRegisterMetadatable called for MetadatableUndo?");
    1108                 :            :     OSL_ENSURE(!dynamic_cast<MetadatableClipboard*>(&i_rObject),
    1109                 :            :         "TryRegisterMetadatable called for MetadatableClipboard?");
    1110                 :            : 
    1111 [ +  - ][ -  + ]:          9 :     if (!isValidXmlId(i_rStreamName, i_rIdref))
    1112                 :            :     {
    1113                 :            :         throw lang::IllegalArgumentException(::rtl::OUString(
    1114 [ #  # ][ #  # ]:          0 :             "illegal XmlId"), 0, 0);
    1115                 :            :     }
    1116 [ +  - ][ +  - ]:         18 :     if (i_rObject.IsInContent()
                 [ -  + ]
    1117         [ +  - ]:          9 :         ?   !isContentFile(i_rStreamName)
    1118         [ #  # ]:          0 :         :   !isStylesFile(i_rStreamName))
    1119                 :            :     {
    1120                 :            :         throw lang::IllegalArgumentException(::rtl::OUString(
    1121 [ #  # ][ #  # ]:          0 :             "illegal XmlId: wrong stream"), 0, 0);
    1122                 :            :     }
    1123                 :            : 
    1124                 :          9 :     ::rtl::OUString old_path;
    1125                 :          9 :     ::rtl::OUString old_idref;
    1126                 :            :     const MetadatableClipboard * pLink;
    1127         [ +  - ]:          9 :     m_pImpl->LookupXmlId(i_rObject, old_path, old_idref, pLink);
    1128 [ +  + ][ +  - ]:          9 :     if (old_path  == i_rStreamName && old_idref == i_rIdref)
                 [ +  + ]
    1129                 :            :     {
    1130         [ +  - ]:          3 :         return (m_pImpl->LookupElement(old_path, old_idref) == &i_rObject);
    1131                 :            :     }
    1132         [ +  - ]:          6 :     ClipboardXmlIdMap_t::iterator old_id( m_pImpl->m_XmlIdMap.end() );
    1133         [ -  + ]:          6 :     if (!old_idref.isEmpty())
    1134                 :            :     {
    1135         [ #  # ]:          0 :         old_id = m_pImpl->m_XmlIdMap.find(old_idref);
    1136                 :            :         OSL_ENSURE(old_id != m_pImpl->m_XmlIdMap.end(), "old id not found");
    1137                 :            :     }
    1138 [ +  - ][ +  + ]:          6 :     if (m_pImpl->TryInsertMetadatable(i_rObject, i_rStreamName, i_rIdref))
    1139                 :            :     {
    1140         [ +  - ]:          3 :         rmIter(m_pImpl->m_XmlIdMap, old_id, old_path, i_rObject);
    1141         [ +  - ]:          3 :         m_pImpl->m_XmlIdReverseMap[&i_rObject] =
    1142 [ +  - ][ +  - ]:          6 :             RMapEntry(i_rStreamName, i_rIdref);
         [ +  - ][ +  - ]
                 [ +  - ]
    1143                 :          3 :         return true;
    1144                 :            :     }
    1145                 :            :     else
    1146                 :            :     {
    1147                 :          3 :         return false;
    1148                 :          9 :     }
    1149                 :            : }
    1150                 :            : 
    1151                 :            : void
    1152                 :          9 : XmlIdRegistryClipboard::RegisterMetadatableAndCreateID(Metadatable & i_rObject)
    1153                 :            : {
    1154                 :            :     OSL_TRACE("RegisterMetadatableAndCreateID: %p", &i_rObject);
    1155                 :            : 
    1156                 :            :     OSL_ENSURE(!dynamic_cast<MetadatableUndo*>(&i_rObject),
    1157                 :            :         "RegisterMetadatableAndCreateID called for MetadatableUndo?");
    1158                 :            :     OSL_ENSURE(!dynamic_cast<MetadatableClipboard*>(&i_rObject),
    1159                 :            :         "RegisterMetadatableAndCreateID called for MetadatableClipboard?");
    1160                 :            : 
    1161         [ +  - ]:          9 :     bool isInContent( i_rObject.IsInContent() );
    1162                 :            :     ::rtl::OUString stream( ::rtl::OUString::createFromAscii(
    1163         [ +  - ]:          9 :         isInContent ? s_content : s_styles ) );
    1164                 :            : 
    1165                 :          9 :     ::rtl::OUString old_path;
    1166                 :          9 :     ::rtl::OUString old_idref;
    1167         [ +  - ]:          9 :     LookupXmlId(i_rObject, old_path, old_idref);
    1168 [ +  + ][ +  - ]:         15 :     if (!old_idref.isEmpty() &&
                 [ +  + ]
    1169         [ +  - ]:          6 :         (m_pImpl->LookupElement(old_path, old_idref) == &i_rObject))
    1170                 :            :     {
    1171                 :          9 :         return;
    1172                 :            :     }
    1173                 :            : 
    1174                 :            :     // create id
    1175         [ +  - ]:          3 :     const ::rtl::OUString id( create_id(m_pImpl->m_XmlIdMap) );
    1176                 :            :     OSL_ENSURE(m_pImpl->m_XmlIdMap.find(id) == m_pImpl->m_XmlIdMap.end(),
    1177                 :            :         "created id is in use");
    1178                 :          3 :     m_pImpl->m_XmlIdMap.insert(::std::make_pair(id, isInContent
    1179                 :            :         ? ::std::make_pair( &i_rObject, static_cast<Metadatable*>(0) )
    1180 [ +  - ][ +  - ]:          6 :         : ::std::make_pair( static_cast<Metadatable*>(0), &i_rObject )));
         [ #  # ][ +  - ]
         [ +  - ][ -  + ]
         [ -  + ][ +  - ]
         [ +  - ][ #  #  
          #  #  #  #  #  
                      # ]
    1181                 :            :     // N.B.: if i_rObject had a latent XmlId, then we implicitly delete the
    1182                 :            :     // MetadatableClipboard and thus the latent XmlId here
    1183 [ +  - ][ +  - ]:          9 :     m_pImpl->m_XmlIdReverseMap[&i_rObject] = RMapEntry(stream, id);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
                 [ +  + ]
    1184                 :            : }
    1185                 :            : 
    1186                 :         12 : void XmlIdRegistryClipboard::UnregisterMetadatable(const Metadatable& i_rObject)
    1187                 :            : {
    1188                 :            :     OSL_TRACE("UnregisterMetadatable: %p", &i_rObject);
    1189                 :            : 
    1190                 :         12 :     ::rtl::OUString path;
    1191                 :         12 :     ::rtl::OUString idref;
    1192                 :            :     const MetadatableClipboard * pLink;
    1193 [ -  + ][ +  - ]:         12 :     if (!m_pImpl->LookupXmlId(i_rObject, path, idref, pLink))
    1194                 :            :     {
    1195                 :            :         OSL_FAIL("unregister: no xml id?");
    1196                 :         12 :         return;
    1197                 :            :     }
    1198         [ +  - ]:         12 :     const ClipboardXmlIdMap_t::iterator iter( m_pImpl->m_XmlIdMap.find(idref) );
    1199 [ +  - ][ +  + ]:         12 :     if (iter != m_pImpl->m_XmlIdMap.end())
    1200                 :            :     {
    1201         [ +  - ]:         12 :         rmIter(m_pImpl->m_XmlIdMap, iter, path, i_rObject);
    1202 [ -  + ][ +  - ]:         12 :     }
    1203                 :            : }
    1204                 :            : 
    1205                 :            : 
    1206                 :         12 : void XmlIdRegistryClipboard::RemoveXmlIdForElement(const Metadatable& i_rObject)
    1207                 :            : {
    1208                 :            :     OSL_TRACE("RemoveXmlIdForElement: %p", &i_rObject);
    1209                 :            : 
    1210                 :            :     ClipboardXmlIdReverseMap_t::iterator iter(
    1211         [ +  - ]:         12 :         m_pImpl->m_XmlIdReverseMap.find(&i_rObject) );
    1212 [ +  - ][ +  - ]:         12 :     if (iter != m_pImpl->m_XmlIdReverseMap.end())
    1213                 :            :     {
    1214                 :            :         OSL_ENSURE(!iter->second.m_XmlId.isEmpty(),
    1215                 :            :             "null id in m_XmlIdReverseMap");
    1216         [ +  - ]:         12 :         m_pImpl->m_XmlIdReverseMap.erase(iter);
    1217                 :            :     }
    1218                 :         12 : }
    1219                 :            : 
    1220                 :            : // -------------------------------------------------------------------
    1221                 :            : 
    1222                 :            : ::boost::shared_ptr<MetadatableClipboard>
    1223                 :          6 : XmlIdRegistryClipboard::CreateClipboard(const bool i_isInContent)
    1224                 :            : {
    1225                 :            :     OSL_TRACE("CreateClipboard:");
    1226                 :            : 
    1227                 :            :     return ::boost::shared_ptr<MetadatableClipboard>(
    1228         [ +  - ]:          6 :         new MetadatableClipboard(i_isInContent) );
    1229                 :            : }
    1230                 :            : 
    1231                 :            : MetadatableClipboard &
    1232                 :          6 : XmlIdRegistryClipboard::RegisterCopyClipboard(Metadatable & i_rCopy,
    1233                 :            :     beans::StringPair const & i_rReference,
    1234                 :            :     const bool i_isLatent)
    1235                 :            : {
    1236                 :            :     OSL_TRACE("RegisterCopyClipboard: %p -> "/*"%p"*/"(%s#%s) (%d)\n",
    1237                 :            :         /*&i_rSource,*/ &i_rCopy,
    1238                 :            :         ::rtl::OUStringToOString(i_rReference.First,
    1239                 :            :             RTL_TEXTENCODING_UTF8).getStr(),
    1240                 :            :         ::rtl::OUStringToOString(i_rReference.Second,
    1241                 :            :             RTL_TEXTENCODING_UTF8).getStr(),
    1242                 :            :         i_isLatent);
    1243                 :            : 
    1244                 :            :     // N.B.: when copying to the clipboard, the selection is always inserted
    1245                 :            :     //       into the body, even if the source is a header/footer!
    1246                 :            :     //       so we do not check whether the stream is right in this function
    1247                 :            : 
    1248 [ +  - ][ -  + ]:          6 :     if (!isValidXmlId(i_rReference.First, i_rReference.Second))
    1249                 :            :     {
    1250                 :            :         throw lang::IllegalArgumentException(::rtl::OUString(
    1251 [ #  # ][ #  # ]:          0 :             "illegal XmlId"), 0, 0);
    1252                 :            :     }
    1253                 :            : 
    1254         [ +  + ]:          6 :     if (!i_isLatent)
    1255                 :            :     {
    1256                 :            :         // this should succeed assuming clipboard has a single source document
    1257                 :            :         const bool success( m_pImpl->TryInsertMetadatable(i_rCopy,
    1258         [ +  - ]:          3 :                 i_rReference.First, i_rReference.Second) );
    1259                 :            :         OSL_ENSURE(success, "RegisterCopyClipboard: TryInsert failed?");
    1260                 :            :         (void) success;
    1261                 :            :     }
    1262                 :            :     const ::boost::shared_ptr<MetadatableClipboard> pLink(
    1263 [ +  - ][ +  - ]:          6 :         CreateClipboard( isContentFile(i_rReference.First)) );
    1264                 :          6 :     m_pImpl->m_XmlIdReverseMap.insert(::std::make_pair(&i_rCopy,
    1265 [ +  - ][ +  - ]:         12 :         RMapEntry(i_rReference.First, i_rReference.Second, pLink)));
           [ +  -  +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1266         [ +  - ]:          6 :     return *pLink.get();
    1267                 :            : }
    1268                 :            : 
    1269                 :            : MetadatableClipboard const*
    1270                 :          6 : XmlIdRegistryClipboard::SourceLink(Metadatable const& i_rObject)
    1271                 :            : {
    1272                 :          6 :     ::rtl::OUString path;
    1273                 :          6 :     ::rtl::OUString idref;
    1274                 :          6 :     const MetadatableClipboard * pLink( 0 );
    1275         [ +  - ]:          6 :     m_pImpl->LookupXmlId(i_rObject, path, idref, pLink);
    1276                 :          6 :     return pLink;
    1277                 :            : }
    1278                 :            : 
    1279                 :            : 
    1280                 :            : //=============================================================================
    1281                 :            : // Metadatable mixin
    1282                 :            : 
    1283                 :            : 
    1284                 :      18925 : Metadatable::~Metadatable()
    1285                 :            : {
    1286         [ +  - ]:      18925 :     RemoveMetadataReference();
    1287         [ -  + ]:      18925 : }
    1288                 :            : 
    1289                 :      20236 : void Metadatable::RemoveMetadataReference()
    1290                 :            : {
    1291                 :            :     try
    1292                 :            :     {
    1293         [ +  + ]:      20236 :         if (m_pReg)
    1294                 :            :         {
    1295         [ +  - ]:        379 :             m_pReg->UnregisterMetadatable( *this );
    1296         [ +  - ]:        379 :             m_pReg->RemoveXmlIdForElement( *this );
    1297                 :        379 :             m_pReg = 0;
    1298                 :            :         }
    1299                 :            :     }
    1300                 :          0 :     catch (const uno::Exception &)
    1301                 :            :     {
    1302                 :            :         OSL_FAIL("Metadatable::RemoveMetadataReference: exception");
    1303                 :            :     }
    1304         [ #  # ]:      20236 : }
    1305                 :            : 
    1306                 :            : // ::com::sun::star::rdf::XMetadatable:
    1307                 :            : beans::StringPair
    1308                 :       5579 : Metadatable::GetMetadataReference() const
    1309                 :            : {
    1310         [ +  + ]:       5579 :     if (m_pReg)
    1311                 :            :     {
    1312                 :       1366 :         return m_pReg->GetXmlIdForElement(*this);
    1313                 :            :     }
    1314                 :       5579 :     return beans::StringPair();
    1315                 :            : }
    1316                 :            : 
    1317                 :            : void
    1318                 :        332 : Metadatable::SetMetadataReference(
    1319                 :            :     const ::com::sun::star::beans::StringPair & i_rReference)
    1320                 :            : {
    1321         [ +  + ]:        332 :     if (i_rReference.Second.isEmpty())
    1322                 :            :     {
    1323                 :          3 :         RemoveMetadataReference();
    1324                 :            :     }
    1325                 :            :     else
    1326                 :            :     {
    1327                 :        329 :         ::rtl::OUString streamName( i_rReference.First );
    1328         [ +  + ]:        329 :         if (streamName.isEmpty())
    1329                 :            :         {
    1330                 :            :             // handle empty stream name as auto-detect.
    1331                 :            :             // necessary for importing flat file format.
    1332                 :            :             streamName = ::rtl::OUString::createFromAscii(
    1333 [ +  - ][ +  + ]:          6 :                             IsInContent() ? s_content : s_styles );
    1334                 :            :         }
    1335 [ +  - ][ +  - ]:        329 :         XmlIdRegistry & rReg( dynamic_cast<XmlIdRegistry&>( GetRegistry() ) );
    1336 [ +  - ][ +  + ]:        329 :         if (rReg.TryRegisterMetadatable(*this, streamName, i_rReference.Second))
    1337                 :            :         {
    1338                 :        323 :             m_pReg = &rReg;
    1339                 :            :         }
    1340                 :            :         else
    1341                 :            :         {
    1342                 :            :             throw lang::IllegalArgumentException(
    1343                 :            :                 ::rtl::OUString("Metadatable::"
    1344 [ +  - ][ +  - ]:          6 :                     "SetMetadataReference: argument is invalid"), /*this*/0, 0);
    1345                 :        329 :         }
    1346                 :            :     }
    1347                 :        326 : }
    1348                 :            : 
    1349                 :        131 : void Metadatable::EnsureMetadataReference()
    1350                 :            : {
    1351                 :            :     XmlIdRegistry& rReg(
    1352 [ +  + ][ +  - ]:        131 :         m_pReg ? *m_pReg : dynamic_cast<XmlIdRegistry&>( GetRegistry() ) );
    1353                 :        131 :     rReg.RegisterMetadatableAndCreateID( *this );
    1354                 :        131 :     m_pReg = &rReg;
    1355                 :        131 : }
    1356                 :            : 
    1357                 :          6 : const ::sfx2::IXmlIdRegistry& GetRegistryConst(Metadatable const& i_rObject)
    1358                 :            : {
    1359                 :          6 :     return const_cast< Metadatable& >( i_rObject ).GetRegistry();
    1360                 :            : }
    1361                 :            : 
    1362                 :            : void
    1363                 :       1225 : Metadatable::RegisterAsCopyOf(Metadatable const & i_rSource,
    1364                 :            :     const bool i_bCopyPrecedesSource)
    1365                 :            : {
    1366                 :            :     OSL_ENSURE(typeid(*this) == typeid(i_rSource)
    1367                 :            :         || typeid(i_rSource) == typeid(MetadatableUndo)
    1368                 :            :         || typeid(*this)     == typeid(MetadatableUndo)
    1369                 :            :         || typeid(i_rSource) == typeid(MetadatableClipboard)
    1370                 :            :         || typeid(*this)     == typeid(MetadatableClipboard),
    1371                 :            :         "RegisterAsCopyOf element with different class?");
    1372                 :            :     OSL_ENSURE(!this->m_pReg, "RegisterAsCopyOf called on element with XmlId?");
    1373                 :            : 
    1374         [ -  + ]:       1225 :     if (this->m_pReg)
    1375                 :            :     {
    1376                 :          0 :         RemoveMetadataReference();
    1377                 :            :     }
    1378                 :            : 
    1379                 :            :     try
    1380                 :            :     {
    1381         [ +  + ]:       1225 :         if (i_rSource.m_pReg)
    1382                 :            :         {
    1383                 :            :             XmlIdRegistry & rReg(
    1384 [ +  - ][ +  - ]:         18 :                 dynamic_cast<XmlIdRegistry&>( GetRegistry() ) );
    1385         [ +  + ]:         18 :             if (i_rSource.m_pReg == &rReg)
    1386                 :            :             {
    1387                 :            :                 OSL_ENSURE(!IsInClipboard(),
    1388                 :            :                     "RegisterAsCopy: both in clipboard?");
    1389 [ +  - ][ +  - ]:          6 :                 if (!IsInClipboard())
    1390                 :            :                 {
    1391                 :            :                     XmlIdRegistryDocument & rRegDoc(
    1392         [ +  - ]:          6 :                         dynamic_cast<XmlIdRegistryDocument&>( rReg ) );
    1393                 :            :                     rRegDoc.RegisterCopy(i_rSource, *this,
    1394         [ +  - ]:          6 :                         i_bCopyPrecedesSource);
    1395                 :          6 :                     this->m_pReg = &rRegDoc;
    1396                 :            :                 }
    1397                 :          6 :                 return;
    1398                 :            :             }
    1399                 :            :             // source is in different document
    1400                 :            :             XmlIdRegistryDocument  * pRegDoc(
    1401         [ -  + ]:         12 :                 dynamic_cast<XmlIdRegistryDocument *>(&rReg) );
    1402                 :            :             XmlIdRegistryClipboard * pRegClp(
    1403         [ -  + ]:         12 :                 dynamic_cast<XmlIdRegistryClipboard*>(&rReg) );
    1404                 :            : 
    1405         [ +  + ]:         12 :             if (pRegClp)
    1406                 :            :             {
    1407                 :            :                 beans::StringPair SourceRef(
    1408         [ +  - ]:          6 :                     i_rSource.m_pReg->GetXmlIdForElement(i_rSource) );
    1409                 :          6 :                 bool isLatent( SourceRef.Second.isEmpty() );
    1410                 :            :                 XmlIdRegistryDocument * pSourceRegDoc(
    1411         [ -  + ]:          6 :                     dynamic_cast<XmlIdRegistryDocument*>(i_rSource.m_pReg) );
    1412                 :            :                 OSL_ENSURE(pSourceRegDoc, "RegisterAsCopyOf: 2 clipboards?");
    1413         [ -  + ]:          6 :                 if (!pSourceRegDoc) return;
    1414                 :            :                 // this is a copy _to_ the clipboard
    1415         [ +  + ]:          6 :                 if (isLatent)
    1416                 :            :                 {
    1417                 :            :                     pSourceRegDoc->LookupXmlId(i_rSource,
    1418         [ +  - ]:          3 :                         SourceRef.First, SourceRef.Second);
    1419                 :            :                 }
    1420                 :            :                 Metadatable & rLink(
    1421         [ +  - ]:          6 :                     pRegClp->RegisterCopyClipboard(*this, SourceRef, isLatent));
    1422                 :          6 :                 this->m_pReg = pRegClp;
    1423                 :            :                 // register as copy in the non-clipboard registry
    1424                 :            :                 pSourceRegDoc->RegisterCopy(i_rSource, rLink,
    1425         [ +  - ]:          6 :                     false); // i_bCopyPrecedesSource);
    1426 [ +  - ][ #  # ]:          6 :                 rLink.m_pReg = pSourceRegDoc;
    1427                 :            :             }
    1428         [ +  - ]:          6 :             else if (pRegDoc)
    1429                 :            :             {
    1430                 :            :                 XmlIdRegistryClipboard * pSourceRegClp(
    1431         [ -  + ]:          6 :                     dynamic_cast<XmlIdRegistryClipboard*>(i_rSource.m_pReg) );
    1432                 :            :                 OSL_ENSURE(pSourceRegClp,
    1433                 :            :                     "RegisterAsCopyOf: 2 non-clipboards?");
    1434         [ -  + ]:          6 :                 if (!pSourceRegClp) return;
    1435                 :            :                 const MetadatableClipboard * pLink(
    1436         [ +  - ]:          6 :                     pSourceRegClp->SourceLink(i_rSource) );
    1437                 :            :                 // may happen if src got its id via UNO call
    1438         [ -  + ]:          6 :                 if (!pLink) return;
    1439                 :            :                 // only register copy if clipboard content is from this SwDoc!
    1440 [ +  - ][ +  - ]:          6 :                 if (pLink && (&GetRegistryConst(*pLink) == pRegDoc))
         [ +  - ][ +  - ]
    1441                 :            :                 {
    1442                 :            :                     // this is a copy _from_ the clipboard; check if the
    1443                 :            :                     // element is still in the same stream
    1444                 :            :                     // N.B.: we check the stream of pLink, not of i_rSource!
    1445         [ +  - ]:          6 :                     bool srcInContent( pLink->IsInContent() );
    1446         [ +  - ]:          6 :                     bool tgtInContent( this->IsInContent() );
    1447         [ +  - ]:          6 :                     if (srcInContent == tgtInContent)
    1448                 :            :                     {
    1449                 :            :                         pRegDoc->RegisterCopy(*pLink, *this,
    1450         [ +  - ]:          6 :                             true); // i_bCopyPrecedesSource);
    1451                 :       1225 :                         this->m_pReg = pRegDoc;
    1452                 :            :                     }
    1453                 :            :                     // otherwise: stream change! do not register!
    1454                 :            :                 }
    1455                 :            :             }
    1456                 :            :             else
    1457                 :            :             {
    1458                 :            :                 OSL_FAIL("neither RegDoc nor RegClp cannot happen");
    1459                 :            :             }
    1460                 :            :         }
    1461                 :            :     }
    1462                 :          0 :     catch (const uno::Exception &)
    1463                 :            :     {
    1464                 :            :         OSL_FAIL("Metadatable::RegisterAsCopyOf: exception");
    1465                 :            :     }
    1466                 :            : }
    1467                 :            : 
    1468                 :       2740 : ::boost::shared_ptr<MetadatableUndo> Metadatable::CreateUndo() const
    1469                 :            : {
    1470                 :            :     OSL_ENSURE(!IsInUndo(), "CreateUndo called for object in undo?");
    1471                 :            :     OSL_ENSURE(!IsInClipboard(), "CreateUndo called for object in clipboard?");
    1472                 :            :     try
    1473                 :            :     {
    1474 [ +  - ][ +  - ]:       2740 :         if (!IsInClipboard() && !IsInUndo() && m_pReg)
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
    1475                 :            :         {
    1476                 :            :             XmlIdRegistryDocument * pRegDoc(
    1477         [ #  # ]:          0 :                 dynamic_cast<XmlIdRegistryDocument*>( m_pReg ) );
    1478                 :            :             ::boost::shared_ptr<MetadatableUndo> pUndo(
    1479         [ #  # ]:          0 :                 pRegDoc->CreateUndo(*this) );
    1480         [ #  # ]:          0 :             pRegDoc->RegisterCopy(*this, *pUndo, false);
    1481                 :          0 :             pUndo->m_pReg = pRegDoc;
    1482 [ #  # ][ #  # ]:          0 :             return pUndo;
                 [ #  # ]
    1483                 :            :         }
    1484                 :            :     }
    1485                 :          0 :     catch (const uno::Exception &)
    1486                 :            :     {
    1487                 :            :         OSL_FAIL("Metadatable::CreateUndo: exception");
    1488                 :            :     }
    1489                 :       2740 :     return ::boost::shared_ptr<MetadatableUndo>();
    1490                 :            : }
    1491                 :            : 
    1492                 :        182 : ::boost::shared_ptr<MetadatableUndo> Metadatable::CreateUndoForDelete()
    1493                 :            : {
    1494                 :        182 :     ::boost::shared_ptr<MetadatableUndo> const pUndo( CreateUndo() );
    1495         [ +  - ]:        182 :     RemoveMetadataReference();
    1496                 :        182 :     return pUndo;
    1497                 :            : }
    1498                 :            : 
    1499                 :          0 : void Metadatable::RestoreMetadata(
    1500                 :            :     ::boost::shared_ptr<MetadatableUndo> const& i_pUndo)
    1501                 :            : {
    1502                 :            :     OSL_ENSURE(!IsInUndo(), "RestoreMetadata called for object in undo?");
    1503                 :            :     OSL_ENSURE(!IsInClipboard(),
    1504                 :            :         "RestoreMetadata called for object in clipboard?");
    1505 [ #  # ][ #  # ]:          0 :     if (IsInClipboard() || IsInUndo()) return;
                 [ #  # ]
    1506                 :          0 :     RemoveMetadataReference();
    1507         [ #  # ]:          0 :     if (i_pUndo)
    1508                 :            :     {
    1509                 :          0 :         this->RegisterAsCopyOf(*i_pUndo, true);
    1510                 :            :     }
    1511                 :            : }
    1512                 :            : 
    1513                 :            : void
    1514                 :        726 : Metadatable::JoinMetadatable(Metadatable const & i_rOther,
    1515                 :            :     const bool i_isMergedEmpty, const bool i_isOtherEmpty)
    1516                 :            : {
    1517                 :            :     OSL_ENSURE(!IsInUndo(), "JoinMetadatables called for object in undo?");
    1518                 :            :     OSL_ENSURE(!IsInClipboard(),
    1519                 :            :         "JoinMetadatables called for object in clipboard?");
    1520 [ +  - ][ -  + ]:        726 :     if (IsInClipboard() || IsInUndo()) return;
                 [ -  + ]
    1521                 :            : 
    1522 [ +  + ][ +  + ]:        726 :     if (i_isOtherEmpty && !i_isMergedEmpty)
    1523                 :            :     {
    1524                 :            :         // other is empty, thus loses => nothing to do
    1525                 :        471 :         return;
    1526                 :            :     }
    1527 [ +  + ][ +  + ]:        255 :     if (i_isMergedEmpty && !i_isOtherEmpty)
    1528                 :            :     {
    1529                 :          2 :         this->RemoveMetadataReference();
    1530                 :          2 :         this->RegisterAsCopyOf(i_rOther, true);
    1531                 :          2 :         return;
    1532                 :            :     }
    1533                 :            : 
    1534         [ +  - ]:        253 :     if (!i_rOther.m_pReg)
    1535                 :            :     {
    1536                 :            :         // other doesn't have xmlid, thus loses => nothing to do
    1537                 :        253 :         return;
    1538                 :            :     }
    1539         [ #  # ]:          0 :     if (!m_pReg)
    1540                 :            :     {
    1541                 :          0 :         this->RegisterAsCopyOf(i_rOther, true);
    1542                 :            :         // assumption: i_rOther will be deleted, so don't unregister it here
    1543                 :          0 :         return;
    1544                 :            :     }
    1545                 :            :     try
    1546                 :            :     {
    1547                 :            :         XmlIdRegistryDocument * pRegDoc(
    1548         [ #  # ]:          0 :             dynamic_cast<XmlIdRegistryDocument*>( m_pReg ) );
    1549                 :            :         OSL_ENSURE(pRegDoc, "JoinMetadatable: no pRegDoc?");
    1550         [ #  # ]:          0 :         if (pRegDoc)
    1551                 :            :         {
    1552 [ #  # ][ #  # ]:        726 :             pRegDoc->JoinMetadatables(*this, i_rOther);
    1553                 :            :         }
    1554                 :            :     }
    1555                 :          0 :     catch (const uno::Exception &)
    1556                 :            :     {
    1557                 :            :         OSL_FAIL("Metadatable::JoinMetadatable: exception");
    1558                 :            :     }
    1559                 :            : }
    1560                 :            : 
    1561                 :            : 
    1562                 :            : //=============================================================================
    1563                 :            : // XMetadatable mixin
    1564                 :            : 
    1565                 :            : // ::com::sun::star::rdf::XNode:
    1566                 :        194 : ::rtl::OUString SAL_CALL MetadatableMixin::getStringValue()
    1567                 :            :     throw (::com::sun::star::uno::RuntimeException)
    1568                 :            : {
    1569         [ +  - ]:        194 :     return getNamespace() + getLocalName();
    1570                 :            : }
    1571                 :            : 
    1572                 :            : // ::com::sun::star::rdf::XURI:
    1573                 :        194 : ::rtl::OUString SAL_CALL MetadatableMixin::getLocalName()
    1574                 :            :     throw (::com::sun::star::uno::RuntimeException)
    1575                 :            : {
    1576         [ +  - ]:        194 :     SolarMutexGuard aGuard;
    1577         [ +  - ]:        194 :     beans::StringPair mdref( getMetadataReference() );
    1578         [ +  + ]:        194 :     if (mdref.Second.isEmpty())
    1579                 :            :     {
    1580         [ +  - ]:          2 :         ensureMetadataReference(); // N.B.: side effect!
    1581         [ +  - ]:          2 :         mdref = getMetadataReference();
    1582                 :            :     }
    1583                 :        194 :     ::rtl::OUStringBuffer buf;
    1584         [ +  - ]:        194 :     buf.append(mdref.First);
    1585         [ +  - ]:        194 :     buf.append(static_cast<sal_Unicode>('#'));
    1586         [ +  - ]:        194 :     buf.append(mdref.Second);
    1587 [ +  - ][ +  - ]:        194 :     return buf.makeStringAndClear();
    1588                 :            : }
    1589                 :            : 
    1590                 :        194 : ::rtl::OUString SAL_CALL MetadatableMixin::getNamespace()
    1591                 :            :     throw (::com::sun::star::uno::RuntimeException)
    1592                 :            : {
    1593         [ +  - ]:        194 :     SolarMutexGuard aGuard;
    1594         [ +  - ]:        194 :     const uno::Reference< frame::XModel > xModel( GetModel() );
    1595         [ +  - ]:        194 :     const uno::Reference< rdf::XURI > xDMA( xModel, uno::UNO_QUERY_THROW );
    1596 [ +  - ][ +  - ]:        194 :     return xDMA->getStringValue();
                 [ +  - ]
    1597                 :            : }
    1598                 :            : 
    1599                 :            : // ::com::sun::star::rdf::XMetadatable:
    1600                 :            : beans::StringPair SAL_CALL
    1601                 :       5462 : MetadatableMixin::getMetadataReference()
    1602                 :            : throw (uno::RuntimeException)
    1603                 :            : {
    1604         [ +  - ]:       5462 :     SolarMutexGuard aGuard;
    1605                 :            : 
    1606         [ +  - ]:       5462 :     Metadatable *const pObject( GetCoreObject() );
    1607         [ -  + ]:       5462 :     if (!pObject)
    1608                 :            :     {
    1609                 :            :         throw uno::RuntimeException(
    1610                 :            :             ::rtl::OUString(
    1611                 :            :                 "MetadatableMixin: cannot get core object; not inserted?"),
    1612 [ #  # ][ #  # ]:          0 :             *this);
    1613                 :            :     }
    1614 [ +  - ][ +  - ]:       5462 :     return pObject->GetMetadataReference();
    1615                 :            : }
    1616                 :            : 
    1617                 :            : void SAL_CALL
    1618                 :        302 : MetadatableMixin::setMetadataReference(
    1619                 :            :     const beans::StringPair & i_rReference)
    1620                 :            : throw (uno::RuntimeException, lang::IllegalArgumentException)
    1621                 :            : {
    1622         [ +  - ]:        302 :     SolarMutexGuard aGuard;
    1623                 :            : 
    1624         [ +  - ]:        302 :     Metadatable *const pObject( GetCoreObject() );
    1625         [ -  + ]:        302 :     if (!pObject)
    1626                 :            :     {
    1627                 :            :         throw uno::RuntimeException(
    1628                 :            :             ::rtl::OUString(
    1629                 :            :                 "MetadatableMixin: cannot get core object; not inserted?"),
    1630 [ #  # ][ #  # ]:          0 :             *this);
    1631                 :            :     }
    1632 [ +  - ][ +  - ]:        302 :     return pObject->SetMetadataReference(i_rReference);
    1633                 :            : }
    1634                 :            : 
    1635                 :        110 : void SAL_CALL MetadatableMixin::ensureMetadataReference()
    1636                 :            : throw (uno::RuntimeException)
    1637                 :            : {
    1638         [ +  - ]:        110 :     SolarMutexGuard aGuard;
    1639                 :            : 
    1640         [ +  - ]:        110 :     Metadatable *const pObject( GetCoreObject() );
    1641         [ -  + ]:        110 :     if (!pObject)
    1642                 :            :     {
    1643                 :            :         throw uno::RuntimeException(
    1644                 :            :             ::rtl::OUString(
    1645                 :            :                 "MetadatableMixin: cannot get core object; not inserted?"),
    1646 [ #  # ][ #  # ]:          0 :             *this);
    1647                 :            :     }
    1648 [ +  - ][ +  - ]:        110 :     return pObject->EnsureMetadataReference();
    1649                 :            : }
    1650                 :            : 
    1651 [ +  - ][ +  - ]:        735 : } // namespace sfx2
    1652                 :            : 
    1653                 :            : 
    1654                 :            : //=============================================================================
    1655                 :            : 
    1656                 :            : #if OSL_DEBUG_LEVEL > 1
    1657                 :            : 
    1658                 :            : #include <stdio.h>
    1659                 :            : 
    1660                 :            : static void dump(sfx2::XmlIdList_t * pList)
    1661                 :            : #ifdef GCC
    1662                 :            : __attribute__ ((unused))
    1663                 :            : #endif
    1664                 :            : ;
    1665                 :            : static void dump(sfx2::XmlIdList_t * pList)
    1666                 :            : {
    1667                 :            :     fprintf(stderr, "\nXmlIdList(%p):  ", pList);
    1668                 :            :     for (sfx2::XmlIdList_t::iterator i = pList->begin(); i != pList->end(); ++i)
    1669                 :            :     {
    1670                 :            :         fprintf(stderr, "%p  ", *i);
    1671                 :            :     }
    1672                 :            :     fprintf(stderr, "\n");
    1673                 :            : }
    1674                 :            : 
    1675                 :            : #endif
    1676                 :            : 
    1677                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10