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