LibreOffice Module xmloff (master)  1
XMLIndexTOCContext.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include "XMLIndexTOCContext.hxx"
21 #include <com/sun/star/frame/XModel.hpp>
22 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
23 #include <com/sun/star/lang/IllegalArgumentException.hpp>
24 #include <com/sun/star/uno/XInterface.hpp>
25 #include <com/sun/star/text/XTextContent.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <sax/tools/converter.hxx>
35 #include "XMLIndexBodyContext.hxx"
36 #include <xmloff/xmlictxt.hxx>
37 #include <xmloff/xmlimp.hxx>
38 #include <xmloff/txtimp.hxx>
39 #include <xmloff/nmspmap.hxx>
40 #include <xmloff/xmlnmspe.hxx>
41 #include <xmloff/xmltoken.hxx>
42 #include <xmloff/prstylei.hxx>
43 #include <xmloff/xmlerror.hxx>
44 #include <xmloff/xmluconv.hxx>
45 #include <xmloff/xmlement.hxx>
46 #include <rtl/ustring.hxx>
47 #include <osl/diagnose.h>
48 
49 
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::text;
52 using namespace ::xmloff::token;
53 
54 using ::com::sun::star::beans::XPropertySet;
55 using ::com::sun::star::uno::Reference;
56 using ::com::sun::star::xml::sax::XAttributeList;
57 using ::com::sun::star::lang::XMultiServiceFactory;
58 using ::com::sun::star::lang::IllegalArgumentException;
59 
60 
61 static const char* aIndexServiceMap[] =
62 {
63  "com.sun.star.text.ContentIndex",
64  "com.sun.star.text.DocumentIndex",
65  "com.sun.star.text.TableIndex",
66  "com.sun.star.text.ObjectIndex",
67  "com.sun.star.text.Bibliography",
68  "com.sun.star.text.UserIndex",
69  "com.sun.star.text.IllustrationsIndex"
70 };
71 
73 {
81 };
82 
84 {
93 };
94 
95 
97  sal_uInt16 nPrfx, const OUString& rLocalName)
98  : SvXMLImportContext(rImport, nPrfx, rLocalName)
99  , eIndexType(TEXT_INDEX_UNKNOWN)
100  , bValid(false)
101 {
102  if (XML_NAMESPACE_TEXT == nPrfx)
103  {
104  if (SvXMLUnitConverter::convertEnum(eIndexType, rLocalName, aIndexTypeMap))
105  {
106  // check for array index:
107  OSL_ENSURE(unsigned(eIndexType) < (SAL_N_ELEMENTS(aIndexServiceMap)), "index out of range");
108  OSL_ENSURE(SAL_N_ELEMENTS(aIndexServiceMap) ==
110  "service and source element maps must be same size");
111  bValid = true;
112  }
113  }
114 }
115 
117 {
118 }
119 
121  const Reference<XAttributeList> & xAttrList)
122 {
123  if (!bValid)
124  return;
125 
126  // find text:style-name attribute and set section style
127  // find text:protected and set value
128  // find text:name and set value (if not empty)
129  sal_Int16 nCount = xAttrList->getLength();
130  bool bProtected = false;
131  OUString sIndexName;
132  OUString sXmlId;
133  XMLPropStyleContext* pStyle(nullptr);
134  for(sal_Int16 nAttr = 0; nAttr < nCount; nAttr++)
135  {
136  OUString sLocalName;
137  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
138  GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
139  &sLocalName );
140  if ( XML_NAMESPACE_TEXT == nPrefix)
141  {
142  if ( IsXMLToken( sLocalName, XML_STYLE_NAME ) )
143  {
144  pStyle = GetImport().GetTextImport()->FindSectionStyle(
145  xAttrList->getValueByIndex(nAttr));
146  }
147  else if ( IsXMLToken( sLocalName, XML_PROTECTED ) )
148  {
149  bool bTmp(false);
151  bTmp, xAttrList->getValueByIndex(nAttr)))
152  {
153  bProtected = bTmp;
154  }
155  }
156  else if ( IsXMLToken( sLocalName, XML_NAME ) )
157  {
158  sIndexName = xAttrList->getValueByIndex(nAttr);
159  }
160  }
161  else if ( XML_NAMESPACE_XML == nPrefix)
162  {
163  if ( IsXMLToken( sLocalName, XML_ID ) )
164  {
165  sXmlId = xAttrList->getValueByIndex(nAttr);
166  }
167  }
168  }
169 
170  // create table of content (via MultiServiceFactory)
171  Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),
172  UNO_QUERY);
173  if( xFactory.is() )
174  {
175  Reference<XInterface> xIfc =
176  xFactory->createInstance(
177  OUString::createFromAscii(aIndexServiceMap[eIndexType]));
178  if( xIfc.is() )
179  {
180  // get Property set
181  Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY);
182  xTOCPropertySet = xPropSet;
183 
184  // insert section
185  // a) insert section
186  // The inserted index consists of an empty paragraph
187  // only, as well as an empty paragraph *after* the index
188  // b) insert marker after index, and put Cursor inside of the
189  // index
190 
191  // preliminaries
192 #ifndef DBG_UTIL
193  OUString const sMarker(" ");
194 #else
195  OUString const sMarker("Y");
196 #endif
199 
200  // a) insert index
201  Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
202  try
203  {
204  GetImport().GetTextImport()->InsertTextContent(
205  xTextContent);
206  }
207  catch(const IllegalArgumentException& e)
208  {
209  // illegal argument? Then we can't accept indices here!
213  aSeq, e.Message, nullptr );
214 
215  // set bValid to false, and return prematurely
216  bValid = false;
217  return;
218  }
219 
220  // xml:id for RDF metadata
221  GetImport().SetXmlId(xIfc, sXmlId);
222 
223  // b) insert marker and move cursor
224  rImport->InsertString(sMarker);
225  rImport->GetCursor()->goLeft(2, false);
226  }
227  }
228 
229  // finally, check for redlines that should start at
230  // the section start node
231  if( bValid )
232  GetImport().GetTextImport()->RedlineAdjustStartNodeCursor();
233 
234  if (pStyle != nullptr)
235  {
236  pStyle->FillPropertySet( xTOCPropertySet );
237  }
238 
239  xTOCPropertySet->setPropertyValue( "IsProtected", Any(bProtected) );
240 
241  if (!sIndexName.isEmpty())
242  {
243  xTOCPropertySet->setPropertyValue( "Name", Any(sIndexName) );
244  }
245 
246 }
247 
249 {
250  // complete import of index by removing the markers (if the index
251  // was actually inserted, that is)
252  if( bValid )
253  {
254  // preliminaries
256 
257  // get rid of last paragraph (unless it's the only paragraph)
258  rHelper->GetCursor()->goRight(1, false);
259  if( xBodyContextRef.is() &&
260  static_cast<XMLIndexBodyContext*>(xBodyContextRef.get())->HasContent() )
261  {
262  rHelper->GetCursor()->goLeft(1, true);
263  rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
264  "", true);
265  }
266 
267  // and delete second marker
268  rHelper->GetCursor()->goRight(1, true);
269  rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
270  "", true);
271 
272  // check for Redlines on our end node
273  GetImport().GetTextImport()->RedlineAdjustStartNodeCursor();
274  }
275 }
276 
278  sal_uInt16 nPrefix,
279  const OUString& rLocalName,
280  const Reference<XAttributeList> & /*xAttrList*/ )
281 {
282  SvXMLImportContextRef xContext;
283 
284  if (bValid)
285  {
286  if (XML_NAMESPACE_TEXT == nPrefix)
287  {
288  if ( IsXMLToken( rLocalName, XML_INDEX_BODY ) )
289  {
290  xContext = new XMLIndexBodyContext(GetImport(), nPrefix,
291  rLocalName);
292  if ( !xBodyContextRef.is() ||
293  !static_cast<XMLIndexBodyContext*>(xBodyContextRef.get())->HasContent() )
294  {
295  xBodyContextRef = xContext;
296  }
297  }
298  else if (IsXMLToken(rLocalName, aIndexSourceElementMap[eIndexType]))
299  {
300  // instantiate source context for the appropriate index type
301  switch (eIndexType)
302  {
303  case TEXT_INDEX_TOC:
304  xContext = new XMLIndexTOCSourceContext(
305  GetImport(), nPrefix, rLocalName, xTOCPropertySet);
306  break;
307 
308  case TEXT_INDEX_OBJECT:
309  xContext = new XMLIndexObjectSourceContext(
310  GetImport(), nPrefix, rLocalName, xTOCPropertySet);
311  break;
312 
314  xContext = new XMLIndexAlphabeticalSourceContext(
315  GetImport(), nPrefix, rLocalName, xTOCPropertySet);
316  break;
317 
318  case TEXT_INDEX_USER:
319  xContext = new XMLIndexUserSourceContext(
320  GetImport(), nPrefix, rLocalName, xTOCPropertySet);
321  break;
322 
324  xContext = new XMLIndexBibliographySourceContext(
325  GetImport(), nPrefix, rLocalName, xTOCPropertySet);
326  break;
327 
328  case TEXT_INDEX_TABLE:
329  xContext = new XMLIndexTableSourceContext(
330  GetImport(), nPrefix, rLocalName, xTOCPropertySet);
331  break;
332 
334  xContext = new XMLIndexIllustrationSourceContext(
335  GetImport(), nPrefix, rLocalName, xTOCPropertySet);
336  break;
337 
338  default:
339  OSL_FAIL("index type not implemented");
340  break;
341  }
342  }
343  // else: ignore
344  }
345  // else: no text: namespace -> ignore
346  }
347  // else: not valid -> ignore
348 
349  return xContext;
350 }
351 
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3422
static bool convertEnum(EnumT &rEnum, const OUString &rValue, const SvXMLEnumMapEntry< EnumT > *pMap)
convert string to enum using given enum map, if the enum is not found in the map, this method will re...
Definition: xmluconv.hxx:128
Import object index source element.
static bool convertBool(bool &rBool, const OUString &rString)
#define XMLERROR_NO_INDEX_ALLOWED_HERE
Definition: xmlerror.hxx:54
Import table index source element.
static const char * aIndexServiceMap[]
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:62
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:397
constexpr sal_uInt16 XML_NAMESPACE_TEXT
Definition: xmlnmspe.hxx:31
rtl::Reference< XMLTextImportHelper > const & GetTextImport()
Definition: xmlimp.hxx:594
Import user defined index source element.
Import illustration index source element;.
const OUString & GetLocalName() const
Definition: xmlictxt.hxx:69
int nCount
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:47
static const XMLTokenEnum aIndexSourceElementMap[]
#define SAL_N_ELEMENTS(arr)
constexpr sal_uInt16 XML_NAMESPACE_XML
Definition: xmlnmspe.hxx:51
enum IndexTypeEnum eIndexType
virtual void FillPropertySet(const css::uno::Reference< css::beans::XPropertySet > &rPropSet)
Definition: prstylei.cxx:231
Import table of context source element.
Import alphabetical (keyword) index source element.
SvXMLImportContextRef xBodyContextRef
void SetXmlId(css::uno::Reference< css::uno::XInterface > const &i_xIfc, OUString const &i_rXmlId)
set the XmlId attribute of given UNO object (for RDF metadata)
Definition: xmlimp.cxx:1960
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:44
Map an XMLTokenEnum to an enum value.
Definition: ximpshap.hxx:40
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
StartElement is called after a context has been constructed and before an elements context is parsed...
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
Handling of tokens in XML:
#define XMLERROR_FLAG_ERROR
Definition: xmlerror.hxx:36
XMLIndexTOCContext(SvXMLImport &rImport, sal_uInt16 nPrfx, const OUString &rLocalName)
void SetError(sal_Int32 nId, const css::uno::Sequence< OUString > &rMsgParams, const OUString &rExceptionMessage, const css::uno::Reference< css::xml::sax::XLocator > &rLocator)
Record an error condition that occurred during import.
Sequence< sal_Int8 > aSeq
css::uno::Reference< css::beans::XPropertySet > xTOCPropertySet
XPropertySet of the index.
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
virtual ~XMLIndexTOCContext() override
SvXMLEnumMapEntry< IndexTypeEnum > const aIndexTypeMap[]
Reference< XSingleServiceFactory > xFactory
Import index body.