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
XMLIndexTOCContext(SvXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLocalName)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
~XMLIndexTOCContext()132 XMLIndexTOCContext::~XMLIndexTOCContext()
133 {
134 }
135
StartElement(const Reference<XAttributeList> & xAttrList)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
EndElement()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
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<XAttributeList> & xAttrList)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