Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/xmloff/source/text/XMLIndexTemplateContext.cxx
Line
Count
Source
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 "XMLIndexTemplateContext.hxx"
21
#include "XMLIndexSimpleEntryContext.hxx"
22
#include "XMLIndexSpanEntryContext.hxx"
23
#include "XMLIndexTabStopEntryContext.hxx"
24
#include "XMLIndexBibliographyEntryContext.hxx"
25
#include "XMLIndexChapterInfoEntryContext.hxx"
26
#include <xmloff/xmlictxt.hxx>
27
#include <xmloff/xmlimp.hxx>
28
#include <xmloff/txtimp.hxx>
29
#include <xmloff/xmlnamespace.hxx>
30
#include <xmloff/xmltoken.hxx>
31
#include <xmloff/xmluconv.hxx>
32
#include <xmloff/xmlement.hxx>
33
#include <tools/debug.hxx>
34
#include <rtl/ustring.hxx>
35
#include <sal/log.hxx>
36
#include <com/sun/star/container/XIndexReplace.hpp>
37
#include <com/sun/star/container/XNameContainer.hpp>
38
#include <com/sun/star/beans/XPropertySet.hpp>
39
40
#include <algorithm>
41
42
using namespace ::xmloff::token;
43
44
using ::com::sun::star::beans::XPropertySet;
45
using ::com::sun::star::beans::PropertyValues;
46
using ::com::sun::star::uno::Reference;
47
using ::com::sun::star::uno::Sequence;
48
using ::com::sun::star::uno::Any;
49
using ::com::sun::star::container::XIndexReplace;
50
51
XMLIndexTemplateContext::XMLIndexTemplateContext(
52
    SvXMLImport& rImport,
53
    Reference<XPropertySet> & rPropSet,
54
    const SvXMLEnumMapEntry<sal_uInt16>* pLevelNameMap,
55
    enum XMLTokenEnum eLevelAttrName,
56
    std::span<const OUString> pLevelStylePropMap,
57
    const bool* pAllowedTokenTypes,
58
    bool bT )
59
758
:   SvXMLImportContext(rImport)
60
758
,   pOutlineLevelNameMap(pLevelNameMap)
61
758
,   eOutlineLevelAttrName(eLevelAttrName)
62
758
,   pOutlineLevelStylePropMap(pLevelStylePropMap)
63
758
,   pAllowedTokenTypesMap(pAllowedTokenTypes)
64
758
,   nOutlineLevel(1)    // all indices have level 1 (0 is for header)
65
758
,   bStyleNameOK(false)
66
758
,   bOutlineLevelOK(false)
67
758
,   bTOC( bT )
68
758
,   rPropertySet(rPropSet)
69
758
{
70
758
    DBG_ASSERT( ((XML_TOKEN_INVALID != eLevelAttrName) &&  (nullptr != pLevelNameMap))
71
758
                || ((XML_TOKEN_INVALID == eLevelAttrName) &&  (nullptr == pLevelNameMap)),
72
758
                "need both, attribute name and value map, or neither" );
73
758
    SAL_WARN_IF( nullptr == pAllowedTokenTypes, "xmloff", "need allowed tokens map" );
74
75
    // no map for outline-level? then use 1
76
758
    if (nullptr == pLevelNameMap)
77
0
    {
78
0
        nOutlineLevel = 1;
79
0
        bOutlineLevelOK = true;
80
0
    }
81
758
}
82
83
XMLIndexTemplateContext::~XMLIndexTemplateContext()
84
758
{
85
758
}
86
87
88
void XMLIndexTemplateContext::addTemplateEntry(
89
    const PropertyValues& aValues)
