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