masterfix DEV300: #i10000# build fix
[LibreOffice.git] / extensions / source / propctrlr / stringrepresentation.cxx
blob2897ba57d9e65bfba59c61af3efbf4ea15433f0d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
27 // MARKER(update_precomp.py): autogen include statement, do not remove
28 #include "precompiled_extensions.hxx"
30 #include "sal/config.h"
31 #include "cppuhelper/factory.hxx"
32 #include "cppuhelper/implementationentry.hxx"
33 #include "cppuhelper/implbase3.hxx"
34 #include "com/sun/star/lang/XServiceInfo.hpp"
35 #include "com/sun/star/inspection/XStringRepresentation.hpp"
36 #include "com/sun/star/lang/XInitialization.hpp"
37 #include "com/sun/star/script/XTypeConverter.hpp"
38 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
39 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
40 #include <com/sun/star/beans/XIntrospection.hpp>
41 #include <com/sun/star/util/DateTime.hpp>
42 #include <com/sun/star/util/Date.hpp>
43 #include <com/sun/star/util/Time.hpp>
44 #include <comphelper/sequence.hxx>
45 #include <connectivity/dbconversion.hxx>
46 #ifndef _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_
47 #include "modulepcr.hxx"
48 #endif
49 #ifndef _EXTENSIONS_FORMCTRLR_PROPRESID_HRC_
50 #include "formresid.hrc"
51 #endif
52 #include <tools/debug.hxx>
53 #include <tools/string.hxx>
54 #include <tools/StringListResource.hxx>
55 #include <comphelper/types.hxx>
56 #ifndef _EXTENSIONS_PROPCTRLR_MODULEPCR_HXX_
57 #include "modulepcr.hxx"
58 #endif
60 #include <functional>
61 #include <algorithm>
63 // component helper namespace
64 namespace comp_StringRepresentation {
66 using namespace ::com::sun::star;
68 // component and service helper functions:
69 ::rtl::OUString SAL_CALL _getImplementationName();
70 uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames();
71 uno::Reference< uno::XInterface > SAL_CALL _create( uno::Reference< uno::XComponentContext > const & context );
73 } // closing component helper namespace
76 namespace pcr{
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::uno;
81 class StringRepresentation:
82 public ::cppu::WeakImplHelper3<
83 lang::XServiceInfo,
84 inspection::XStringRepresentation,
85 lang::XInitialization>
87 public:
88 explicit StringRepresentation(uno::Reference< uno::XComponentContext > const & context);
90 // lang::XServiceInfo:
91 virtual ::rtl::OUString SAL_CALL getImplementationName() throw (uno::RuntimeException);
92 virtual ::sal_Bool SAL_CALL supportsService(const ::rtl::OUString & ServiceName) throw (uno::RuntimeException);
93 virtual uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (uno::RuntimeException);
95 // inspection::XStringRepresentation:
96 virtual ::rtl::OUString SAL_CALL convertToControlValue(const uno::Any & PropertyValue) throw (uno::RuntimeException, uno::Exception);
97 virtual uno::Any SAL_CALL convertToPropertyValue(const ::rtl::OUString & ControlValue, const uno::Type & ControlValueType) throw (uno::RuntimeException, uno::Exception);
99 // lang::XInitialization:
100 virtual void SAL_CALL initialize(const uno::Sequence< uno::Any > & aArguments) throw (uno::RuntimeException, uno::Exception);
102 private:
103 StringRepresentation(StringRepresentation &); // not defined
104 void operator =(StringRepresentation &); // not defined
106 virtual ~StringRepresentation() {}
108 /** converts a generic value into a string representation
110 If you want to convert values whose string representation does not depend
111 on a concrete property, use this version
113 @return <TRUE/>
114 if and only if the value could be converted
116 bool convertGenericValueToString(
117 const uno::Any& _rValue,
118 ::rtl::OUString& _rStringRep
121 /** converts string representation into generic value
123 If you want to convert values whose string representation does not depend
124 on a concrete property, use this version
126 @return <TRUE/>
127 if and only if the value could be converted
129 bool convertStringToGenericValue(
130 const ::rtl::OUString& _rStringRep,
131 uno::Any& _rValue,
132 const uno::Type& _rTargetType
135 /** uses the simple convert method from the type converter
137 * \param _rValue the value to be converted
138 * \return the converted string.
140 ::rtl::OUString convertSimpleToString( const uno::Any& _rValue );
142 /** converts a string into his constant value if it exists, otherwise the type converter is used.
143 * \param _rValue the value to be converted
144 * \param _ePropertyType teh type of the propery to be converted into
145 * \return the converted value
147 uno::Any convertStringToSimple( const ::rtl::OUString& _rValue,const uno::TypeClass& _ePropertyType );
149 uno::Reference< uno::XComponentContext > m_xContext;
150 uno::Reference< script::XTypeConverter > m_xTypeConverter;
151 uno::Reference< reflection::XConstantsTypeDescription > m_xTypeDescription;
152 uno::Sequence< ::rtl::OUString > m_aValues;
153 uno::Sequence< uno::Reference< reflection::XConstantTypeDescription> > m_aConstants;
157 StringRepresentation::StringRepresentation(uno::Reference< uno::XComponentContext > const & context) :
158 m_xContext(context)
161 // com.sun.star.uno.XServiceInfo:
162 ::rtl::OUString SAL_CALL StringRepresentation::getImplementationName() throw (uno::RuntimeException)
164 return comp_StringRepresentation::_getImplementationName();
167 ::sal_Bool SAL_CALL StringRepresentation::supportsService(::rtl::OUString const & serviceName) throw (uno::RuntimeException)
169 return ::comphelper::existsValue(serviceName,comp_StringRepresentation::_getSupportedServiceNames());
172 uno::Sequence< ::rtl::OUString > SAL_CALL StringRepresentation::getSupportedServiceNames() throw (uno::RuntimeException)
174 return comp_StringRepresentation::_getSupportedServiceNames();
177 // inspection::XStringRepresentation:
178 ::rtl::OUString SAL_CALL StringRepresentation::convertToControlValue(const uno::Any & PropertyValue) throw (uno::RuntimeException, uno::Exception)
180 ::rtl::OUString sReturn;
181 if ( !convertGenericValueToString( PropertyValue, sReturn ) )
183 sReturn = convertSimpleToString( PropertyValue );
184 #ifdef DBG_UTIL
185 if ( !sReturn.getLength() && PropertyValue.hasValue() )
187 ::rtl::OString sMessage( "StringRepresentation::convertPropertyValueToStringRepresentation: cannot convert values of type '" );
188 sMessage += ::rtl::OString( PropertyValue.getValueType().getTypeName().getStr(), PropertyValue.getValueType().getTypeName().getLength(), RTL_TEXTENCODING_ASCII_US );
189 sMessage += ::rtl::OString( "'!" );
190 DBG_ERROR( sMessage.getStr() );
192 #endif
195 return sReturn;
198 uno::Any SAL_CALL StringRepresentation::convertToPropertyValue(const ::rtl::OUString & ControlValue, const uno::Type & ControlValueType) throw (uno::RuntimeException, uno::Exception)
200 uno::Any aReturn;
202 uno::TypeClass ePropertyType = ControlValueType.getTypeClass();
203 switch ( ePropertyType )
205 case uno::TypeClass_FLOAT:
206 case uno::TypeClass_DOUBLE:
207 case uno::TypeClass_BYTE:
208 case uno::TypeClass_SHORT:
209 case uno::TypeClass_LONG:
210 case uno::TypeClass_HYPER:
211 case uno::TypeClass_UNSIGNED_SHORT:
212 case uno::TypeClass_UNSIGNED_LONG:
213 case uno::TypeClass_UNSIGNED_HYPER:
216 aReturn = convertStringToSimple(ControlValue, ePropertyType);
218 catch( const script::CannotConvertException& ) { }
219 catch( const lang::IllegalArgumentException& ) { }
220 break;
222 default:
223 #if OSL_DEBUG_LEVEL > 0
224 bool bCanConvert =
225 #endif
226 convertStringToGenericValue( ControlValue, aReturn, ControlValueType );
228 #if OSL_DEBUG_LEVEL > 0
229 // could not convert ...
230 if ( !bCanConvert && ControlValue.getLength() )
232 ::rtl::OString sMessage( "StringRepresentation::convertStringRepresentationToPropertyValue: cannot convert into values of type '" );
233 sMessage += ::rtl::OString( ControlValueType.getTypeName().getStr(), ControlValueType.getTypeName().getLength(), RTL_TEXTENCODING_ASCII_US );
234 sMessage += ::rtl::OString( "'!" );
235 DBG_ERROR( sMessage.getStr() );
237 #endif
240 return aReturn;
243 // lang::XInitialization:
244 void SAL_CALL StringRepresentation::initialize(const uno::Sequence< uno::Any > & aArguments) throw (uno::RuntimeException, uno::Exception)
246 sal_Int32 nLength = aArguments.getLength();
247 if ( nLength )
249 const uno::Any* pIter = aArguments.getConstArray();
250 m_xTypeConverter.set(*pIter++,uno::UNO_QUERY);
251 if ( nLength == 3 )
253 ::rtl::OUString sConstantName;
254 *pIter++ >>= sConstantName;
255 *pIter >>= m_aValues;
257 if ( m_xContext.is() )
259 uno::Reference< container::XHierarchicalNameAccess > xTypeDescProv(
260 m_xContext->getValueByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) ) ),
261 uno::UNO_QUERY_THROW );
263 m_xTypeDescription.set( xTypeDescProv->getByHierarchicalName( sConstantName ), uno::UNO_QUERY_THROW );
264 m_aConstants = m_xTypeDescription->getConstants();
269 //------------------------------------------------------------------------
270 ::rtl::OUString StringRepresentation::convertSimpleToString( const uno::Any& _rValue )
272 ::rtl::OUString sReturn;
273 if ( m_xTypeConverter.is() && _rValue.hasValue() )
277 if ( m_aConstants.getLength() )
279 sal_Int16 nConstantValue = 0;
280 if ( _rValue >>= nConstantValue )
282 const uno::Reference< reflection::XConstantTypeDescription>* pIter = m_aConstants.getConstArray();
283 const uno::Reference< reflection::XConstantTypeDescription>* pEnd = pIter + m_aConstants.getLength();
284 for(sal_Int32 i = 0;pIter != pEnd;++pIter,++i)
286 if ( (*pIter)->getConstantValue() == _rValue )
288 OSL_ENSURE(i < m_aValues.getLength() ,"StringRepresentation::convertSimpleToString: Index is not in range of m_aValues");
289 sReturn = m_aValues[i];
290 break;
296 if ( !sReturn.getLength() )
297 m_xTypeConverter->convertToSimpleType( _rValue, uno::TypeClass_STRING ) >>= sReturn;
299 catch( script::CannotConvertException& ) { }
300 catch( lang::IllegalArgumentException& ) { }
302 return sReturn;
305 //--------------------------------------------------------------------
306 namespace
308 struct ConvertIntegerFromAndToString
310 ::rtl::OUString operator()( sal_Int32 _rIntValue ) const
312 return ::rtl::OUString::valueOf( (sal_Int32)_rIntValue );
314 sal_Int32 operator()( const ::rtl::OUString& _rStringValue ) const
316 return _rStringValue.toInt32();
320 struct StringIdentity
322 ::rtl::OUString operator()( const ::rtl::OUString& _rValue ) const
324 return _rValue;
328 template < class ElementType, class Transformer >
329 ::rtl::OUString composeSequenceElements( const Sequence< ElementType >& _rElements, const Transformer& _rTransformer )
331 String sCompose;
333 // loop through the elements and concatenate the string representations of the integers
334 // (separated by a line break)
335 const ElementType* pElements = _rElements.getConstArray();
336 const ElementType* pElementsEnd = pElements + _rElements.getLength();
337 for ( ; pElements != pElementsEnd; ++pElements )
339 sCompose += String( _rTransformer( *pElements ) );
340 if ( pElements != pElementsEnd )
341 sCompose += '\n';
344 return sCompose;
347 template < class ElementType, class Transformer >
348 void splitComposedStringToSequence( const ::rtl::OUString& _rComposed, Sequence< ElementType >& _out_SplitUp, const Transformer& _rTransformer )
350 _out_SplitUp.realloc( 0 );
351 if ( !_rComposed.getLength() )
352 return;
353 sal_Int32 tokenPos = 0;
356 _out_SplitUp.realloc( _out_SplitUp.getLength() + 1 );
357 _out_SplitUp[ _out_SplitUp.getLength() - 1 ] = (ElementType)_rTransformer( _rComposed.getToken( 0, '\n', tokenPos ) );
359 while ( tokenPos != -1 );
363 //--------------------------------------------------------------------
364 bool StringRepresentation::convertGenericValueToString( const uno::Any& _rValue, ::rtl::OUString& _rStringRep )
366 bool bCanConvert = true;
368 switch ( _rValue.getValueTypeClass() )
370 case uno::TypeClass_STRING:
371 _rValue >>= _rStringRep;
372 break;
374 case uno::TypeClass_BOOLEAN:
376 ::std::vector< ::rtl::OUString > aListEntries;
377 tools::StringListResource aRes(PcrRes(RID_RSC_ENUM_YESNO),aListEntries);
378 sal_Bool bValue = sal_False;
379 _rValue >>= bValue;
380 _rStringRep = bValue ? aListEntries[1] : aListEntries[0];
382 break;
384 // some sequence types
385 case uno::TypeClass_SEQUENCE:
387 Sequence< ::rtl::OUString > aStringValues;
388 Sequence< sal_Int8 > aInt8Values;
389 Sequence< sal_uInt16 > aUInt16Values;
390 Sequence< sal_Int16 > aInt16Values;
391 Sequence< sal_uInt32 > aUInt32Values;
392 Sequence< sal_Int32 > aInt32Values;
394 // string sequences
395 if ( _rValue >>= aStringValues )
397 _rStringRep = composeSequenceElements( aStringValues, StringIdentity() );
399 // byte sequences
400 else if ( _rValue >>= aInt8Values )
402 _rStringRep = composeSequenceElements( aInt8Values, ConvertIntegerFromAndToString() );
404 // uInt16 sequences
405 else if ( _rValue >>= aUInt16Values )
407 _rStringRep = composeSequenceElements( aUInt16Values, ConvertIntegerFromAndToString() );
409 // Int16 sequences
410 else if ( _rValue >>= aInt16Values )
412 _rStringRep = composeSequenceElements( aInt16Values, ConvertIntegerFromAndToString() );
414 // uInt32 sequences
415 else if ( _rValue >>= aUInt32Values )
417 _rStringRep = composeSequenceElements( aUInt32Values, ConvertIntegerFromAndToString() );
419 // Int32 sequences
420 else if ( _rValue >>= aInt32Values )
422 _rStringRep = composeSequenceElements( aInt32Values, ConvertIntegerFromAndToString() );
424 else
425 bCanConvert = false;
427 break;
428 case uno::TypeClass_CONSTANT:
430 int i = 0;
431 ++i;
433 break;
435 // some structs
436 case uno::TypeClass_STRUCT:
437 OSL_ENSURE( false, "StringRepresentation::convertGenericValueToString(STRUCT): this is dead code - isn't it?" );
438 if ( _rValue.getValueType().equals( ::getCppuType( static_cast< util::Date* >( NULL ) ) ) )
440 // weird enough, the string representation of dates, as used
441 // by the control displaying dates, and thus as passed through the layers,
442 // is YYYYMMDD.
443 util::Date aUnoDate;
444 _rValue >>= aUnoDate;
445 _rStringRep = ::dbtools::DBTypeConversion::toDateString(aUnoDate);
447 else if ( _rValue.getValueType().equals( ::getCppuType( static_cast< util::Time* >( NULL ) ) ) )
449 // similar for time (HHMMSSHH)
450 util::Time aUnoTime;
451 _rValue >>= aUnoTime;
452 _rStringRep = ::dbtools::DBTypeConversion::toTimeString(aUnoTime);
454 else if ( _rValue.getValueType().equals( ::getCppuType( static_cast< util::DateTime* >( NULL ) ) ) )
456 util::DateTime aUnoDateTime;
457 _rValue >>= aUnoDateTime;
458 _rStringRep = ::dbtools::DBTypeConversion::toDateTimeString(aUnoDateTime);
460 else
461 bCanConvert = false;
462 break;
464 default:
465 bCanConvert = false;
466 break;
469 return bCanConvert;
471 //------------------------------------------------------------------------
472 uno::Any StringRepresentation::convertStringToSimple( const ::rtl::OUString& _rValue,const uno::TypeClass& _ePropertyType )
474 uno::Any aReturn;
475 if ( m_xTypeConverter.is() && _rValue.getLength() )
479 if ( m_aConstants.getLength() && m_aValues.getLength() )
481 const ::rtl::OUString* pIter = m_aValues.getConstArray();
482 const ::rtl::OUString* pEnd = pIter + m_aValues.getLength();
483 for(sal_Int32 i = 0;pIter != pEnd;++pIter,++i)
485 if ( *pIter == _rValue )
487 OSL_ENSURE(i < m_aConstants.getLength() ,"StringRepresentation::convertSimpleToString: Index is not in range of m_aValues");
488 aReturn <<= m_aConstants[i]->getConstantValue();
489 break;
494 if ( !aReturn.hasValue() )
495 aReturn = m_xTypeConverter->convertToSimpleType( makeAny( _rValue ), _ePropertyType );
497 catch( script::CannotConvertException& ) { }
498 catch( lang::IllegalArgumentException& ) { }
500 return aReturn;
502 //--------------------------------------------------------------------
503 bool StringRepresentation::convertStringToGenericValue( const ::rtl::OUString& _rStringRep, uno::Any& _rValue, const uno::Type& _rTargetType )
505 bool bCanConvert = true;
507 switch ( _rTargetType.getTypeClass() )
509 case uno::TypeClass_STRING:
510 _rValue <<= _rStringRep;
511 break;
513 case uno::TypeClass_BOOLEAN:
515 ::std::vector< ::rtl::OUString > aListEntries;
516 tools::StringListResource aRes(PcrRes(RID_RSC_ENUM_YESNO),aListEntries);
517 if ( aListEntries[0] == _rStringRep )
518 _rValue <<= (sal_Bool)sal_False;
519 else
520 _rValue <<= (sal_Bool)sal_True;
522 break;
524 case uno::TypeClass_SEQUENCE:
526 uno::Type aElementType = ::comphelper::getSequenceElementType( _rTargetType );
528 String aStr( _rStringRep );
529 switch ( aElementType.getTypeClass() )
531 case uno::TypeClass_STRING:
533 Sequence< ::rtl::OUString > aElements;
534 splitComposedStringToSequence( aStr, aElements, StringIdentity() );
535 _rValue <<= aElements;
537 break;
538 case uno::TypeClass_SHORT:
540 Sequence< sal_Int16 > aElements;
541 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
542 _rValue <<= aElements;
544 break;
545 case uno::TypeClass_UNSIGNED_SHORT:
547 Sequence< sal_uInt16 > aElements;
548 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
549 _rValue <<= aElements;
551 break;
552 case uno::TypeClass_LONG:
554 Sequence< sal_Int32 > aElements;
555 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
556 _rValue <<= aElements;
558 break;
559 case uno::TypeClass_UNSIGNED_LONG:
561 Sequence< sal_uInt32 > aElements;
562 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
563 _rValue <<= aElements;
565 break;
566 case uno::TypeClass_BYTE:
568 Sequence< sal_Int8 > aElements;
569 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
570 _rValue <<= aElements;
572 break;
573 default:
574 bCanConvert = false;
575 break;
578 break;
580 case uno::TypeClass_STRUCT:
581 OSL_ENSURE( false, "StringRepresentation::convertStringToGenericValue(STRUCT): this is dead code - isn't it?" );
582 if ( _rTargetType.equals( ::getCppuType( static_cast< util::Date* >( NULL ) ) ) )
584 // weird enough, the string representation of dates, as used
585 // by the control displaying dates, and thus as passed through the layers,
586 // is YYYYMMDD.
588 _rValue <<= ::dbtools::DBTypeConversion::toDate(_rStringRep);
590 else if ( _rTargetType.equals( ::getCppuType( static_cast< util::Time* >( NULL ) ) ) )
592 // similar for time (HHMMSSHH)
593 _rValue <<= ::dbtools::DBTypeConversion::toTime(_rStringRep);
595 else if ( _rTargetType.equals( ::getCppuType( static_cast< util::DateTime* >( NULL ) ) ) )
597 _rValue <<= ::dbtools::DBTypeConversion::toDateTime(_rStringRep);
599 else
600 bCanConvert = false;
601 break;
603 default:
604 bCanConvert = false;
605 break;
608 return bCanConvert;
610 //------------------------------------------------------------------------
611 //------------------------------------------------------------------------
612 } // pcr
613 //------------------------------------------------------------------------
616 // component helper namespace
617 namespace comp_StringRepresentation {
619 ::rtl::OUString SAL_CALL _getImplementationName() {
620 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
621 "StringRepresentation"));
624 uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
626 uno::Sequence< ::rtl::OUString > s(1);
627 s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
628 "com.sun.star.inspection.StringRepresentation"));
629 return s;
632 uno::Reference< uno::XInterface > SAL_CALL _create(
633 const uno::Reference< uno::XComponentContext > & context)
634 SAL_THROW((uno::Exception))
636 return static_cast< ::cppu::OWeakObject * >(new pcr::StringRepresentation(context));
639 } // closing component helper namespace
641 //------------------------------------------------------------------------
642 extern "C" void SAL_CALL createRegistryInfo_StringRepresentation()
644 ::pcr::PcrModule::getInstance().registerImplementation(
645 comp_StringRepresentation::_getImplementationName(),
646 comp_StringRepresentation::_getSupportedServiceNames(),
647 comp_StringRepresentation::_create