90
4.83k
{
91
4.83k
    aValueVector.push_back(aValues);
92
4.83k
}
93
94
95
void XMLIndexTemplateContext::startFastElement(
96
    sal_Int32 /*nElement*/,
97
    const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
98
758
{
99
    // process two attributes: style-name, outline-level
100
758
    for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
101
1.50k
    {
102
1.50k
        if(aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME))
103
748
        {
104
            // style name
105
748
            sStyleName = aIter.toString();
106
748
            bStyleNameOK = true;
107
748
        }
108
759
        else if (aIter.getToken() == XML_ELEMENT(TEXT, eOutlineLevelAttrName))
109
742
        {
110
            // we have an attr name! Then see if we have the attr, too.
111
            // outline level
112
742
            sal_uInt16 nTmp;
113
742
            if (SvXMLUnitConverter::convertEnum(nTmp, aIter.toView(), pOutlineLevelNameMap))
114
732
            {
115
732
                nOutlineLevel = nTmp;
116
732
                bOutlineLevelOK = true;
117
732
            }
118
            // else: illegal value -> ignore
119
742
        }
120
        // else: attribute not in text namespace -> ignore
121
1.50k
    }
122
758
}
123
124
void XMLIndexTemplateContext::endFastElement(sal_Int32 )
125
688
{
126
688
    if (!bOutlineLevelOK)
127
20
        return;
128
129
668
    const sal_Int32 nCount = aValueVector.size();
130
668
    Sequence<PropertyValues> aValueSequence(nCount);
131
668
    std::copy(aValueVector.begin(), aValueVector.end(), aValueSequence.getArray());
132
133
    // get LevelFormat IndexReplace ...
134
668
    Any aAny = rPropertySet->getPropertyValue(u"LevelFormat"_ustr);
135
668
    Reference<XIndexReplace> xIndexReplace;
136
668
    aAny >>= xIndexReplace;
137
138
    // ... and insert
139
668
    xIndexReplace->replaceByIndex(nOutlineLevel, Any(aValueSequence));
140
141
668
    if (!bStyleNameOK)
142
5
        return;
143
144
663
    const OUString pStyleProperty =
145
663
        pOutlineLevelStylePropMap[nOutlineLevel];
146
147
663
    DBG_ASSERT(!pStyleProperty.isEmpty(), "need property name");
148
663
    if (pStyleProperty.isEmpty())
149
0
        return;
150
151
663
    OUString sDisplayStyleName =
152
663
            GetImport().GetStyleDisplayName(
153
663
            XmlStyleFamily::TEXT_PARAGRAPH,
154
663
            sStyleName );
155
    // #i50288#: Check if style exists
156
663
    const Reference < css::container::XNameContainer > & rStyles =
157
663
        GetImport().GetTextImport()->GetParaStyles();
158
663
    if( rStyles.is() &&
159
663
        rStyles->hasByName( sDisplayStyleName ) )
160
511
    {
161
511
        rPropertySet->setPropertyValue(
162
511
            pStyleProperty, css::uno::Any(sDisplayStyleName));
163
511
    }
164
663
}
165
166
namespace {
167
/// template token types; used for aTokenTypeMap parameter
168
enum TemplateTokenType
169
{
170
    XML_TOK_INDEX_TYPE_ENTRY_TEXT = 0,
171
    XML_TOK_INDEX_TYPE_TAB_STOP,
172
    XML_TOK_INDEX_TYPE_TEXT,
173
    XML_TOK_INDEX_TYPE_PAGE_NUMBER,
174
    XML_TOK_INDEX_TYPE_CHAPTER,
175
    XML_TOK_INDEX_TYPE_LINK_START,
176
    XML_TOK_INDEX_TYPE_LINK_END,
177
    XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
178
};
179
180
}
181
182
SvXMLEnumMapEntry<TemplateTokenType> const aTemplateTokenTypeMap[] =
183
{
184
    { XML_INDEX_ENTRY_TEXT,         XML_TOK_INDEX_TYPE_ENTRY_TEXT },
185
    { XML_INDEX_ENTRY_TAB_STOP,     XML_TOK_INDEX_TYPE_TAB_STOP },
186
    { XML_INDEX_ENTRY_SPAN,         XML_TOK_INDEX_TYPE_TEXT },
187
    { XML_INDEX_ENTRY_PAGE_NUMBER,  XML_TOK_INDEX_TYPE_PAGE_NUMBER },
188
    { XML_INDEX_ENTRY_CHAPTER,      XML_TOK_INDEX_TYPE_CHAPTER },
189
    { XML_INDEX_ENTRY_LINK_START,   XML_TOK_INDEX_TYPE_LINK_START },
190
    { XML_INDEX_ENTRY_LINK_END,     XML_TOK_INDEX_TYPE_LINK_END },
191
    { XML_INDEX_ENTRY_BIBLIOGRAPHY, XML_TOK_INDEX_TYPE_BIBLIOGRAPHY },
192
    { XML_TOKEN_INVALID, TemplateTokenType(0) }
193
};
194
195
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexTemplateContext::createFastChildContext(
196
    sal_Int32 nElement,
197
    const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
198
5.11k
{
199
5.11k
    SvXMLImportContext* pContext = nullptr;
200
201
5.11k
    if (IsTokenInNamespace(nElement, XML_NAMESPACE_TEXT) || IsTokenInNamespace(nElement, XML_NAMESPACE_LO_EXT))
202
5.01k
    {
203
5.01k
        TemplateTokenType nToken;
204
5.01k
        if (SvXMLUnitConverter::convertEnum(nToken, SvXMLImport::getNameFromToken(nElement),
205
5.01k
                                            aTemplateTokenTypeMap))
206
4.96k
        {
207
            // can this index accept this kind of token?
208
4.96k
            if (pAllowedTokenTypesMap[nToken])
209
4.96k
            {
210
4.96k
                switch (nToken)
211
4.96k
                {
212
0
                    case XML_TOK_INDEX_TYPE_ENTRY_TEXT:
213
0
                        pContext = new XMLIndexSimpleEntryContext(
214
0
                            GetImport(), u"TokenEntryText"_ustr, *this);
215
0
                        break;
216
217
0
                    case XML_TOK_INDEX_TYPE_PAGE_NUMBER:
218
0
                        pContext = new XMLIndexSimpleEntryContext(
219
0
                            GetImport(), u"TokenPageNumber"_ustr, *this);
220
0
                        break;
221
222
0
                    case XML_TOK_INDEX_TYPE_LINK_START:
223
0
                        pContext = new XMLIndexSimpleEntryContext(
224
0
                            GetImport(), u"TokenHyperlinkStart"_ustr, *this);
225
0
                        break;
226
227
0
                    case XML_TOK_INDEX_TYPE_LINK_END:
228
0
                        pContext = new XMLIndexSimpleEntryContext(
229
0
                            GetImport(), u"TokenHyperlinkEnd"_ustr, *this);
230
0
                        break;
231
232
2.15k
                    case XML_TOK_INDEX_TYPE_TEXT:
233
2.15k
                        pContext = new XMLIndexSpanEntryContext(
234
2.15k
                            GetImport(), *this);
235
2.15k
                        break;
236
237
0
                    case XML_TOK_INDEX_TYPE_TAB_STOP:
238
0
                        pContext = new XMLIndexTabStopEntryContext(
239
0
                            GetImport(), *this);
240
0
                        break;
241
242
2.81k
                    case XML_TOK_INDEX_TYPE_BIBLIOGRAPHY:
243
2.81k
                        pContext = new XMLIndexBibliographyEntryContext(
244
2.81k
                            GetImport(), *this);
245
2.81k
                        break;
246
247
0
                    case XML_TOK_INDEX_TYPE_CHAPTER:
248
0
                        pContext = new XMLIndexChapterInfoEntryContext(
249
0
                            GetImport(), *this, bTOC );
250
0
                        break;
251
252
0
                    default:
253
                        // ignore!
254
0
                        break;
255
4.96k
                }
256
4.96k
            }
257
4.96k
        }
258
5.01k
    }
259
260
    // ignore unknown
261
5.11k
    return pContext;
262
5.11k
}
263
264
265
// maps for the XMLIndexTemplateContext constructor
266
267
268
// table of content and user defined index:
269
270
const SvXMLEnumMapEntry<sal_uInt16> aSvLevelNameTOCMap[] =
271
{
272
    { XML_1, 1 },
273
    { XML_2, 2 },
274
    { XML_3, 3 },
275
    { XML_4, 4 },
276
    { XML_5, 5 },
277
    { XML_6, 6 },
278
    { XML_7, 7 },
279
    { XML_8, 8 },
280
    { XML_9, 9 },
281
    { XML_10, 10 },
282
    { XML_TOKEN_INVALID, 0 }
283
};
284
285
constexpr OUString aLevelStylePropNameTOCMapArray[] =
286
    { u""_ustr, u"ParaStyleLevel1"_ustr, u"ParaStyleLevel2"_ustr, u"ParaStyleLevel3"_ustr,
287
          u"ParaStyleLevel4"_ustr, u"ParaStyleLevel5"_ustr, u"ParaStyleLevel6"_ustr,
288
          u"ParaStyleLevel7"_ustr, u"ParaStyleLevel8"_ustr, u"ParaStyleLevel9"_ustr,
289
          u"ParaStyleLevel10"_ustr, u""_ustr };
290
std::span<const OUString> const aLevelStylePropNameTOCMap = aLevelStylePropNameTOCMapArray;
291
292
const bool aAllowedTokenTypesTOC[] =
293
{
294
    true,       // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
295
    true,       // XML_TOK_INDEX_TYPE_TAB_STOP,
296
    true,       // XML_TOK_INDEX_TYPE_TEXT,
297
    true,       // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
298
    true,       // XML_TOK_INDEX_TYPE_CHAPTER,
299
    true,       // XML_TOK_INDEX_TYPE_LINK_START,
300
    true,       // XML_TOK_INDEX_TYPE_LINK_END,
301
    false       // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
302
};
303
304
const bool aAllowedTokenTypesUser[] =
305
{
306
    true,       // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
307
    true,       // XML_TOK_INDEX_TYPE_TAB_STOP,
308
    true,       // XML_TOK_INDEX_TYPE_TEXT,
309
    true,       // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
310
    true,       // XML_TOK_INDEX_TYPE_CHAPTER,
311
    true,       // XML_TOK_INDEX_TYPE_LINK_START,
312
    true,       // XML_TOK_INDEX_TYPE_LINK_END,
313
    false       // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
314
};
315
316
317
// alphabetical index
318
319
const SvXMLEnumMapEntry<sal_uInt16> aLevelNameAlphaMap[] =
320
{
321
    { XML_SEPARATOR, 1 },
322
    { XML_1, 2 },
323
    { XML_2, 3 },
324
    { XML_3, 4 },
325
    { XML_TOKEN_INVALID, 0 }
326
};
327
328
constexpr OUString aLevelStylePropNameAlphaMapArray[] =
329
    { u""_ustr, u"ParaStyleSeparator"_ustr, u"ParaStyleLevel1"_ustr, u"ParaStyleLevel2"_ustr,
330
          u"ParaStyleLevel3"_ustr, u""_ustr };
331
std::span<const OUString> const aLevelStylePropNameAlphaMap = aLevelStylePropNameAlphaMapArray;
332
333
const bool aAllowedTokenTypesAlpha[] =
334
{
335
    true,       // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
336
    true,       // XML_TOK_INDEX_TYPE_TAB_STOP,
337
    true,       // XML_TOK_INDEX_TYPE_TEXT,
338
    true,       // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
339
    true,       // XML_TOK_INDEX_TYPE_CHAPTER,
340
    false,      // XML_TOK_INDEX_TYPE_LINK_START,
341
    false,      // XML_TOK_INDEX_TYPE_LINK_END,
342
    false       // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
343
};
344
345
346
// bibliography index:
347
348
const SvXMLEnumMapEntry<sal_uInt16> aLevelNameBibliographyMap[] =
349
{
350
    { XML_ARTICLE, 1 },
351
    { XML_BOOK, 2 },
352
    { XML_BOOKLET, 3 },
353
    { XML_CONFERENCE, 4 },
354
    { XML_CUSTOM1, 5 },
355
    { XML_CUSTOM2, 6 },
356
    { XML_CUSTOM3, 7 },
357
    { XML_CUSTOM4, 8 },
358
    { XML_CUSTOM5, 9 },
359
    { XML_EMAIL, 10 },
360
    { XML_INBOOK, 11 },
361
    { XML_INCOLLECTION, 12 },
362
    { XML_INPROCEEDINGS, 13 },
363
    { XML_JOURNAL, 14 },
364
    { XML_MANUAL, 15 },
365
    { XML_MASTERSTHESIS, 16 },
366
    { XML_MISC, 17 },
367
    { XML_PHDTHESIS, 18 },
368
    { XML_PROCEEDINGS, 19 },
369
    { XML_TECHREPORT, 20 },
370
    { XML_UNPUBLISHED, 21 },
371
    { XML_WWW, 22 },
372
    { XML_TOKEN_INVALID, 0 }
373
};
374
375
// TODO: replace with real property names, when available
376
constexpr OUString aLevelStylePropNameBibliographyMapArray[] =
377
{
378
    u""_ustr, u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr,
379
    u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr,
380
    u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr,
381
    u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr,
382
    u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr,
383
    u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr,
384
    u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr, u"ParaStyleLevel1"_ustr,
385
    u"ParaStyleLevel1"_ustr, u""_ustr };
386
std::span<const OUString> const aLevelStylePropNameBibliographyMap = aLevelStylePropNameBibliographyMapArray;
387
388
const bool aAllowedTokenTypesBibliography[] =
389
{
390
    true,       // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
391
    true,       // XML_TOK_INDEX_TYPE_TAB_STOP,
392
    true,       // XML_TOK_INDEX_TYPE_TEXT,
393
    true,       // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
394
    false,      // XML_TOK_INDEX_TYPE_CHAPTER,
395
    false,      // XML_TOK_INDEX_TYPE_LINK_START,
396
    false,      // XML_TOK_INDEX_TYPE_LINK_END,
397
    true        // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
398
};
399
400
401
// table, illustration and object index
402
403
// no name map
404
const SvXMLEnumMapEntry<sal_uInt16>* aLevelNameTableMap = nullptr;
405
406
constexpr OUString aLevelStylePropNameTableMapArray[] =
407
    { u""_ustr, u"ParaStyleLevel1"_ustr, u""_ustr };
408
std::span<const OUString> const aLevelStylePropNameTableMap = aLevelStylePropNameTableMapArray;
409
410
const bool aAllowedTokenTypesTable[] =
411
{
412
    true,       // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
413
    true,       // XML_TOK_INDEX_TYPE_TAB_STOP,
414
    true,       // XML_TOK_INDEX_TYPE_TEXT,
415
    true,       // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
416
    true,       // XML_TOK_INDEX_TYPE_CHAPTER,
417
    true,       // XML_TOK_INDEX_TYPE_LINK_START,
418
    true,       // XML_TOK_INDEX_TYPE_LINK_END,
419
    false       // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
420
};
421
422
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */