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