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> 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> 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> 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> 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> 96 XMLPropertyBackpatcher<A>::~XMLPropertyBackpatcher() 97 { 98 SetDefault(); 99 } 100 101 102 template<class A> 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> 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> 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> 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> 219 XMLTextImportHelper::MakeBackpatcherImpl() 220 { 221 // n.b.: the shared_ptr stores the dtor! 222 return ::boost::shared_ptr<BackpatcherImpl>(new BackpatcherImpl); 223 } 224 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 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 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 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 278 void XMLTextImportHelper::InsertFootnoteID( 279 const OUString& sXMLId, 280 sal_Int16 nAPIId) 281 { 282 GetFootnoteBP().ResolveId(sXMLId, nAPIId); 283 } 284 285 void XMLTextImportHelper::ProcessFootnoteReference( 286 const OUString& sXMLId, 287 const Reference<XPropertySet> & xPropSet) 288 { 289 GetFootnoteBP().SetProperty(xPropSet, sXMLId); 290 } 291 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 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