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