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