bump product version to 5.0.4.1
[LibreOffice.git] / xmloff / source / core / SettingsExportHelper.cxx
blob3c4edf5047c22f6498158ee4eb2733bf34acee9c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <sax/tools/converter.hxx>
23 #include <xmloff/SettingsExportHelper.hxx>
24 #include <xmloff/xmlnmspe.hxx>
25 #include <xmloff/xmltoken.hxx>
26 #include <tools/debug.hxx>
27 #include <tools/diagnose_ex.h>
28 #include <comphelper/extract.hxx>
29 #include <comphelper/processfactory.hxx>
31 #include <com/sun/star/linguistic2/XSupportedLocales.hpp>
32 #include <com/sun/star/i18n/XForbiddenCharacters.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/container/XNameContainer.hpp>
35 #include <com/sun/star/container/XIndexContainer.hpp>
36 #include <com/sun/star/util/PathSubstitution.hpp>
37 #include <com/sun/star/util/DateTime.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/formula/SymbolDescriptor.hpp>
40 #include <com/sun/star/document/PrinterIndependentLayout.hpp>
41 #include <com/sun/star/document/IndexedPropertyValues.hpp>
42 #include <xmloff/XMLSettingsExportContext.hxx>
43 #include <xmlenums.hxx>
45 using namespace ::com::sun::star;
46 using namespace ::xmloff::token;
48 XMLSettingsExportHelper::XMLSettingsExportHelper( ::xmloff::XMLSettingsExportContext& i_rContext )
49 : m_rContext( i_rContext )
50 , msPrinterIndependentLayout( "PrinterIndependentLayout" )
51 , msColorTableURL( "ColorTableURL" )
52 , msLineEndTableURL( "LineEndTableURL" )
53 , msHatchTableURL( "HatchTableURL" )
54 , msDashTableURL( "DashTableURL" )
55 , msGradientTableURL( "GradientTableURL" )
56 , msBitmapTableURL( "BitmapTableURL" )
60 XMLSettingsExportHelper::~XMLSettingsExportHelper()
64 void XMLSettingsExportHelper::CallTypeFunction(const uno::Any& rAny,
65 const OUString& rName) const
67 uno::Any aAny( rAny );
68 ManipulateSetting( aAny, rName );
70 uno::TypeClass eClass = aAny.getValueTypeClass();
71 switch (eClass)
73 case uno::TypeClass_VOID:
76 * This assertion pops up when exporting values which are set to:
77 * PropertyAttribute::MAYBEVOID, and thus are _supposed_ to have
78 * a VOID value...so I'm removing it ...mtg
79 * OSL_FAIL("no type");
82 break;
83 case uno::TypeClass_BOOLEAN:
85 exportBool(::cppu::any2bool(aAny), rName);
87 break;
88 case uno::TypeClass_BYTE:
90 sal_Int8 nInt8 = 0;
91 aAny >>= nInt8;
92 exportByte(nInt8, rName);
94 break;
95 case uno::TypeClass_SHORT:
97 sal_Int16 nInt16 = 0;
98 aAny >>= nInt16;
99 exportShort(nInt16, rName);
101 break;
102 case uno::TypeClass_LONG:
104 sal_Int32 nInt32 = 0;
105 aAny >>= nInt32;
106 exportInt(nInt32, rName);
108 break;
109 case uno::TypeClass_HYPER:
111 sal_Int64 nInt64 = 0;
112 aAny >>= nInt64;
113 exportLong(nInt64, rName);
115 break;
116 case uno::TypeClass_DOUBLE:
118 double fDouble = 0.0;
119 aAny >>= fDouble;
120 exportDouble(fDouble, rName);
122 break;
123 case uno::TypeClass_STRING:
125 OUString sString;
126 aAny >>= sString;
127 exportString(sString, rName);
129 break;
130 default:
132 uno::Type aType = aAny.getValueType();
133 if (aType.equals(cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get() ) )
135 uno::Sequence< beans::PropertyValue> aProps;
136 aAny >>= aProps;
137 exportSequencePropertyValue(aProps, rName);
139 else if( aType.equals(cppu::UnoType<uno::Sequence<sal_Int8>>::get() ) )
141 uno::Sequence< sal_Int8 > aProps;
142 aAny >>= aProps;
143 exportbase64Binary(aProps, rName);
145 else if (aType.equals(cppu::UnoType<container::XNameContainer>::get()) ||
146 aType.equals(cppu::UnoType<container::XNameAccess>::get()))
148 uno::Reference< container::XNameAccess> aNamed;
149 aAny >>= aNamed;
150 exportNameAccess(aNamed, rName);
152 else if (aType.equals(cppu::UnoType<container::XIndexAccess>::get()) ||
153 aType.equals(cppu::UnoType<container::XIndexContainer>::get()) )
155 uno::Reference<container::XIndexAccess> aIndexed;
156 aAny >>= aIndexed;
157 exportIndexAccess(aIndexed, rName);
159 else if (aType.equals(cppu::UnoType<util::DateTime>::get()) )
161 util::DateTime aDateTime;
162 aAny >>= aDateTime;
163 exportDateTime(aDateTime, rName);
165 else if( aType.equals(cppu::UnoType<i18n::XForbiddenCharacters>::get()) )
167 exportForbiddenCharacters( aAny, rName );
169 else if( aType.equals(cppu::UnoType<uno::Sequence<formula::SymbolDescriptor>>::get() ) )
171 uno::Sequence< formula::SymbolDescriptor > aProps;
172 aAny >>= aProps;
173 exportSymbolDescriptors(aProps, rName);
175 else {
176 OSL_FAIL("this type is not implemented now");
179 break;
183 void XMLSettingsExportHelper::exportBool(const bool bValue, const OUString& rName) const
185 DBG_ASSERT(!rName.isEmpty(), "no name");
186 m_rContext.AddAttribute( XML_NAME, rName );
187 m_rContext.AddAttribute( XML_TYPE, XML_BOOLEAN );
188 m_rContext.StartElement( XML_CONFIG_ITEM, true );
189 OUString sValue;
190 if (bValue)
191 sValue = GetXMLToken(XML_TRUE);
192 else
193 sValue = GetXMLToken(XML_FALSE);
194 m_rContext.Characters( sValue );
195 m_rContext.EndElement( false );
198 void XMLSettingsExportHelper::exportByte(const sal_Int8 nValue, const OUString& rName)
200 (void) nValue; (void) rName;
201 OSL_ENSURE(false, "XMLSettingsExportHelper::exportByte(): #i114162#:\n"
202 "config-items of type \"byte\" are not valid ODF, "
203 "so storing them is disabled!\n"
204 "Use a different type instead (e.g. \"short\").");
206 void XMLSettingsExportHelper::exportShort(const sal_Int16 nValue, const OUString& rName) const
208 DBG_ASSERT(!rName.isEmpty(), "no name");
209 m_rContext.AddAttribute( XML_NAME, rName );
210 m_rContext.AddAttribute( XML_TYPE, XML_SHORT );
211 m_rContext.StartElement( XML_CONFIG_ITEM, true );
212 OUStringBuffer sBuffer;
213 ::sax::Converter::convertNumber(sBuffer, sal_Int32(nValue));
214 m_rContext.Characters( sBuffer.makeStringAndClear() );
215 m_rContext.EndElement( false );
218 void XMLSettingsExportHelper::exportInt(const sal_Int32 nValue, const OUString& rName) const
220 DBG_ASSERT(!rName.isEmpty(), "no name");
221 m_rContext.AddAttribute( XML_NAME, rName );
222 m_rContext.AddAttribute( XML_TYPE, XML_INT );
223 m_rContext.StartElement( XML_CONFIG_ITEM, true );
224 OUStringBuffer sBuffer;
225 ::sax::Converter::convertNumber(sBuffer, nValue);
226 m_rContext.Characters( sBuffer.makeStringAndClear() );
227 m_rContext.EndElement( false );
230 void XMLSettingsExportHelper::exportLong(const sal_Int64 nValue, const OUString& rName) const
232 DBG_ASSERT(!rName.isEmpty(), "no name");
233 m_rContext.AddAttribute( XML_NAME, rName );
234 m_rContext.AddAttribute( XML_TYPE, XML_LONG );
235 m_rContext.StartElement( XML_CONFIG_ITEM, true );
236 OUString sValue(OUString::number(nValue));
237 m_rContext.Characters( sValue );
238 m_rContext.EndElement( false );
241 void XMLSettingsExportHelper::exportDouble(const double fValue, const OUString& rName) const
243 DBG_ASSERT(!rName.isEmpty(), "no name");
244 m_rContext.AddAttribute( XML_NAME, rName );
245 m_rContext.AddAttribute( XML_TYPE, XML_DOUBLE );
246 m_rContext.StartElement( XML_CONFIG_ITEM, true );
247 OUStringBuffer sBuffer;
248 ::sax::Converter::convertDouble(sBuffer, fValue);
249 m_rContext.Characters( sBuffer.makeStringAndClear() );
250 m_rContext.EndElement( false );
253 void XMLSettingsExportHelper::exportString(const OUString& sValue, const OUString& rName) const
255 DBG_ASSERT(!rName.isEmpty(), "no name");
256 m_rContext.AddAttribute( XML_NAME, rName );
257 m_rContext.AddAttribute( XML_TYPE, XML_STRING );
258 m_rContext.StartElement( XML_CONFIG_ITEM, true );
259 if (!sValue.isEmpty())
260 m_rContext.Characters( sValue );
261 m_rContext.EndElement( false );
264 void XMLSettingsExportHelper::exportDateTime(const util::DateTime& aValue, const OUString& rName) const
266 DBG_ASSERT(!rName.isEmpty(), "no name");
267 m_rContext.AddAttribute( XML_NAME, rName );
268 m_rContext.AddAttribute( XML_TYPE, XML_DATETIME );
269 OUStringBuffer sBuffer;
270 ::sax::Converter::convertDateTime(sBuffer, aValue, 0);
271 m_rContext.StartElement( XML_CONFIG_ITEM, true );
272 m_rContext.Characters( sBuffer.makeStringAndClear() );
273 m_rContext.EndElement( false );
276 void XMLSettingsExportHelper::exportSequencePropertyValue(
277 const uno::Sequence<beans::PropertyValue>& aProps,
278 const OUString& rName) const
280 DBG_ASSERT(!rName.isEmpty(), "no name");
281 sal_Int32 nLength(aProps.getLength());
282 if(nLength)
284 m_rContext.AddAttribute( XML_NAME, rName );
285 m_rContext.StartElement( XML_CONFIG_ITEM_SET, true );
286 for (sal_Int32 i = 0; i < nLength; i++)
287 CallTypeFunction(aProps[i].Value, aProps[i].Name);
288 m_rContext.EndElement( true );
291 void XMLSettingsExportHelper::exportSymbolDescriptors(
292 const uno::Sequence < formula::SymbolDescriptor > &rProps,
293 const OUString& rName) const
295 uno::Reference< container::XIndexContainer > xBox = document::IndexedPropertyValues::create(m_rContext.GetComponentContext());
297 const OUString sName ( "Name" );
298 const OUString sExportName ( "ExportName" );
299 const OUString sSymbolSet ( "SymbolSet" );
300 const OUString sCharacter ( "Character" );
301 const OUString sFontName ( "FontName" );
302 const OUString sCharSet ( "CharSet" );
303 const OUString sFamily ( "Family" );
304 const OUString sPitch ( "Pitch" );
305 const OUString sWeight ( "Weight" );
306 const OUString sItalic ( "Italic" );
308 sal_Int32 nCount = rProps.getLength();
309 const formula::SymbolDescriptor *pDescriptor = rProps.getConstArray();
311 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++, pDescriptor++ )
313 uno::Sequence < beans::PropertyValue > aSequence ( XML_SYMBOL_DESCRIPTOR_MAX );
314 beans::PropertyValue *pSymbol = aSequence.getArray();
316 pSymbol[XML_SYMBOL_DESCRIPTOR_NAME].Name = sName;
317 pSymbol[XML_SYMBOL_DESCRIPTOR_NAME].Value <<= pDescriptor->sName;
318 pSymbol[XML_SYMBOL_DESCRIPTOR_EXPORT_NAME].Name = sExportName;
319 pSymbol[XML_SYMBOL_DESCRIPTOR_EXPORT_NAME].Value<<= pDescriptor->sExportName;
320 pSymbol[XML_SYMBOL_DESCRIPTOR_FONT_NAME].Name = sFontName;
321 pSymbol[XML_SYMBOL_DESCRIPTOR_FONT_NAME].Value <<= pDescriptor->sFontName;
322 pSymbol[XML_SYMBOL_DESCRIPTOR_CHAR_SET].Name = sCharSet;
323 pSymbol[XML_SYMBOL_DESCRIPTOR_CHAR_SET].Value <<= pDescriptor->nCharSet;
324 pSymbol[XML_SYMBOL_DESCRIPTOR_FAMILY].Name = sFamily;
325 pSymbol[XML_SYMBOL_DESCRIPTOR_FAMILY].Value <<= pDescriptor->nFamily;
326 pSymbol[XML_SYMBOL_DESCRIPTOR_PITCH].Name = sPitch;
327 pSymbol[XML_SYMBOL_DESCRIPTOR_PITCH].Value <<= pDescriptor->nPitch;
328 pSymbol[XML_SYMBOL_DESCRIPTOR_WEIGHT].Name = sWeight;
329 pSymbol[XML_SYMBOL_DESCRIPTOR_WEIGHT].Value <<= pDescriptor->nWeight;
330 pSymbol[XML_SYMBOL_DESCRIPTOR_ITALIC].Name = sItalic;
331 pSymbol[XML_SYMBOL_DESCRIPTOR_ITALIC].Value <<= pDescriptor->nItalic;
332 pSymbol[XML_SYMBOL_DESCRIPTOR_SYMBOL_SET].Name = sSymbolSet;
333 pSymbol[XML_SYMBOL_DESCRIPTOR_SYMBOL_SET].Value <<= pDescriptor->sSymbolSet;
334 pSymbol[XML_SYMBOL_DESCRIPTOR_CHARACTER].Name = sCharacter;
335 pSymbol[XML_SYMBOL_DESCRIPTOR_CHARACTER].Value <<= pDescriptor->nCharacter;
337 xBox->insertByIndex(nIndex, uno::makeAny( aSequence ));
340 uno::Reference< container::XIndexAccess > xIA( xBox, uno::UNO_QUERY );
341 exportIndexAccess( xIA, rName );
343 void XMLSettingsExportHelper::exportbase64Binary(
344 const uno::Sequence<sal_Int8>& aProps,
345 const OUString& rName) const
347 DBG_ASSERT(!rName.isEmpty(), "no name");
348 sal_Int32 nLength(aProps.getLength());
349 m_rContext.AddAttribute( XML_NAME, rName );
350 m_rContext.AddAttribute( XML_TYPE, XML_BASE64BINARY );
351 m_rContext.StartElement( XML_CONFIG_ITEM, true );
352 if(nLength)
354 OUStringBuffer sBuffer;
355 ::sax::Converter::encodeBase64(sBuffer, aProps);
356 m_rContext.Characters( sBuffer.makeStringAndClear() );
358 m_rContext.EndElement( false );
361 void XMLSettingsExportHelper::exportMapEntry(const uno::Any& rAny,
362 const OUString& rName,
363 const bool bNameAccess) const
365 DBG_ASSERT((bNameAccess && !rName.isEmpty()) || !bNameAccess, "no name");
366 uno::Sequence<beans::PropertyValue> aProps;
367 rAny >>= aProps;
368 sal_Int32 nLength = aProps.getLength();
369 if (nLength)
371 if (bNameAccess)
372 m_rContext.AddAttribute( XML_NAME, rName );
373 m_rContext.StartElement( XML_CONFIG_ITEM_MAP_ENTRY, true );
374 for (sal_Int32 i = 0; i < nLength; i++)
375 CallTypeFunction(aProps[i].Value, aProps[i].Name);
376 m_rContext.EndElement( true );
380 void XMLSettingsExportHelper::exportNameAccess(
381 const uno::Reference<container::XNameAccess>& aNamed,
382 const OUString& rName) const
384 DBG_ASSERT(!rName.isEmpty(), "no name");
385 DBG_ASSERT(aNamed->getElementType().equals(cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get() ),
386 "wrong NameAccess" );
387 if(aNamed->hasElements())
389 m_rContext.AddAttribute( XML_NAME, rName );
390 m_rContext.StartElement( XML_CONFIG_ITEM_MAP_NAMED, true );
391 uno::Sequence< OUString > aNames(aNamed->getElementNames());
392 for (sal_Int32 i = 0; i < aNames.getLength(); i++)
393 exportMapEntry(aNamed->getByName(aNames[i]), aNames[i], true);
394 m_rContext.EndElement( true );
398 void XMLSettingsExportHelper::exportIndexAccess(
399 const uno::Reference<container::XIndexAccess>& rIndexed,
400 const OUString& rName) const
402 DBG_ASSERT(!rName.isEmpty(), "no name");
403 DBG_ASSERT(rIndexed->getElementType().equals(cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get() ),
404 "wrong IndexAccess" );
405 OUString sEmpty;
406 if (rIndexed->hasElements())
408 m_rContext.AddAttribute( XML_NAME, rName );
409 m_rContext.StartElement( XML_CONFIG_ITEM_MAP_INDEXED, true );
410 sal_Int32 nCount = rIndexed->getCount();
411 for (sal_Int32 i = 0; i < nCount; i++)
413 exportMapEntry(rIndexed->getByIndex(i), sEmpty, false);
415 m_rContext.EndElement( true );
419 void XMLSettingsExportHelper::exportForbiddenCharacters(
420 const uno::Any &rAny,
421 const OUString& rName) const
423 uno::Reference<i18n::XForbiddenCharacters> xForbChars;
424 uno::Reference<linguistic2::XSupportedLocales> xLocales;
426 rAny >>= xForbChars;
427 rAny >>= xLocales;
429 DBG_ASSERT( xForbChars.is() && xLocales.is(),"XMLSettingsExportHelper::exportForbiddenCharacters: got illegal forbidden characters!" );
431 if( !xForbChars.is() || !xLocales.is() )
432 return;
434 uno::Reference< container::XIndexContainer > xBox = document::IndexedPropertyValues::create(m_rContext.GetComponentContext());
435 const uno::Sequence< lang::Locale > aLocales( xLocales->getLocales() );
436 const lang::Locale* pLocales = aLocales.getConstArray();
438 const sal_Int32 nCount = aLocales.getLength();
440 /* FIXME-BCP47: this stupid and counterpart in
441 * xmloff/source/core/DocumentSettingsContext.cxx
442 * XMLConfigItemMapIndexedContext::EndElement() */
444 const OUString sLanguage ( "Language" );
445 const OUString sCountry ( "Country" );
446 const OUString sVariant ( "Variant" );
447 const OUString sBeginLine ( "BeginLine" );
448 const OUString sEndLine ( "EndLine" );
450 sal_Int32 nPos = 0;
451 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++, pLocales++ )
453 if( xForbChars->hasForbiddenCharacters( *pLocales ) )
455 const i18n::ForbiddenCharacters aChars( xForbChars->getForbiddenCharacters( *pLocales ) );
458 uno::Sequence < beans::PropertyValue > aSequence ( XML_FORBIDDEN_CHARACTER_MAX );
459 beans::PropertyValue *pForChar = aSequence.getArray();
461 pForChar[XML_FORBIDDEN_CHARACTER_LANGUAGE].Name = sLanguage;
462 pForChar[XML_FORBIDDEN_CHARACTER_LANGUAGE].Value <<= pLocales->Language;
463 pForChar[XML_FORBIDDEN_CHARACTER_COUNTRY].Name = sCountry;
464 pForChar[XML_FORBIDDEN_CHARACTER_COUNTRY].Value <<= pLocales->Country;
465 pForChar[XML_FORBIDDEN_CHARACTER_VARIANT].Name = sVariant;
466 pForChar[XML_FORBIDDEN_CHARACTER_VARIANT].Value <<= pLocales->Variant;
467 pForChar[XML_FORBIDDEN_CHARACTER_BEGIN_LINE].Name = sBeginLine;
468 pForChar[XML_FORBIDDEN_CHARACTER_BEGIN_LINE].Value <<= aChars.beginLine;
469 pForChar[XML_FORBIDDEN_CHARACTER_END_LINE].Name = sEndLine;
470 pForChar[XML_FORBIDDEN_CHARACTER_END_LINE].Value <<= aChars.endLine;
471 xBox->insertByIndex(nPos++, uno::makeAny( aSequence ));
475 uno::Reference< container::XIndexAccess > xIA( xBox, uno::UNO_QUERY );
476 exportIndexAccess( xIA, rName );
479 void XMLSettingsExportHelper::exportAllSettings(
480 const uno::Sequence<beans::PropertyValue>& aProps,
481 const OUString& rName) const
483 DBG_ASSERT(!rName.isEmpty(), "no name");
484 exportSequencePropertyValue(aProps, rName);
488 /** For some settings we may want to change their API representation
489 * from their XML settings representation. This is your chance to do
490 * so!
492 void XMLSettingsExportHelper::ManipulateSetting( uno::Any& rAny, const OUString& rName ) const
494 if( rName == msPrinterIndependentLayout )
496 sal_Int16 nTmp = sal_Int16();
497 if( rAny >>= nTmp )
499 if( nTmp == document::PrinterIndependentLayout::LOW_RESOLUTION )
500 rAny <<= OUString("low-resolution");
501 else if( nTmp == document::PrinterIndependentLayout::DISABLED )
502 rAny <<= OUString("disabled");
503 else if( nTmp == document::PrinterIndependentLayout::HIGH_RESOLUTION )
504 rAny <<= OUString("high-resolution");
507 else if( (rName == msColorTableURL) || (rName == msLineEndTableURL) || (rName == msHatchTableURL) ||
508 (rName == msDashTableURL) || (rName == msGradientTableURL) || (rName == msBitmapTableURL ) )
510 if( !mxStringSubsitution.is() )
514 const_cast< XMLSettingsExportHelper* >(this)->mxStringSubsitution =
515 util::PathSubstitution::create( m_rContext.GetComponentContext() );
517 catch( uno::Exception& )
519 DBG_UNHANDLED_EXCEPTION();
523 if( mxStringSubsitution.is() )
525 OUString aURL;
526 rAny >>= aURL;
527 aURL = mxStringSubsitution->reSubstituteVariables( aURL );
528 rAny <<= aURL;
533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */