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 31 32 #include "XMLIndexTOCContext.hxx" 33 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 34 #include <com/sun/star/lang/IllegalArgumentException.hpp> 35 #include <com/sun/star/uno/XInterface.hpp> 36 #include <com/sun/star/text/XTextContent.hpp> 37 #include <com/sun/star/text/XTextSection.hpp> 38 #include <com/sun/star/text/XRelativeTextContentInsert.hpp> 39 #include <com/sun/star/beans/XPropertySet.hpp> 40 #include "XMLIndexTOCSourceContext.hxx" 41 #include "XMLIndexObjectSourceContext.hxx" 42 #include "XMLIndexAlphabeticalSourceContext.hxx" 43 #include "XMLIndexUserSourceContext.hxx" 44 #include "XMLIndexBibliographySourceContext.hxx" 45 #include "XMLIndexTableSourceContext.hxx" 46 #include "XMLIndexIllustrationSourceContext.hxx" 47 #include "XMLIndexBodyContext.hxx" 48 #include <xmloff/xmlictxt.hxx> 49 #include <xmloff/xmlimp.hxx> 50 #include <xmloff/txtimp.hxx> 51 #include <xmloff/nmspmap.hxx> 52 #include "xmloff/xmlnmspe.hxx" 53 #include <xmloff/xmltoken.hxx> 54 #include <xmloff/prstylei.hxx> 55 #include "xmloff/xmlerror.hxx" 56 #include <xmloff/xmluconv.hxx> 57 #include <rtl/ustring.hxx> 58 59 60 using namespace ::com::sun::star::uno; 61 using namespace ::com::sun::star::text; 62 using namespace ::xmloff::token; 63 64 using ::rtl::OUString; 65 using ::com::sun::star::beans::XPropertySet; 66 using ::com::sun::star::uno::Reference; 67 using ::com::sun::star::xml::sax::XAttributeList; 68 using ::com::sun::star::lang::XMultiServiceFactory; 69 using ::com::sun::star::lang::IllegalArgumentException; 70 71 72 TYPEINIT1(XMLIndexTOCContext, SvXMLImportContext); 73 74 static const sal_Char* aIndexServiceMap[] = 75 { 76 "com.sun.star.text.ContentIndex", 77 "com.sun.star.text.DocumentIndex", 78 "com.sun.star.text.TableIndex", 79 "com.sun.star.text.ObjectIndex", 80 "com.sun.star.text.Bibliography", 81 "com.sun.star.text.UserIndex", 82 "com.sun.star.text.IllustrationsIndex" 83 }; 84 85 static const XMLTokenEnum aIndexSourceElementMap[] = 86 { 87 XML_TABLE_OF_CONTENT_SOURCE, 88 XML_ALPHABETICAL_INDEX_SOURCE, 89 XML_TABLE_INDEX_SOURCE, 90 XML_OBJECT_INDEX_SOURCE, 91 XML_BIBLIOGRAPHY_SOURCE, 92 XML_USER_INDEX_SOURCE, 93 XML_ILLUSTRATION_INDEX_SOURCE 94 }; 95 96 SvXMLEnumMapEntry __READONLY_DATA aIndexTypeMap[] = 97 { 98 { XML_TABLE_OF_CONTENT, TEXT_INDEX_TOC }, 99 { XML_ALPHABETICAL_INDEX, TEXT_INDEX_ALPHABETICAL }, 100 { XML_TABLE_INDEX, TEXT_INDEX_TABLE }, 101 { XML_OBJECT_INDEX, TEXT_INDEX_OBJECT }, 102 { XML_BIBLIOGRAPHY, TEXT_INDEX_BIBLIOGRAPHY }, 103 { XML_USER_INDEX, TEXT_INDEX_USER }, 104 { XML_ILLUSTRATION_INDEX, TEXT_INDEX_ILLUSTRATION }, 105 { XML_TOKEN_INVALID, 0 } 106 }; 107 108 109 XMLIndexTOCContext::XMLIndexTOCContext( 110 SvXMLImport& rImport, 111 sal_uInt16 nPrfx, 112 const OUString& rLocalName ) 113 : SvXMLImportContext(rImport, nPrfx, rLocalName) 114 , sTitle(RTL_CONSTASCII_USTRINGPARAM("Title")) 115 , sIsProtected(RTL_CONSTASCII_USTRINGPARAM("IsProtected")) 116 , sName(RTL_CONSTASCII_USTRINGPARAM("Name")) 117 , bValid(sal_False) 118 { 119 if (XML_NAMESPACE_TEXT == nPrfx) 120 { 121 sal_uInt16 nTmp; 122 if (SvXMLUnitConverter::convertEnum(nTmp, rLocalName, aIndexTypeMap)) 123 { 124 // check for array index: 125 OSL_ENSURE(nTmp < (sizeof(aIndexServiceMap)/sizeof(sal_Char*)), "index out of range"); 126 OSL_ENSURE(sizeof(aIndexServiceMap) == 127 sizeof(aIndexSourceElementMap), 128 "service and source element maps must be same size"); 129 130 eIndexType = static_cast<IndexTypeEnum>(nTmp); 131 bValid = sal_True; 132 } 133 } 134 } 135 136 XMLIndexTOCContext::~XMLIndexTOCContext() 137 { 138 } 139 140 void XMLIndexTOCContext::StartElement( 141 const Reference<XAttributeList> & xAttrList) 142 { 143 if (bValid) 144 { 145 // find text:style-name attribute and set section style 146 // find text:protected and set value 147 // find text:name and set value (if not empty) 148 sal_Int16 nCount = xAttrList->getLength(); 149 sal_Bool bProtected = sal_False; 150 OUString sIndexName; 151 OUString sXmlId; 152 XMLPropStyleContext* pStyle(NULL); 153 for(sal_Int16 nAttr = 0; nAttr < nCount; nAttr++) 154 { 155 OUString sLocalName; 156 sal_uInt16 nPrefix = GetImport().GetNamespaceMap(). 157 GetKeyByAttrName( xAttrList->getNameByIndex(nAttr), 158 &sLocalName ); 159 if ( XML_NAMESPACE_TEXT == nPrefix) 160 { 161 if ( IsXMLToken( sLocalName, XML_STYLE_NAME ) ) 162 { 163 pStyle = GetImport().GetTextImport()->FindSectionStyle( 164 xAttrList->getValueByIndex(nAttr)); 165 } 166 else if ( IsXMLToken( sLocalName, XML_PROTECTED ) ) 167 { 168 sal_Bool bTmp; 169 if ( SvXMLUnitConverter::convertBool( 170 bTmp, xAttrList->getValueByIndex(nAttr) ) ) 171 { 172 bProtected = bTmp; 173 } 174 } 175 else if ( IsXMLToken( sLocalName, XML_NAME ) ) 176 { 177 sIndexName = xAttrList->getValueByIndex(nAttr); 178 } 179 } 180 else if ( XML_NAMESPACE_XML == nPrefix) 181 { 182 if ( IsXMLToken( sLocalName, XML_ID ) ) 183 { 184 sXmlId = xAttrList->getValueByIndex(nAttr); 185 } 186 } 187 } 188 189 // create table of content (via MultiServiceFactory) 190 Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(), 191 UNO_QUERY); 192 if( xFactory.is() ) 193 { 194 Reference<XInterface> xIfc = 195 xFactory->createInstance( 196 OUString::createFromAscii(aIndexServiceMap[eIndexType])); 197 if( xIfc.is() ) 198 { 199 // get Property set 200 Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY); 201 xTOCPropertySet = xPropSet; 202 203 // insert section 204 // a) insert section 205 // The inserted index consists of an empty paragraph 206 // only, as well as an empty paragraph *after* the index 207 // b) insert marker after index, and put Cursor inside of the 208 // index 209 210 // preliminaries 211 #ifndef DBG_UTIL 212 OUString sMarker(RTL_CONSTASCII_USTRINGPARAM(" ")); 213 #else 214 OUString sMarker(RTL_CONSTASCII_USTRINGPARAM("Y")); 215 #endif 216 UniReference<XMLTextImportHelper> rImport = 217 GetImport().GetTextImport(); 218 219 // a) insert index 220 Reference<XTextContent> xTextContent(xIfc, UNO_QUERY); 221 try 222 { 223 GetImport().GetTextImport()->InsertTextContent( 224 xTextContent); 225 } 226 catch( IllegalArgumentException e ) 227 { 228 // illegal argument? Then we can't accept indices here! 229 Sequence<OUString> aSeq(1); 230 aSeq[0] = GetLocalName(); 231 GetImport().SetError( 232 XMLERROR_FLAG_ERROR | XMLERROR_NO_INDEX_ALLOWED_HERE, 233 aSeq, e.Message, NULL ); 234 235 // set bValid to false, and return prematurely 236 bValid = false; 237 return; 238 } 239 240 // xml:id for RDF metadata 241 GetImport().SetXmlId(xIfc, sXmlId); 242 243 // b) insert marker and move cursor 244 rImport->InsertString(sMarker); 245 rImport->GetCursor()->goLeft(2, sal_False); 246 } 247 } 248 249 // finally, check for redlines that should start at 250 // the section start node 251 if( bValid ) 252 GetImport().GetTextImport()-> 253 RedlineAdjustStartNodeCursor(sal_True); 254 255 if (pStyle != NULL) 256 { 257 pStyle->FillPropertySet( xTOCPropertySet ); 258 } 259 260 Any aAny; 261 aAny.setValue( &bProtected, ::getBooleanCppuType() ); 262 xTOCPropertySet->setPropertyValue( sIsProtected, aAny ); 263 264 if (sIndexName.getLength() > 0) 265 { 266 aAny <<= sIndexName; 267 xTOCPropertySet->setPropertyValue( sName, aAny ); 268 } 269 } 270 } 271 272 void XMLIndexTOCContext::EndElement() 273 { 274 // complete import of index by removing the markers (if the index 275 // was actually inserted, that is) 276 if( bValid ) 277 { 278 // preliminaries 279 OUString sEmpty; 280 UniReference<XMLTextImportHelper> rHelper= GetImport().GetTextImport(); 281 282 // get rid of last paragraph (unless it's the only paragraph) 283 rHelper->GetCursor()->goRight(1, sal_False); 284 if( xBodyContextRef.Is() && 285 ((XMLIndexBodyContext*)&xBodyContextRef)->HasContent() ) 286 { 287 rHelper->GetCursor()->goLeft(1, sal_True); 288 rHelper->GetText()->insertString(rHelper->GetCursorAsRange(), 289 sEmpty, sal_True); 290 } 291 292 // and delete second marker 293 rHelper->GetCursor()->goRight(1, sal_True); 294 rHelper->GetText()->insertString(rHelper->GetCursorAsRange(), 295 sEmpty, sal_True); 296 297 // check for Redlines on our end node 298 GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(sal_False); 299 } 300 } 301 302 SvXMLImportContext* XMLIndexTOCContext::CreateChildContext( 303 sal_uInt16 nPrefix, 304 const OUString& rLocalName, 305 const Reference<XAttributeList> & xAttrList ) 306 { 307 SvXMLImportContext* pContext = NULL; 308 309 if (bValid) 310 { 311 if (XML_NAMESPACE_TEXT == nPrefix) 312 { 313 if ( IsXMLToken( rLocalName, XML_INDEX_BODY ) ) 314 { 315 pContext = new XMLIndexBodyContext(GetImport(), nPrefix, 316 rLocalName); 317 if ( !xBodyContextRef.Is() || 318 !((XMLIndexBodyContext*)&xBodyContextRef)->HasContent() ) 319 { 320 xBodyContextRef = pContext; 321 } 322 } 323 else if (IsXMLToken(rLocalName, aIndexSourceElementMap[eIndexType])) 324 { 325 // instantiate source context for the appropriate index type 326 switch (eIndexType) 327 { 328 case TEXT_INDEX_TOC: 329 pContext = new XMLIndexTOCSourceContext( 330 GetImport(), nPrefix, rLocalName, xTOCPropertySet); 331 break; 332 333 case TEXT_INDEX_OBJECT: 334 pContext = new XMLIndexObjectSourceContext( 335 GetImport(), nPrefix, rLocalName, xTOCPropertySet); 336 break; 337 338 case TEXT_INDEX_ALPHABETICAL: 339 pContext = new XMLIndexAlphabeticalSourceContext( 340 GetImport(), nPrefix, rLocalName, xTOCPropertySet); 341 break; 342 343 case TEXT_INDEX_USER: 344 pContext = new XMLIndexUserSourceContext( 345 GetImport(), nPrefix, rLocalName, xTOCPropertySet); 346 break; 347 348 case TEXT_INDEX_BIBLIOGRAPHY: 349 pContext = new XMLIndexBibliographySourceContext( 350 GetImport(), nPrefix, rLocalName, xTOCPropertySet); 351 break; 352 353 case TEXT_INDEX_TABLE: 354 pContext = new XMLIndexTableSourceContext( 355 GetImport(), nPrefix, rLocalName, xTOCPropertySet); 356 break; 357 358 case TEXT_INDEX_ILLUSTRATION: 359 pContext = new XMLIndexIllustrationSourceContext( 360 GetImport(), nPrefix, rLocalName, xTOCPropertySet); 361 break; 362 363 default: 364 OSL_ENSURE(false, "index type not implemented"); 365 break; 366 } 367 } 368 // else: ignore 369 } 370 // else: no text: namespace -> ignore 371 } 372 // else: not valid -> ignore 373 374 // default: ignore 375 if (pContext == NULL) 376 { 377 pContext = SvXMLImportContext::CreateChildContext(nPrefix, rLocalName, 378 xAttrList); 379 } 380 381 return pContext; 382 } 383