1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "sal/config.h"
30 #include "cppuhelper/factory.hxx"
31 #include "cppuhelper/implementationentry.hxx"
32 #include "cppuhelper/implbase3.hxx"
33 #include "com/sun/star/lang/XServiceInfo.hpp"
34 #include "com/sun/star/inspection/XStringRepresentation.hpp"
35 #include "com/sun/star/lang/XInitialization.hpp"
36 #include "com/sun/star/script/XTypeConverter.hpp"
37 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
38 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
39 #include <com/sun/star/beans/XIntrospection.hpp>
40 #include <com/sun/star/util/DateTime.hpp>
41 #include <com/sun/star/util/Date.hpp>
42 #include <com/sun/star/util/Time.hpp>
43 #include <comphelper/sequence.hxx>
44 #include <connectivity/dbconversion.hxx>
45 #include "formresid.hrc"
46 #include <tools/debug.hxx>
47 #include <tools/string.hxx>
48 #include <tools/StringListResource.hxx>
49 #include <comphelper/types.hxx>
50 #include "modulepcr.hxx"
55 // component helper namespace
56 namespace comp_StringRepresentation
{
58 using namespace ::com::sun::star
;
60 // component and service helper functions:
61 ::rtl::OUString SAL_CALL
_getImplementationName();
62 uno::Sequence
< ::rtl::OUString
> SAL_CALL
_getSupportedServiceNames();
63 uno::Reference
< uno::XInterface
> SAL_CALL
_create( uno::Reference
< uno::XComponentContext
> const & context
);
65 } // closing component helper namespace
70 using namespace ::com::sun::star
;
71 using namespace ::com::sun::star::uno
;
73 class StringRepresentation
:
74 public ::cppu::WeakImplHelper3
<
76 inspection::XStringRepresentation
,
77 lang::XInitialization
>
80 explicit StringRepresentation(uno::Reference
< uno::XComponentContext
> const & context
);
82 // lang::XServiceInfo:
83 virtual ::rtl::OUString SAL_CALL
getImplementationName() throw (uno::RuntimeException
);
84 virtual ::sal_Bool SAL_CALL
supportsService(const ::rtl::OUString
& ServiceName
) throw (uno::RuntimeException
);
85 virtual uno::Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames() throw (uno::RuntimeException
);
87 // inspection::XStringRepresentation:
88 virtual ::rtl::OUString SAL_CALL
convertToControlValue(const uno::Any
& PropertyValue
) throw (uno::RuntimeException
, uno::Exception
);
89 virtual uno::Any SAL_CALL
convertToPropertyValue(const ::rtl::OUString
& ControlValue
, const uno::Type
& ControlValueType
) throw (uno::RuntimeException
, uno::Exception
);
91 // lang::XInitialization:
92 virtual void SAL_CALL
initialize(const uno::Sequence
< uno::Any
> & aArguments
) throw (uno::RuntimeException
, uno::Exception
);
95 StringRepresentation(StringRepresentation
&); // not defined
96 void operator =(StringRepresentation
&); // not defined
98 virtual ~StringRepresentation() {}
100 /** converts a generic value into a string representation
102 If you want to convert values whose string representation does not depend
103 on a concrete property, use this version
106 if and only if the value could be converted
108 bool convertGenericValueToString(
109 const uno::Any
& _rValue
,
110 ::rtl::OUString
& _rStringRep
113 /** converts string representation into generic value
115 If you want to convert values whose string representation does not depend
116 on a concrete property, use this version
119 if and only if the value could be converted
121 bool convertStringToGenericValue(
122 const ::rtl::OUString
& _rStringRep
,
124 const uno::Type
& _rTargetType
127 /** uses the simple convert method from the type converter
129 * \param _rValue the value to be converted
130 * \return the converted string.
132 ::rtl::OUString
convertSimpleToString( const uno::Any
& _rValue
);
134 /** converts a string into his constant value if it exists, otherwise the type converter is used.
135 * \param _rValue the value to be converted
136 * \param _ePropertyType teh type of the propery to be converted into
137 * \return the converted value
139 uno::Any
convertStringToSimple( const ::rtl::OUString
& _rValue
,const uno::TypeClass
& _ePropertyType
);
141 uno::Reference
< uno::XComponentContext
> m_xContext
;
142 uno::Reference
< script::XTypeConverter
> m_xTypeConverter
;
143 uno::Reference
< reflection::XConstantsTypeDescription
> m_xTypeDescription
;
144 uno::Sequence
< ::rtl::OUString
> m_aValues
;
145 uno::Sequence
< uno::Reference
< reflection::XConstantTypeDescription
> > m_aConstants
;
149 StringRepresentation::StringRepresentation(uno::Reference
< uno::XComponentContext
> const & context
) :
153 // com.sun.star.uno.XServiceInfo:
154 ::rtl::OUString SAL_CALL
StringRepresentation::getImplementationName() throw (uno::RuntimeException
)
156 return comp_StringRepresentation::_getImplementationName();
159 ::sal_Bool SAL_CALL
StringRepresentation::supportsService(::rtl::OUString
const & serviceName
) throw (uno::RuntimeException
)
161 return ::comphelper::existsValue(serviceName
,comp_StringRepresentation::_getSupportedServiceNames());
164 uno::Sequence
< ::rtl::OUString
> SAL_CALL
StringRepresentation::getSupportedServiceNames() throw (uno::RuntimeException
)
166 return comp_StringRepresentation::_getSupportedServiceNames();
169 // inspection::XStringRepresentation:
170 ::rtl::OUString SAL_CALL
StringRepresentation::convertToControlValue(const uno::Any
& PropertyValue
) throw (uno::RuntimeException
, uno::Exception
)
172 ::rtl::OUString sReturn
;
173 if ( !convertGenericValueToString( PropertyValue
, sReturn
) )
175 sReturn
= convertSimpleToString( PropertyValue
);
177 if ( sReturn
.isEmpty() && PropertyValue
.hasValue() )
179 ::rtl::OString
sMessage( "StringRepresentation::convertPropertyValueToStringRepresentation: cannot convert values of type '" );
180 sMessage
+= ::rtl::OString( PropertyValue
.getValueType().getTypeName().getStr(), PropertyValue
.getValueType().getTypeName().getLength(), RTL_TEXTENCODING_ASCII_US
);
181 sMessage
+= ::rtl::OString( "'!" );
182 OSL_FAIL( sMessage
.getStr() );
190 uno::Any SAL_CALL
StringRepresentation::convertToPropertyValue(const ::rtl::OUString
& ControlValue
, const uno::Type
& ControlValueType
) throw (uno::RuntimeException
, uno::Exception
)
194 uno::TypeClass ePropertyType
= ControlValueType
.getTypeClass();
195 switch ( ePropertyType
)
197 case uno::TypeClass_FLOAT
:
198 case uno::TypeClass_DOUBLE
:
199 case uno::TypeClass_BYTE
:
200 case uno::TypeClass_SHORT
:
201 case uno::TypeClass_LONG
:
202 case uno::TypeClass_HYPER
:
203 case uno::TypeClass_UNSIGNED_SHORT
:
204 case uno::TypeClass_UNSIGNED_LONG
:
205 case uno::TypeClass_UNSIGNED_HYPER
:
208 aReturn
= convertStringToSimple(ControlValue
, ePropertyType
);
210 catch( const script::CannotConvertException
& ) { }
211 catch( const lang::IllegalArgumentException
& ) { }
215 #if OSL_DEBUG_LEVEL > 0
218 convertStringToGenericValue( ControlValue
, aReturn
, ControlValueType
);
220 #if OSL_DEBUG_LEVEL > 0
221 // could not convert ...
222 if ( !bCanConvert
&& !ControlValue
.isEmpty() )
224 ::rtl::OString
sMessage( "StringRepresentation::convertStringRepresentationToPropertyValue: cannot convert into values of type '" );
225 sMessage
+= ::rtl::OString( ControlValueType
.getTypeName().getStr(), ControlValueType
.getTypeName().getLength(), RTL_TEXTENCODING_ASCII_US
);
226 sMessage
+= ::rtl::OString( "'!" );
227 OSL_FAIL( sMessage
.getStr() );
235 // lang::XInitialization:
236 void SAL_CALL
StringRepresentation::initialize(const uno::Sequence
< uno::Any
> & aArguments
) throw (uno::RuntimeException
, uno::Exception
)
238 sal_Int32 nLength
= aArguments
.getLength();
241 const uno::Any
* pIter
= aArguments
.getConstArray();
242 m_xTypeConverter
.set(*pIter
++,uno::UNO_QUERY
);
245 ::rtl::OUString sConstantName
;
246 *pIter
++ >>= sConstantName
;
247 *pIter
>>= m_aValues
;
249 if ( m_xContext
.is() )
251 uno::Reference
< container::XHierarchicalNameAccess
> xTypeDescProv(
252 m_xContext
->getValueByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) ) ),
253 uno::UNO_QUERY_THROW
);
255 m_xTypeDescription
.set( xTypeDescProv
->getByHierarchicalName( sConstantName
), uno::UNO_QUERY_THROW
);
256 m_aConstants
= m_xTypeDescription
->getConstants();
261 //------------------------------------------------------------------------
262 ::rtl::OUString
StringRepresentation::convertSimpleToString( const uno::Any
& _rValue
)
264 ::rtl::OUString sReturn
;
265 if ( m_xTypeConverter
.is() && _rValue
.hasValue() )
269 if ( m_aConstants
.getLength() )
271 sal_Int16 nConstantValue
= 0;
272 if ( _rValue
>>= nConstantValue
)
274 const uno::Reference
< reflection::XConstantTypeDescription
>* pIter
= m_aConstants
.getConstArray();
275 const uno::Reference
< reflection::XConstantTypeDescription
>* pEnd
= pIter
+ m_aConstants
.getLength();
276 for(sal_Int32 i
= 0;pIter
!= pEnd
;++pIter
,++i
)
278 if ( (*pIter
)->getConstantValue() == _rValue
)
280 OSL_ENSURE(i
< m_aValues
.getLength() ,"StringRepresentation::convertSimpleToString: Index is not in range of m_aValues");
281 sReturn
= m_aValues
[i
];
288 if ( sReturn
.isEmpty() )
289 m_xTypeConverter
->convertToSimpleType( _rValue
, uno::TypeClass_STRING
) >>= sReturn
;
291 catch( const script::CannotConvertException
& ) { }
292 catch( const lang::IllegalArgumentException
& ) { }
297 //--------------------------------------------------------------------
300 struct ConvertIntegerFromAndToString
302 ::rtl::OUString
operator()( sal_Int32 _rIntValue
) const
304 return ::rtl::OUString::valueOf( (sal_Int32
)_rIntValue
);
306 sal_Int32
operator()( const ::rtl::OUString
& _rStringValue
) const
308 return _rStringValue
.toInt32();
312 struct StringIdentity
314 ::rtl::OUString
operator()( const ::rtl::OUString
& _rValue
) const
320 template < class ElementType
, class Transformer
>
321 ::rtl::OUString
composeSequenceElements( const Sequence
< ElementType
>& _rElements
, const Transformer
& _rTransformer
)
325 // loop through the elements and concatenate the string representations of the integers
326 // (separated by a line break)
327 const ElementType
* pElements
= _rElements
.getConstArray();
328 const ElementType
* pElementsEnd
= pElements
+ _rElements
.getLength();
329 for ( ; pElements
!= pElementsEnd
; ++pElements
)
331 sCompose
+= String( _rTransformer( *pElements
) );
332 if ( pElements
!= pElementsEnd
)
339 template < class ElementType
, class Transformer
>
340 void splitComposedStringToSequence( const ::rtl::OUString
& _rComposed
, Sequence
< ElementType
>& _out_SplitUp
, const Transformer
& _rTransformer
)
342 _out_SplitUp
.realloc( 0 );
343 if ( _rComposed
.isEmpty() )
345 sal_Int32 tokenPos
= 0;
348 _out_SplitUp
.realloc( _out_SplitUp
.getLength() + 1 );
349 _out_SplitUp
[ _out_SplitUp
.getLength() - 1 ] = (ElementType
)_rTransformer( _rComposed
.getToken( 0, '\n', tokenPos
) );
351 while ( tokenPos
!= -1 );
355 //--------------------------------------------------------------------
356 bool StringRepresentation::convertGenericValueToString( const uno::Any
& _rValue
, ::rtl::OUString
& _rStringRep
)
358 bool bCanConvert
= true;
360 switch ( _rValue
.getValueTypeClass() )
362 case uno::TypeClass_STRING
:
363 _rValue
>>= _rStringRep
;
366 case uno::TypeClass_BOOLEAN
:
368 ::std::vector
< ::rtl::OUString
> aListEntries
;
369 tools::StringListResource
aRes(PcrRes(RID_RSC_ENUM_YESNO
),aListEntries
);
370 sal_Bool bValue
= sal_False
;
372 _rStringRep
= bValue
? aListEntries
[1] : aListEntries
[0];
376 // some sequence types
377 case uno::TypeClass_SEQUENCE
:
379 Sequence
< ::rtl::OUString
> aStringValues
;
380 Sequence
< sal_Int8
> aInt8Values
;
381 Sequence
< sal_uInt16
> aUInt16Values
;
382 Sequence
< sal_Int16
> aInt16Values
;
383 Sequence
< sal_uInt32
> aUInt32Values
;
384 Sequence
< sal_Int32
> aInt32Values
;
387 if ( _rValue
>>= aStringValues
)
389 _rStringRep
= composeSequenceElements( aStringValues
, StringIdentity() );
392 else if ( _rValue
>>= aInt8Values
)
394 _rStringRep
= composeSequenceElements( aInt8Values
, ConvertIntegerFromAndToString() );
397 else if ( _rValue
>>= aUInt16Values
)
399 _rStringRep
= composeSequenceElements( aUInt16Values
, ConvertIntegerFromAndToString() );
402 else if ( _rValue
>>= aInt16Values
)
404 _rStringRep
= composeSequenceElements( aInt16Values
, ConvertIntegerFromAndToString() );
407 else if ( _rValue
>>= aUInt32Values
)
409 _rStringRep
= composeSequenceElements( aUInt32Values
, ConvertIntegerFromAndToString() );
412 else if ( _rValue
>>= aInt32Values
)
414 _rStringRep
= composeSequenceElements( aInt32Values
, ConvertIntegerFromAndToString() );
420 case uno::TypeClass_CONSTANT
:
428 case uno::TypeClass_STRUCT
:
429 OSL_FAIL( "StringRepresentation::convertGenericValueToString(STRUCT): this is dead code - isn't it?" );
430 if ( _rValue
.getValueType().equals( ::getCppuType( static_cast< util::Date
* >( NULL
) ) ) )
432 // weird enough, the string representation of dates, as used
433 // by the control displaying dates, and thus as passed through the layers,
436 _rValue
>>= aUnoDate
;
437 _rStringRep
= ::dbtools::DBTypeConversion::toDateString(aUnoDate
);
439 else if ( _rValue
.getValueType().equals( ::getCppuType( static_cast< util::Time
* >( NULL
) ) ) )
441 // similar for time (HHMMSSHH)
443 _rValue
>>= aUnoTime
;
444 _rStringRep
= ::dbtools::DBTypeConversion::toTimeString(aUnoTime
);
446 else if ( _rValue
.getValueType().equals( ::getCppuType( static_cast< util::DateTime
* >( NULL
) ) ) )
448 util::DateTime aUnoDateTime
;
449 _rValue
>>= aUnoDateTime
;
450 _rStringRep
= ::dbtools::DBTypeConversion::toDateTimeString(aUnoDateTime
);
463 //------------------------------------------------------------------------
464 uno::Any
StringRepresentation::convertStringToSimple( const ::rtl::OUString
& _rValue
,const uno::TypeClass
& _ePropertyType
)
467 if ( m_xTypeConverter
.is() && !_rValue
.isEmpty() )
471 if ( m_aConstants
.getLength() && m_aValues
.getLength() )
473 const ::rtl::OUString
* pIter
= m_aValues
.getConstArray();
474 const ::rtl::OUString
* pEnd
= pIter
+ m_aValues
.getLength();
475 for(sal_Int32 i
= 0;pIter
!= pEnd
;++pIter
,++i
)
477 if ( *pIter
== _rValue
)
479 OSL_ENSURE(i
< m_aConstants
.getLength() ,"StringRepresentation::convertSimpleToString: Index is not in range of m_aValues");
480 aReturn
<<= m_aConstants
[i
]->getConstantValue();
486 if ( !aReturn
.hasValue() )
487 aReturn
= m_xTypeConverter
->convertToSimpleType( makeAny( _rValue
), _ePropertyType
);
489 catch( const script::CannotConvertException
& ) { }
490 catch( const lang::IllegalArgumentException
& ) { }
494 //--------------------------------------------------------------------
495 bool StringRepresentation::convertStringToGenericValue( const ::rtl::OUString
& _rStringRep
, uno::Any
& _rValue
, const uno::Type
& _rTargetType
)
497 bool bCanConvert
= true;
499 switch ( _rTargetType
.getTypeClass() )
501 case uno::TypeClass_STRING
:
502 _rValue
<<= _rStringRep
;
505 case uno::TypeClass_BOOLEAN
:
507 ::std::vector
< ::rtl::OUString
> aListEntries
;
508 tools::StringListResource
aRes(PcrRes(RID_RSC_ENUM_YESNO
),aListEntries
);
509 if ( aListEntries
[0] == _rStringRep
)
510 _rValue
<<= (sal_Bool
)sal_False
;
512 _rValue
<<= (sal_Bool
)sal_True
;
516 case uno::TypeClass_SEQUENCE
:
518 uno::Type aElementType
= ::comphelper::getSequenceElementType( _rTargetType
);
520 String
aStr( _rStringRep
);
521 switch ( aElementType
.getTypeClass() )
523 case uno::TypeClass_STRING
:
525 Sequence
< ::rtl::OUString
> aElements
;
526 splitComposedStringToSequence( aStr
, aElements
, StringIdentity() );
527 _rValue
<<= aElements
;
530 case uno::TypeClass_SHORT
:
532 Sequence
< sal_Int16
> aElements
;
533 splitComposedStringToSequence( aStr
, aElements
, ConvertIntegerFromAndToString() );
534 _rValue
<<= aElements
;
537 case uno::TypeClass_UNSIGNED_SHORT
:
539 Sequence
< sal_uInt16
> aElements
;
540 splitComposedStringToSequence( aStr
, aElements
, ConvertIntegerFromAndToString() );
541 _rValue
<<= aElements
;
544 case uno::TypeClass_LONG
:
546 Sequence
< sal_Int32
> aElements
;
547 splitComposedStringToSequence( aStr
, aElements
, ConvertIntegerFromAndToString() );
548 _rValue
<<= aElements
;
551 case uno::TypeClass_UNSIGNED_LONG
:
553 Sequence
< sal_uInt32
> aElements
;
554 splitComposedStringToSequence( aStr
, aElements
, ConvertIntegerFromAndToString() );
555 _rValue
<<= aElements
;
558 case uno::TypeClass_BYTE
:
560 Sequence
< sal_Int8
> aElements
;
561 splitComposedStringToSequence( aStr
, aElements
, ConvertIntegerFromAndToString() );
562 _rValue
<<= aElements
;
572 case uno::TypeClass_STRUCT
:
573 OSL_FAIL( "StringRepresentation::convertStringToGenericValue(STRUCT): this is dead code - isn't it?" );
574 if ( _rTargetType
.equals( ::getCppuType( static_cast< util::Date
* >( NULL
) ) ) )
576 // weird enough, the string representation of dates, as used
577 // by the control displaying dates, and thus as passed through the layers,
580 _rValue
<<= ::dbtools::DBTypeConversion::toDate(_rStringRep
);
582 else if ( _rTargetType
.equals( ::getCppuType( static_cast< util::Time
* >( NULL
) ) ) )
584 // similar for time (HHMMSSHH)
585 _rValue
<<= ::dbtools::DBTypeConversion::toTime(_rStringRep
);
587 else if ( _rTargetType
.equals( ::getCppuType( static_cast< util::DateTime
* >( NULL
) ) ) )
589 _rValue
<<= ::dbtools::DBTypeConversion::toDateTime(_rStringRep
);
602 //------------------------------------------------------------------------
603 //------------------------------------------------------------------------
605 //------------------------------------------------------------------------
608 // component helper namespace
609 namespace comp_StringRepresentation
{
611 ::rtl::OUString SAL_CALL
_getImplementationName() {
612 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
613 "StringRepresentation"));
616 uno::Sequence
< ::rtl::OUString
> SAL_CALL
_getSupportedServiceNames()
618 uno::Sequence
< ::rtl::OUString
> s(1);
619 s
[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
620 "com.sun.star.inspection.StringRepresentation"));
624 uno::Reference
< uno::XInterface
> SAL_CALL
_create(
625 const uno::Reference
< uno::XComponentContext
> & context
)
626 SAL_THROW((uno::Exception
))
628 return static_cast< ::cppu::OWeakObject
* >(new pcr::StringRepresentation(context
));
631 } // closing component helper namespace
633 //------------------------------------------------------------------------
634 extern "C" void SAL_CALL
createRegistryInfo_StringRepresentation()
636 ::pcr::PcrModule::getInstance().registerImplementation(
637 comp_StringRepresentation::_getImplementationName(),
638 comp_StringRepresentation::_getSupportedServiceNames(),
639 comp_StringRepresentation::_create
643 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */