1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: stringrepresentation.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 // MARKER(update_precomp.py): autogen include statement, do not remove
31 #include "precompiled_extensions.hxx"
33 #include "sal/config.h"
34 #include "cppuhelper/factory.hxx"
35 #include "cppuhelper/implementationentry.hxx"
36 #include "cppuhelper/implbase3.hxx"
37 #include "com/sun/star/lang/XServiceInfo.hpp"
38 #include "com/sun/star/inspection/XStringRepresentation.hpp"
39 #include "com/sun/star/lang/XInitialization.hpp"
40 #include "com/sun/star/script/XTypeConverter.hpp"
41 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
42 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
43 #include <com/sun/star/beans/XIntrospection.hpp>
44 #include <com/sun/star/util/DateTime.hpp>
45 #include <com/sun/star/util/Date.hpp>
46 #include <com/sun/star/util/Time.hpp>
47 #include <comphelper/sequence.hxx>
48 #include <connectivity/dbconversion.hxx>
49 #ifndef _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_
50 #include "modulepcr.hxx"
52 #ifndef _EXTENSIONS_FORMCTRLR_PROPRESID_HRC_
53 #include "formresid.hrc"
55 #include <tools/debug.hxx>
56 #include <tools/string.hxx>
57 #include <tools/StringListResource.hxx>
58 #include <comphelper/types.hxx>
59 #ifndef _EXTENSIONS_PROPCTRLR_MODULEPCR_HXX_
60 #include "modulepcr.hxx"
66 // component helper namespace
67 namespace comp_StringRepresentation
{
69 using namespace ::com::sun::star
;
71 // component and service helper functions:
72 ::rtl::OUString SAL_CALL
_getImplementationName();
73 uno::Sequence
< ::rtl::OUString
> SAL_CALL
_getSupportedServiceNames();
74 uno::Reference
< uno::XInterface
> SAL_CALL
_create( uno::Reference
< uno::XComponentContext
> const & context
);
76 } // closing component helper namespace
81 using namespace ::com::sun::star
;
82 using namespace ::com::sun::star::uno
;
84 class StringRepresentation
:
85 public ::cppu::WeakImplHelper3
<
87 inspection::XStringRepresentation
,
88 lang::XInitialization
>
91 explicit StringRepresentation(uno::Reference
< uno::XComponentContext
> const & context
);
93 // lang::XServiceInfo:
94 virtual ::rtl::OUString SAL_CALL
getImplementationName() throw (uno::RuntimeException
);
95 virtual ::sal_Bool SAL_CALL
supportsService(const ::rtl::OUString
& ServiceName
) throw (uno::RuntimeException
);
96 virtual uno::Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames() throw (uno::RuntimeException
);
98 // inspection::XStringRepresentation:
99 virtual ::rtl::OUString SAL_CALL
convertToControlValue(const uno::Any
& PropertyValue
) throw (uno::RuntimeException
, uno::Exception
);
100 virtual uno::Any SAL_CALL
convertToPropertyValue(const ::rtl::OUString
& ControlValue
, const uno::Type
& ControlValueType
) throw (uno::RuntimeException
, uno::Exception
);
102 // lang::XInitialization:
103 virtual void SAL_CALL
initialize(const uno::Sequence
< uno::Any
> & aArguments
) throw (uno::RuntimeException
, uno::Exception
);
106 StringRepresentation(StringRepresentation
&); // not defined
107 void operator =(StringRepresentation
&); // not defined
109 virtual ~StringRepresentation() {}
111 /** converts a generic value into a string representation
113 If you want to convert values whose string representation does not depend
114 on a concrete property, use this version
117 if and only if the value could be converted
119 bool convertGenericValueToString(
120 const uno::Any
& _rValue
,
121 ::rtl::OUString
& _rStringRep
124 /** converts string representation into generic value
126 If you want to convert values whose string representation does not depend
127 on a concrete property, use this version
130 if and only if the value could be converted
132 bool convertStringToGenericValue(
133 const ::rtl::OUString
& _rStringRep
,
135 const uno::Type
& _rTargetType
138 /** uses the simple convert method from the type converter
140 * \param _rValue the value to be converted
141 * \return the converted string.
143 ::rtl::OUString
convertSimpleToString( const uno::Any
& _rValue
);
145 /** converts a string into his constant value if it exists, otherwise the type converter is used.
146 * \param _rValue the value to be converted
147 * \param _ePropertyType teh type of the propery to be converted into
148 * \return the converted value
150 uno::Any
convertStringToSimple( const ::rtl::OUString
& _rValue
,const uno::TypeClass
& _ePropertyType
);
152 uno::Reference
< uno::XComponentContext
> m_xContext
;
153 uno::Reference
< script::XTypeConverter
> m_xTypeConverter
;
154 uno::Reference
< reflection::XConstantsTypeDescription
> m_xTypeDescription
;
155 uno::Sequence
< ::rtl::OUString
> m_aValues
;
156 uno::Sequence
< uno::Reference
< reflection::XConstantTypeDescription
> > m_aConstants
;
160 StringRepresentation::StringRepresentation(uno::Reference
< uno::XComponentContext
> const & context
) :
164 // com.sun.star.uno.XServiceInfo:
165 ::rtl::OUString SAL_CALL
StringRepresentation::getImplementationName() throw (uno::RuntimeException
)
167 return comp_StringRepresentation::_getImplementationName();
170 ::sal_Bool SAL_CALL
StringRepresentation::supportsService(::rtl::OUString
const & serviceName
) throw (uno::RuntimeException
)
172 return ::comphelper::existsValue(serviceName
,comp_StringRepresentation::_getSupportedServiceNames());
175 uno::Sequence
< ::rtl::OUString
> SAL_CALL
StringRepresentation::getSupportedServiceNames() throw (uno::RuntimeException
)
177 return comp_StringRepresentation::_getSupportedServiceNames();
180 // inspection::XStringRepresentation:
181 ::rtl::OUString SAL_CALL
StringRepresentation::convertToControlValue(const uno::Any
& PropertyValue
) throw (uno::RuntimeException
, uno::Exception
)
183 ::rtl::OUString sReturn
;
184 if ( !convertGenericValueToString( PropertyValue
, sReturn
) )
186 sReturn
= convertSimpleToString( PropertyValue
);
188 if ( !sReturn
.getLength() && PropertyValue
.hasValue() )
190 ::rtl::OString
sMessage( "StringRepresentation::convertPropertyValueToStringRepresentation: cannot convert values of type '" );
191 sMessage
+= ::rtl::OString( PropertyValue
.getValueType().getTypeName().getStr(), PropertyValue
.getValueType().getTypeName().getLength(), RTL_TEXTENCODING_ASCII_US
);
192 sMessage
+= ::rtl::OString( "'!" );
193 DBG_ERROR( sMessage
.getStr() );
201 uno::Any SAL_CALL
StringRepresentation::convertToPropertyValue(const ::rtl::OUString
& ControlValue
, const uno::Type
& ControlValueType
) throw (uno::RuntimeException
, uno::Exception
)
205 uno::TypeClass ePropertyType
= ControlValueType
.getTypeClass();
206 switch ( ePropertyType
)
208 case uno::TypeClass_FLOAT
:
209 case uno::TypeClass_DOUBLE
:
210 case uno::TypeClass_BYTE
:
211 case uno::TypeClass_SHORT
:
212 case uno::TypeClass_LONG
:
213 case uno::TypeClass_HYPER
:
214 case uno::TypeClass_UNSIGNED_SHORT
:
215 case uno::TypeClass_UNSIGNED_LONG
:
216 case uno::TypeClass_UNSIGNED_HYPER
:
219 aReturn
= convertStringToSimple(ControlValue
, ePropertyType
);
221 catch( const script::CannotConvertException
& ) { }
222 catch( const lang::IllegalArgumentException
& ) { }
226 #if OSL_DEBUG_LEVEL > 0
229 convertStringToGenericValue( ControlValue
, aReturn
, ControlValueType
);
231 #if OSL_DEBUG_LEVEL > 0
232 // could not convert ...
233 if ( !bCanConvert
&& ControlValue
.getLength() )
235 ::rtl::OString
sMessage( "StringRepresentation::convertStringRepresentationToPropertyValue: cannot convert into values of type '" );
236 sMessage
+= ::rtl::OString( ControlValueType
.getTypeName().getStr(), ControlValueType
.getTypeName().getLength(), RTL_TEXTENCODING_ASCII_US
);
237 sMessage
+= ::rtl::OString( "'!" );
238 DBG_ERROR( sMessage
.getStr() );
246 // lang::XInitialization:
247 void SAL_CALL
StringRepresentation::initialize(const uno::Sequence
< uno::Any
> & aArguments
) throw (uno::RuntimeException
, uno::Exception
)
249 sal_Int32 nLength
= aArguments
.getLength();
252 const uno::Any
* pIter
= aArguments
.getConstArray();
253 m_xTypeConverter
.set(*pIter
++,uno::UNO_QUERY
);
256 ::rtl::OUString sConstantName
;
257 *pIter
++ >>= sConstantName
;
258 *pIter
>>= m_aValues
;
260 if ( m_xContext
.is() )
262 uno::Reference
< container::XHierarchicalNameAccess
> xTypeDescProv(
263 m_xContext
->getValueByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) ) ),
264 uno::UNO_QUERY_THROW
);
266 m_xTypeDescription
.set( xTypeDescProv
->getByHierarchicalName( sConstantName
), uno::UNO_QUERY_THROW
);
267 m_aConstants
= m_xTypeDescription
->getConstants();
272 //------------------------------------------------------------------------
273 ::rtl::OUString
StringRepresentation::convertSimpleToString( const uno::Any
& _rValue
)
275 ::rtl::OUString sReturn
;
276 if ( m_xTypeConverter
.is() && _rValue
.hasValue() )
280 if ( m_aConstants
.getLength() )
282 sal_Int16 nConstantValue
= 0;
283 if ( _rValue
>>= nConstantValue
)
285 const uno::Reference
< reflection::XConstantTypeDescription
>* pIter
= m_aConstants
.getConstArray();
286 const uno::Reference
< reflection::XConstantTypeDescription
>* pEnd
= pIter
+ m_aConstants
.getLength();
287 for(sal_Int32 i
= 0;pIter
!= pEnd
;++pIter
,++i
)
289 if ( (*pIter
)->getConstantValue() == _rValue
)
291 OSL_ENSURE(i
< m_aValues
.getLength() ,"StringRepresentation::convertSimpleToString: Index is not in range of m_aValues");
292 sReturn
= m_aValues
[i
];
299 if ( !sReturn
.getLength() )
300 m_xTypeConverter
->convertToSimpleType( _rValue
, uno::TypeClass_STRING
) >>= sReturn
;
302 catch( script::CannotConvertException
& ) { }
303 catch( lang::IllegalArgumentException
& ) { }
308 //--------------------------------------------------------------------
311 struct ConvertIntegerFromAndToString
313 ::rtl::OUString
operator()( sal_Int32 _rIntValue
) const
315 return ::rtl::OUString::valueOf( (sal_Int32
)_rIntValue
);
317 sal_Int32
operator()( const ::rtl::OUString
& _rStringValue
) const
319 return _rStringValue
.toInt32();
323 struct StringIdentity
325 ::rtl::OUString
operator()( const ::rtl::OUString
& _rValue
) const
331 template < class ElementType
, class Transformer
>
332 ::rtl::OUString
composeSequenceElements( const Sequence
< ElementType
>& _rElements
, const Transformer
& _rTransformer
)
336 // loop through the elements and concatenate the string representations of the integers
337 // (separated by a line break)
338 const ElementType
* pElements
= _rElements
.getConstArray();
339 const ElementType
* pElementsEnd
= pElements
+ _rElements
.getLength();
340 for ( ; pElements
!= pElementsEnd
; ++pElements
)
342 sCompose
+= String( _rTransformer( *pElements
) );
343 if ( pElements
!= pElementsEnd
)
350 template < class ElementType
, class Transformer
>
351 void splitComposedStringToSequence( const ::rtl::OUString
& _rComposed
, Sequence
< ElementType
>& _out_SplitUp
, const Transformer
& _rTransformer
)
353 _out_SplitUp
.realloc( 0 );
354 if ( !_rComposed
.getLength() )
356 sal_Int32 tokenPos
= 0;
359 _out_SplitUp
.realloc( _out_SplitUp
.getLength() + 1 );
360 _out_SplitUp
[ _out_SplitUp
.getLength() - 1 ] = (ElementType
)_rTransformer( _rComposed
.getToken( 0, '\n', tokenPos
) );
362 while ( tokenPos
!= -1 );
366 //--------------------------------------------------------------------
367 bool StringRepresentation::convertGenericValueToString( const uno::Any
& _rValue
, ::rtl::OUString
& _rStringRep
)
369 bool bCanConvert
= true;
371 switch ( _rValue
.getValueTypeClass() )
373 case uno::TypeClass_STRING
:
374 _rValue
>>= _rStringRep
;
377 case uno::TypeClass_BOOLEAN
:
379 ::std::vector
< ::rtl::OUString
> aListEntries
;
380 tools::StringListResource
aRes(PcrRes(RID_RSC_ENUM_YESNO
),aListEntries
);
381 sal_Bool bValue
= sal_False
;
383 _rStringRep
= bValue
? aListEntries
[1] : aListEntries
[0];
387 // some sequence types
388 case uno::TypeClass_SEQUENCE
:
390 Sequence
< ::rtl::OUString
> aStringValues
;
391 Sequence
< sal_Int8
> aInt8Values
;
392 Sequence
< sal_uInt16
> aUInt16Values
;
393 Sequence
< sal_Int16
> aInt16Values
;
394 Sequence
< sal_uInt32
> aUInt32Values
;
395 Sequence
< sal_Int32
> aInt32Values
;
398 if ( _rValue
>>= aStringValues
)
400 _rStringRep
= composeSequenceElements( aStringValues
, StringIdentity() );
403 else if ( _rValue
>>= aInt8Values
)
405 _rStringRep
= composeSequenceElements( aInt8Values
, ConvertIntegerFromAndToString() );
408 else if ( _rValue
>>= aUInt16Values
)
410 _rStringRep
= composeSequenceElements( aUInt16Values
, ConvertIntegerFromAndToString() );
413 else if ( _rValue
>>= aInt16Values
)
415 _rStringRep
= composeSequenceElements( aInt16Values
, ConvertIntegerFromAndToString() );
418 else if ( _rValue
>>= aUInt32Values
)
420 _rStringRep
= composeSequenceElements( aUInt32Values
, ConvertIntegerFromAndToString() );
423 else if ( _rValue
>>= aInt32Values
)
425 _rStringRep
= composeSequenceElements( aInt32Values
, ConvertIntegerFromAndToString() );
431 case uno::TypeClass_CONSTANT
:
439 case uno::TypeClass_STRUCT
:
440 OSL_ENSURE( false, "StringRepresentation::convertGenericValueToString(STRUCT): this is dead code - isn't it?" );
441 if ( _rValue
.getValueType().equals( ::getCppuType( static_cast< util::Date
* >( NULL
) ) ) )
443 // weird enough, the string representation of dates, as used
444 // by the control displaying dates, and thus as passed through the layers,
447 _rValue
>>= aUnoDate
;
448 _rStringRep
= ::dbtools::DBTypeConversion::toDateString(aUnoDate
);
450 else if ( _rValue
.getValueType().equals( ::getCppuType( static_cast< util::Time
* >( NULL
) ) ) )
452 // similar for time (HHMMSSHH)
454 _rValue
>>= aUnoTime
;
455 _rStringRep
= ::dbtools::DBTypeConversion::toTimeString(aUnoTime
);
457 else if ( _rValue
.getValueType().equals( ::getCppuType( static_cast< util::DateTime
* >( NULL
) ) ) )
459 util::DateTime aUnoDateTime
;
460 _rValue
>>= aUnoDateTime
;
461 _rStringRep
= ::dbtools::DBTypeConversion::toDateTimeString(aUnoDateTime
);
474 //------------------------------------------------------------------------
475 uno::Any
StringRepresentation::convertStringToSimple( const ::rtl::OUString
& _rValue
,const uno::TypeClass
& _ePropertyType
)
478 if ( m_xTypeConverter
.is() && _rValue
.getLength() )
482 if ( m_aConstants
.getLength() && m_aValues
.getLength() )
484 const ::rtl::OUString
* pIter
= m_aValues
.getConstArray();
485 const ::rtl::OUString
* pEnd
= pIter
+ m_aValues
.getLength();
486 for(sal_Int32 i
= 0;pIter
!= pEnd
;++pIter
,++i
)
488 if ( *pIter
== _rValue
)
490 OSL_ENSURE(i
< m_aConstants
.getLength() ,"StringRepresentation::convertSimpleToString: Index is not in range of m_aValues");
491 aReturn
<<= m_aConstants
[i
]->getConstantValue();
497 if ( !aReturn
.hasValue() )
498 aReturn
= m_xTypeConverter
->convertToSimpleType( makeAny( _rValue
), _ePropertyType
);
500 catch( script::CannotConvertException
& ) { }
501 catch( lang::IllegalArgumentException
& ) { }
505 //--------------------------------------------------------------------
506 bool StringRepresentation::convertStringToGenericValue( const ::rtl::OUString
& _rStringRep
, uno::Any
& _rValue
, const uno::Type
& _rTargetType
)
508 bool bCanConvert
= true;
510 switch ( _rTargetType
.getTypeClass() )
512 case uno::TypeClass_STRING
:
513 _rValue
<<= _rStringRep
;
516 case uno::TypeClass_BOOLEAN
:
518 ::std::vector
< ::rtl::OUString
> aListEntries
;
519 tools::StringListResource
aRes(PcrRes(RID_RSC_ENUM_YESNO
),aListEntries
);
520 if ( aListEntries
[0] == _rStringRep
)
521 _rValue
<<= (sal_Bool
)sal_False
;
523 _rValue
<<= (sal_Bool
)sal_True
;
527 case uno::TypeClass_SEQUENCE
:
529 uno::Type aElementType
= ::comphelper::getSequenceElementType( _rTargetType
);
531 String
aStr( _rStringRep
);
532 switch ( aElementType
.getTypeClass() )
534 case uno::TypeClass_STRING
:
536 Sequence
< ::rtl::OUString
> aElements
;
537 splitComposedStringToSequence( aStr
, aElements
, StringIdentity() );
538 _rValue
<<= aElements
;
541 case uno::TypeClass_SHORT
:
543 Sequence
< sal_Int16
> aElements
;
544 splitComposedStringToSequence( aStr
, aElements
, ConvertIntegerFromAndToString() );
545 _rValue
<<= aElements
;
548 case uno::TypeClass_UNSIGNED_SHORT
:
550 Sequence
< sal_uInt16
> aElements
;
551 splitComposedStringToSequence( aStr
, aElements
, ConvertIntegerFromAndToString() );
552 _rValue
<<= aElements
;
555 case uno::TypeClass_LONG
:
557 Sequence
< sal_Int32
> aElements
;
558 splitComposedStringToSequence( aStr
, aElements
, ConvertIntegerFromAndToString() );
559 _rValue
<<= aElements
;
562 case uno::TypeClass_UNSIGNED_LONG
:
564 Sequence
< sal_uInt32
> aElements
;
565 splitComposedStringToSequence( aStr
, aElements
, ConvertIntegerFromAndToString() );
566 _rValue
<<= aElements
;
569 case uno::TypeClass_BYTE
:
571 Sequence
< sal_Int8
> aElements
;
572 splitComposedStringToSequence( aStr
, aElements
, ConvertIntegerFromAndToString() );
573 _rValue
<<= aElements
;
583 case uno::TypeClass_STRUCT
:
584 OSL_ENSURE( false, "StringRepresentation::convertStringToGenericValue(STRUCT): this is dead code - isn't it?" );
585 if ( _rTargetType
.equals( ::getCppuType( static_cast< util::Date
* >( NULL
) ) ) )
587 // weird enough, the string representation of dates, as used
588 // by the control displaying dates, and thus as passed through the layers,
591 _rValue
<<= ::dbtools::DBTypeConversion::toDate(_rStringRep
);
593 else if ( _rTargetType
.equals( ::getCppuType( static_cast< util::Time
* >( NULL
) ) ) )
595 // similar for time (HHMMSSHH)
596 _rValue
<<= ::dbtools::DBTypeConversion::toTime(_rStringRep
);
598 else if ( _rTargetType
.equals( ::getCppuType( static_cast< util::DateTime
* >( NULL
) ) ) )
600 _rValue
<<= ::dbtools::DBTypeConversion::toDateTime(_rStringRep
);
613 //------------------------------------------------------------------------
614 //------------------------------------------------------------------------
616 //------------------------------------------------------------------------
619 // component helper namespace
620 namespace comp_StringRepresentation
{
622 ::rtl::OUString SAL_CALL
_getImplementationName() {
623 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
624 "StringRepresentation"));
627 uno::Sequence
< ::rtl::OUString
> SAL_CALL
_getSupportedServiceNames()
629 uno::Sequence
< ::rtl::OUString
> s(1);
630 s
[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
631 "com.sun.star.inspection.StringRepresentation"));
635 uno::Reference
< uno::XInterface
> SAL_CALL
_create(
636 const uno::Reference
< uno::XComponentContext
> & context
)
637 SAL_THROW((uno::Exception
))
639 return static_cast< ::cppu::OWeakObject
* >(new pcr::StringRepresentation(context
));
642 } // closing component helper namespace
644 //------------------------------------------------------------------------
645 extern "C" void SAL_CALL
createRegistryInfo_StringRepresentation()
647 ::pcr::PcrModule::getInstance().registerImplementation(
648 comp_StringRepresentation::_getImplementationName(),
649 comp_StringRepresentation::_getSupportedServiceNames(),
650 comp_StringRepresentation::_create