1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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();
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");
83 case uno::TypeClass_BOOLEAN
:
85 exportBool(::cppu::any2bool(aAny
), rName
);
88 case uno::TypeClass_BYTE
:
92 exportByte(nInt8
, rName
);
95 case uno::TypeClass_SHORT
:
99 exportShort(nInt16
, rName
);
102 case uno::TypeClass_LONG
:
104 sal_Int32 nInt32
= 0;
106 exportInt(nInt32
, rName
);
109 case uno::TypeClass_HYPER
:
111 sal_Int64 nInt64
= 0;
113 exportLong(nInt64
, rName
);
116 case uno::TypeClass_DOUBLE
:
118 double fDouble
= 0.0;
120 exportDouble(fDouble
, rName
);
123 case uno::TypeClass_STRING
:
127 exportString(sString
, rName
);
132 uno::Type aType
= aAny
.getValueType();
133 if (aType
.equals(cppu::UnoType
<uno::Sequence
<beans::PropertyValue
>>::get() ) )
135 uno::Sequence
< beans::PropertyValue
> aProps
;
137 exportSequencePropertyValue(aProps
, rName
);
139 else if( aType
.equals(cppu::UnoType
<uno::Sequence
<sal_Int8
>>::get() ) )
141 uno::Sequence
< sal_Int8
> 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
;
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
;
157 exportIndexAccess(aIndexed
, rName
);
159 else if (aType
.equals(cppu::UnoType
<util::DateTime
>::get()) )
161 util::DateTime 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
;
173 exportSymbolDescriptors(aProps
, rName
);
176 OSL_FAIL("this type is not implemented now");
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 );
191 sValue
= GetXMLToken(XML_TRUE
);
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());
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 );
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
;
368 sal_Int32 nLength
= aProps
.getLength();
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" );
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
;
429 DBG_ASSERT( xForbChars
.is() && xLocales
.is(),"XMLSettingsExportHelper::exportForbiddenCharacters: got illegal forbidden characters!" );
431 if( !xForbChars
.is() || !xLocales
.is() )
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" );
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
492 void XMLSettingsExportHelper::ManipulateSetting( uno::Any
& rAny
, const OUString
& rName
) const
494 if( rName
== msPrinterIndependentLayout
)
496 sal_Int16 nTmp
= sal_Int16();
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() )
527 aURL
= mxStringSubsitution
->reSubstituteVariables( aURL
);
533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */