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