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