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>
28 #include <sal/log.hxx>
36 #include "XMLIndexBodyContext.hxx"
37 #include <xmloff/xmlictxt.hxx>
38 #include <xmloff/xmlimp.hxx>
39 #include <xmloff/txtimp.hxx>
40 #include <xmloff/namespacemap.hxx>
41 #include <xmloff/xmlnamespace.hxx>
42 #include <xmloff/xmltoken.hxx>
43 #include <xmloff/prstylei.hxx>
44 #include <xmloff/xmlerror.hxx>
45 #include <xmloff/xmluconv.hxx>
46 #include <xmloff/xmlement.hxx>
47 #include <rtl/ustring.hxx>
48 #include <osl/diagnose.h>
49 
50 
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::text;
53 using namespace ::xmloff::token;
54 
55 using ::com::sun::star::beans::XPropertySet;
56 using ::com::sun::star::uno::Reference;
57 using ::com::sun::star::xml::sax::XAttributeList;
58 using ::com::sun::star::lang::XMultiServiceFactory;
59 using ::com::sun::star::lang::IllegalArgumentException;
60 
61 
62 static const char* aIndexServiceMap[] =
63 {
64  "com.sun.star.text.ContentIndex",
65  "com.sun.star.text.DocumentIndex",
66  "com.sun.star.text.TableIndex",
67  "com.sun.star.text.ObjectIndex",
68  "com.sun.star.text.Bibliography",
69  "com.sun.star.text.UserIndex",
70  "com.sun.star.text.IllustrationsIndex"
71 };
72 
74 {
82 };
83 
85 {
94 };
95 
96 
98  sal_Int32 nElement)
99  : SvXMLImportContext(rImport)
100  , eIndexType(TEXT_INDEX_UNKNOWN)
101  , bValid(false)
102 {
103  if (IsTokenInNamespace(nElement, XML_NAMESPACE_TEXT))
104  {
106  {
107  // check for array index:
108  OSL_ENSURE(unsigned(eIndexType) < (SAL_N_ELEMENTS(aIndexServiceMap)), "index out of range");
109  OSL_ENSURE(SAL_N_ELEMENTS(aIndexServiceMap) ==
111  "service and source element maps must be same size");
112  bValid = true;
113  }
114  }
115 }
116 
118 {
119 }
120 
122  sal_Int32 nElement,
123  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
124 {
125  if (!bValid)
126  return;
127 
128  // find text:style-name attribute and set section style
129  // find text:protected and set value
130  // find text:name and set value (if not empty)
131  bool bProtected = false;
132  OUString sIndexName;
133  OUString sXmlId;
134  XMLPropStyleContext* pStyle(nullptr);
135  for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
136  {
137  switch(aIter.getToken())
138  {
140  {
141  pStyle = GetImport().GetTextImport()->FindSectionStyle(
142  aIter.toString());
143  break;
144  }
146  {
147  bool bTmp(false);
148  if (::sax::Converter::convertBool(bTmp, aIter.toView()))
149  {
150  bProtected = bTmp;
151  }
152  break;
153  }
154  case XML_ELEMENT(TEXT, XML_NAME):
155  {
156  sIndexName = aIter.toString();
157  break;
158  }
159  case XML_ELEMENT(XML, XML_ID):
160  {
161  sXmlId = aIter.toString();
162  break;
163  }
164  default:
165  XMLOFF_WARN_UNKNOWN("xmloff", aIter);
166  }
167  }
168 
169  // create table of content (via MultiServiceFactory)
170  Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),
171  UNO_QUERY);
172  if( xFactory.is() )
173  {
174  Reference<XInterface> xIfc =
175  xFactory->createInstance(
176  OUString::createFromAscii(aIndexServiceMap[eIndexType]));
177  if( xIfc.is() )
178  {
179  // get Property set
180  Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY);
181  xTOCPropertySet = xPropSet;
182 
183  // insert section
184  // a) insert section
185  // The inserted index consists of an empty paragraph
186  // only, as well as an empty paragraph *after* the index
187  // b) insert marker after index, and put Cursor inside of the
188  // index
189 
190  // preliminaries
191 #ifndef DBG_UTIL
192  OUString const sMarker(" ");
193 #else
194  OUString const sMarker("Y");
195 #endif
198 
199  // a) insert index
200  Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
201  try
202  {
203  GetImport().GetTextImport()->InsertTextContent(
204  xTextContent);
205  }
206  catch(const IllegalArgumentException& e)
207  {
208  // illegal argument? Then we can't accept indices here!
212  aSeq, e.Message, nullptr );
213 
214  // set bValid to false, and return prematurely
215  bValid = false;
216  return;
217  }
218 
219  // xml:id for RDF metadata
220  GetImport().SetXmlId(xIfc, sXmlId);
221 
222  // b) insert marker and move cursor
223  rImport->InsertString(sMarker);
224  rImport->GetCursor()->goLeft(2, false);
225  }
226  }
227 
228  // finally, check for redlines that should start at
229  // the section start node
230  if( bValid )
231  GetImport().GetTextImport()->RedlineAdjustStartNodeCursor();
232 
233  if (pStyle != nullptr)
234  {
235  pStyle->FillPropertySet( xTOCPropertySet );
236  }
237 
238  xTOCPropertySet->setPropertyValue( "IsProtected", Any(bProtected) );
239 
240  if (!sIndexName.isEmpty())
241  {
242  xTOCPropertySet->setPropertyValue( "Name", Any(sIndexName) );
243  }
244 
245 }
246 
248 {
249  // complete import of index by removing the markers (if the index
250  // was actually inserted, that is)
251  if( bValid )
252  {
253  // preliminaries
255 
256  // get rid of last paragraph (unless it's the only paragraph)
257  rHelper->GetCursor()->goRight(1, false);
258  if( xBodyContextRef.is() && xBodyContextRef->HasContent() )
259  {
260  rHelper->GetCursor()->goLeft(1, true);
261  rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
262  "", true);
263  }
264 
265  // and delete second marker
266  rHelper->GetCursor()->goRight(1, true);
267  rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
268  "", true);
269 
270  // check for Redlines on our end node
271  GetImport().GetTextImport()->RedlineAdjustStartNodeCursor();
272  }
273 }
274 
275 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexTOCContext::createFastChildContext(
276  sal_Int32 nElement,
277  const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
278 {
279  SvXMLImportContextRef xContext;
280 
281  // not valid -> ignore
282  if (!bValid)
283  return nullptr;
284 
285  if (nElement == XML_ELEMENT(TEXT, XML_INDEX_BODY) )
286  {
288  xContext = xNewBodyContext;
289  if ( !xBodyContextRef.is() || !xBodyContextRef->HasContent() )
290  {
291  xBodyContextRef = xNewBodyContext;
292  }
293  }
294  else if (nElement == XML_ELEMENT(TEXT, aIndexSourceElementMap[eIndexType]))
295  {
296  // instantiate source context for the appropriate index type
297  switch (eIndexType)
298  {
299  case TEXT_INDEX_TOC:
300  xContext = new XMLIndexTOCSourceContext(
302  break;
303 
304  case TEXT_INDEX_OBJECT:
305  xContext = new XMLIndexObjectSourceContext(
307  break;
308 
310  xContext = new XMLIndexAlphabeticalSourceContext(
312  break;
313 
314  case TEXT_INDEX_USER:
315  xContext = new XMLIndexUserSourceContext(
317  break;
318 
320  xContext = new XMLIndexBibliographySourceContext(
322  break;
323 
324  case TEXT_INDEX_TABLE:
325  xContext = new XMLIndexTableSourceContext(
327  break;
328 
330  xContext = new XMLIndexIllustrationSourceContext(
332  break;
333 
334  default:
335  OSL_FAIL("index type not implemented");
336  break;
337  }
338  }
339  // else: ignore
340 
341  return xContext;
342 }
343 
344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XMLIndexTOCContext(SvXMLImport &rImport, sal_Int32 nElement)
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
Import object index source element.
#define XMLERROR_NO_INDEX_ALLOWED_HERE
Definition: xmlerror.hxx:54
Import table index source element.
static const char * aIndexServiceMap[]
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:59
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
rtl::Reference< XMLTextImportHelper > const & GetTextImport()
Definition: xmlimp.hxx:600
Import user defined index source element.
Import illustration index source element;.
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:113
const XMLTokenEnum aIndexSourceElementMap[]
#define SAL_N_ELEMENTS(arr)
enum IndexTypeEnum eIndexType
virtual void FillPropertySet(const css::uno::Reference< css::beans::XPropertySet > &rPropSet)
Definition: prstylei.cxx:222
constexpr sal_uInt16 XML_NAMESPACE_TEXT
Import table of context source element.
Import alphabetical (keyword) index source element.
static bool convertBool(bool &rBool, std::u16string_view rString)
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:1864
static const OUString & getNameFromToken(sal_Int32 nToken)
Definition: xmlimp.cxx:1920
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:39
constexpr bool IsTokenInNamespace(sal_Int32 nToken, sal_uInt16 nNamespacePrefix)
Definition: xmlimp.hxx:104
Handling of tokens in XML:
rtl::Reference< XMLIndexBodyContext > xBodyContextRef
#define XMLERROR_FLAG_ERROR
Definition: xmlerror.hxx:36
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:97
static bool convertEnum(EnumT &rEnum, std::u16string_view 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:145
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:49
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 SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
virtual ~XMLIndexTOCContext() override
SvXMLEnumMapEntry< IndexTypeEnum > const aIndexTypeMap[]
Reference< XSingleServiceFactory > xFactory
Import index body.
TEXT