xref: /trunk/main/xmloff/source/text/XMLPropertyBackpatcher.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/uno/Reference.h>
32 
33 #include <rtl/ustring.hxx>
34 #include <tools/debug.hxx>
35 #include "XMLPropertyBackpatcher.hxx"
36 #include <xmloff/txtimp.hxx>    // XMLTextImportHelper partially implemented here
37 
38 
39 using ::rtl::OUString;
40 using ::std::vector;
41 using ::std::map;
42 using ::com::sun::star::uno::Reference;
43 using ::com::sun::star::uno::Any;
44 using ::com::sun::star::beans::XPropertySet;
45 
46 
47 template<class A>
48 XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
49     const ::rtl::OUString& sPropName)
50 :   sPropertyName(sPropName)
51 ,   bDefaultHandling(sal_False)
52 ,   bPreserveProperty(sal_False)
53 ,   sPreservePropertyName()
54 {
55 }
56 
57 template<class A>
58 XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
59     const OUString& sPropName,
60     const OUString& sPreserveName,
61     sal_Bool bDefault,
62     A aDef)
63 :   sPropertyName(sPropName)
64 ,   bDefaultHandling(bDefault)
65 ,   bPreserveProperty(sPreserveName.getLength()>0)
66 ,   sPreservePropertyName(sPreserveName)
67 ,   aDefault(aDef)
68 {
69 }
70 
71 template<class A>
72 XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
73     const sal_Char* pPropName)
74 :   bDefaultHandling(sal_False)
75 ,   bPreserveProperty(sal_False)
76 {
77     DBG_ASSERT(pPropName != NULL, "need property name");
78     sPropertyName = OUString::createFromAscii(pPropName);
79 }
80 
81 template<class A>
82 XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
83     const sal_Char* pPropName,
84     const sal_Char* pPreservePropName,
85     sal_Bool bDefault,
86     A aDef)
87 :   bDefaultHandling(bDefault)
88 ,   bPreserveProperty(pPreservePropName != NULL)
89 ,   aDefault(aDef)
90 {
91     DBG_ASSERT(pPropName != NULL, "need property name");
92     sPropertyName = OUString::createFromAscii(pPropName);
93     if (pPreservePropName != NULL)
94     {
95         sPreservePropertyName = OUString::createFromAscii(pPreservePropName);
96     }
97 }
98 
99 template<class A>
100 XMLPropertyBackpatcher<A>::~XMLPropertyBackpatcher()
101 {
102     SetDefault();
103 }
104 
105 
106 template<class A>
107 void XMLPropertyBackpatcher<A>::ResolveId(
108     const OUString& sName,
109     A aValue)
110 {
111     // insert ID into ID map
112     aIDMap[sName] = aValue;
113 
114     // backpatch old references, if backpatch list exists
115     if (aBackpatchListMap.count(sName))
116     {
117         // aah, we have a backpatch list!
118         BackpatchListType* pList =
119             (BackpatchListType*)aBackpatchListMap[sName];
120 
121         // a) remove list from list map
122         aBackpatchListMap.erase(sName);
123 
124         // b) for every item, set SequenceNumber
125         //    (and preserve Property, if appropriate)
126         Any aAny;
127         aAny <<= aValue;
128         if (bPreserveProperty)
129         {
130             // preserve version
131             for(BackpatchListType::iterator aIter = pList->begin();
132                 aIter != pList->end();
133                 aIter++)
134             {
135                 Reference<XPropertySet> xProp = (*aIter);
136                 Any aPres = xProp->getPropertyValue(sPreservePropertyName);
137                 xProp->setPropertyValue(sPropertyName, aAny);
138                 xProp->setPropertyValue(sPreservePropertyName, aPres);
139             }
140         }
141         else
142         {
143             // without preserve
144             for(BackpatchListType::iterator aIter = pList->begin();
145                 aIter != pList->end();
146                 aIter++)
147             {
148                 (*aIter)->setPropertyValue(sPropertyName, aAny);
149             }
150         }
151 
152         // c) delete list
153         delete pList;
154     }
155     // else: no backpatch list -> then we're finished
156 }
157 
158 template<class A>
159 void XMLPropertyBackpatcher<A>::SetProperty(
160     const Reference<XPropertySet> & xPropSet,
161     const OUString& sName)
162 {
163     Reference<XPropertySet> xNonConstPropSet(xPropSet);
164     SetProperty(xNonConstPropSet, sName);
165 }
166 
167 template<class A>
168 void XMLPropertyBackpatcher<A>::SetProperty(
169     Reference<XPropertySet> & xPropSet,
170     const OUString& sName)
171 {
172     if (aIDMap.count(sName))
173     {
174         // we know this ID -> set property
175         Any aAny;
176         aAny <<= aIDMap[sName];
177         xPropSet->setPropertyValue(sPropertyName, aAny);
178     }
179     else
180     {
181         // ID unknown -> into backpatch list for later fixup
182         if (! aBackpatchListMap.count(sName))
183         {
184             // create backpatch list for this name
185             BackpatchListType* pTmp = new BackpatchListType() ;
186             aBackpatchListMap[sName] = (void*)pTmp;
187         }
188 
189         // insert footnote
190         ((BackpatchListType*)aBackpatchListMap[sName])->push_back(xPropSet);
191     }
192 }
193 
194 template<class A>
195 void XMLPropertyBackpatcher<A>::SetDefault()
196 {
197     if (bDefaultHandling)
198     {
199         // not implemented yet
200     }
201 }
202 
203 // force instantiation of templates
204 template class XMLPropertyBackpatcher<sal_Int16>;
205 template class XMLPropertyBackpatcher<OUString>;
206 
207 struct SAL_DLLPRIVATE XMLTextImportHelper::BackpatcherImpl
208 {
209     /// backpatcher for references to footnotes and endnotes
210     ::std::auto_ptr< XMLPropertyBackpatcher<sal_Int16> >
211         m_pFootnoteBackpatcher;
212 
213     /// backpatchers for references to sequences
214     ::std::auto_ptr< XMLPropertyBackpatcher<sal_Int16> >
215         m_pSequenceIdBackpatcher;
216 
217     ::std::auto_ptr< XMLPropertyBackpatcher< ::rtl::OUString> >
218         m_pSequenceNameBackpatcher;
219 
220 };
221 
222 ::boost::shared_ptr<XMLTextImportHelper::BackpatcherImpl>
223 XMLTextImportHelper::MakeBackpatcherImpl()
224 {
225     // n.b.: the shared_ptr stores the dtor!
226     return ::boost::shared_ptr<BackpatcherImpl>(new BackpatcherImpl);
227 }
228 
229 static ::rtl::OUString const& GetSequenceNumber()
230 {
231     static ::rtl::OUString s_SequenceNumber(
232         RTL_CONSTASCII_USTRINGPARAM("SequenceNumber"));
233     return s_SequenceNumber;
234 }
235 
236 //
237 // XMLTextImportHelper
238 //
239 // Code from XMLTextImportHelper using the XMLPropertyBackpatcher is
240 // implemented here. The reason is that in the unxsols2 environment,
241 // all templates are instatiated as file local (switch
242 // -instances=static), and thus are not accessible from the outside.
243 //
244 // The previous solution was to force additional instantiation of
245 // XMLPropertyBackpatcher in txtimp.cxx. This solution combines all
246 // usage of the XMLPropertyBackpatcher in XMLPropertyBackpatcher.cxx
247 // instead.
248 //
249 
250 XMLPropertyBackpatcher<sal_Int16>& XMLTextImportHelper::GetFootnoteBP()
251 {
252     if (!m_pBackpatcherImpl->m_pFootnoteBackpatcher.get())
253     {
254         m_pBackpatcherImpl->m_pFootnoteBackpatcher.reset(
255             new XMLPropertyBackpatcher<sal_Int16>(GetSequenceNumber()));
256     }
257     return *m_pBackpatcherImpl->m_pFootnoteBackpatcher;
258 }
259 
260 XMLPropertyBackpatcher<sal_Int16>& XMLTextImportHelper::GetSequenceIdBP()
261 {
262     if (!m_pBackpatcherImpl->m_pSequenceIdBackpatcher.get())
263     {
264         m_pBackpatcherImpl->m_pSequenceIdBackpatcher.reset(
265             new XMLPropertyBackpatcher<sal_Int16>(GetSequenceNumber()));
266     }
267     return *m_pBackpatcherImpl->m_pSequenceIdBackpatcher;
268 }
269 
270 XMLPropertyBackpatcher<OUString>& XMLTextImportHelper::GetSequenceNameBP()
271 {
272     static ::rtl::OUString s_SourceName(
273         RTL_CONSTASCII_USTRINGPARAM("SourceName"));
274     if (!m_pBackpatcherImpl->m_pSequenceNameBackpatcher.get())
275     {
276         m_pBackpatcherImpl->m_pSequenceNameBackpatcher.reset(
277             new XMLPropertyBackpatcher<OUString>(s_SourceName));
278     }
279     return *m_pBackpatcherImpl->m_pSequenceNameBackpatcher;
280 }
281 
282 void XMLTextImportHelper::InsertFootnoteID(
283     const OUString& sXMLId,
284     sal_Int16 nAPIId)
285 {
286     GetFootnoteBP().ResolveId(sXMLId, nAPIId);
287 }
288 
289 void XMLTextImportHelper::ProcessFootnoteReference(
290     const OUString& sXMLId,
291     const Reference<XPropertySet> & xPropSet)
292 {
293     GetFootnoteBP().SetProperty(xPropSet, sXMLId);
294 }
295 
296 void XMLTextImportHelper::InsertSequenceID(
297     const OUString& sXMLId,
298     const OUString& sName,
299     sal_Int16 nAPIId)
300 {
301     GetSequenceIdBP().ResolveId(sXMLId, nAPIId);
302     GetSequenceNameBP().ResolveId(sXMLId, sName);
303 }
304 
305 void XMLTextImportHelper::ProcessSequenceReference(
306     const OUString& sXMLId,
307     const Reference<XPropertySet> & xPropSet)
308 {
309     GetSequenceIdBP().SetProperty(xPropSet, sXMLId);
310     GetSequenceNameBP().SetProperty(xPropSet, sXMLId);
311 }
312 
313