merge the formfield patch from ooo-build
[ooovba.git] / extensions / source / propctrlr / stringrepresentation.cxx
blob28d869461edaa8b17aa2ac4a599bafb40408553f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: stringrepresentation.cxx,v $
10 * $Revision: 1.8 $
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"
51 #endif
52 #ifndef _EXTENSIONS_FORMCTRLR_PROPRESID_HRC_
53 #include "formresid.hrc"
54 #endif
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"
61 #endif
63 #include <functional>
64 #include <algorithm>
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
79 namespace pcr{
81 using namespace ::com::sun::star;
82 using namespace ::com::sun::star::uno;
84 class StringRepresentation:
85 public ::cppu::WeakImplHelper3<
86 lang::XServiceInfo,
87 inspection::XStringRepresentation,
88 lang::XInitialization>
90 public:
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);
105 private:
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
116 @return <TRUE/>
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
129 @return <TRUE/>
130 if and only if the value could be converted
132 bool convertStringToGenericValue(
133 const ::rtl::OUString& _rStringRep,
134 uno::Any& _rValue,
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) :
161 m_xContext(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 );
187 #ifdef DBG_UTIL
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() );
195 #endif
198 return sReturn;
201 uno::Any SAL_CALL StringRepresentation::convertToPropertyValue(const ::rtl::OUString & ControlValue, const uno::Type & ControlValueType) throw (uno::RuntimeException, uno::Exception)
203 uno::Any aReturn;
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& ) { }
223 break;
225 default:
226 #if OSL_DEBUG_LEVEL > 0
227 bool bCanConvert =
228 #endif
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() );
240 #endif
243 return aReturn;
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();
250 if ( nLength )
252 const uno::Any* pIter = aArguments.getConstArray();
253 m_xTypeConverter.set(*pIter++,uno::UNO_QUERY);
254 if ( nLength == 3 )
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];
293 break;
299 if ( !sReturn.getLength() )
300 m_xTypeConverter->convertToSimpleType( _rValue, uno::TypeClass_STRING ) >>= sReturn;
302 catch( script::CannotConvertException& ) { }
303 catch( lang::IllegalArgumentException& ) { }
305 return sReturn;
308 //--------------------------------------------------------------------
309 namespace
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
327 return _rValue;
331 template < class ElementType, class Transformer >
332 ::rtl::OUString composeSequenceElements( const Sequence< ElementType >& _rElements, const Transformer& _rTransformer )
334 String sCompose;
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 )
344 sCompose += '\n';
347 return sCompose;
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() )
355 return;
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;
375 break;
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;
382 _rValue >>= bValue;
383 _rStringRep = bValue ? aListEntries[1] : aListEntries[0];
385 break;
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;
397 // string sequences
398 if ( _rValue >>= aStringValues )
400 _rStringRep = composeSequenceElements( aStringValues, StringIdentity() );
402 // byte sequences
403 else if ( _rValue >>= aInt8Values )
405 _rStringRep = composeSequenceElements( aInt8Values, ConvertIntegerFromAndToString() );
407 // uInt16 sequences
408 else if ( _rValue >>= aUInt16Values )
410 _rStringRep = composeSequenceElements( aUInt16Values, ConvertIntegerFromAndToString() );
412 // Int16 sequences
413 else if ( _rValue >>= aInt16Values )
415 _rStringRep = composeSequenceElements( aInt16Values, ConvertIntegerFromAndToString() );
417 // uInt32 sequences
418 else if ( _rValue >>= aUInt32Values )
420 _rStringRep = composeSequenceElements( aUInt32Values, ConvertIntegerFromAndToString() );
422 // Int32 sequences
423 else if ( _rValue >>= aInt32Values )
425 _rStringRep = composeSequenceElements( aInt32Values, ConvertIntegerFromAndToString() );
427 else
428 bCanConvert = false;
430 break;
431 case uno::TypeClass_CONSTANT:
433 int i = 0;
434 ++i;
436 break;
438 // some structs
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,
445 // is YYYYMMDD.
446 util::Date aUnoDate;
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)
453 util::Time aUnoTime;
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);
463 else
464 bCanConvert = false;
465 break;
467 default:
468 bCanConvert = false;
469 break;
472 return bCanConvert;
474 //------------------------------------------------------------------------
475 uno::Any StringRepresentation::convertStringToSimple( const ::rtl::OUString& _rValue,const uno::TypeClass& _ePropertyType )
477 uno::Any aReturn;
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();
492 break;
497 if ( !aReturn.hasValue() )
498 aReturn = m_xTypeConverter->convertToSimpleType( makeAny( _rValue ), _ePropertyType );
500 catch( script::CannotConvertException& ) { }
501 catch( lang::IllegalArgumentException& ) { }
503 return aReturn;
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;
514 break;
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;
522 else
523 _rValue <<= (sal_Bool)sal_True;
525 break;
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;
540 break;
541 case uno::TypeClass_SHORT:
543 Sequence< sal_Int16 > aElements;
544 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
545 _rValue <<= aElements;
547 break;
548 case uno::TypeClass_UNSIGNED_SHORT:
550 Sequence< sal_uInt16 > aElements;
551 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
552 _rValue <<= aElements;
554 break;
555 case uno::TypeClass_LONG:
557 Sequence< sal_Int32 > aElements;
558 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
559 _rValue <<= aElements;
561 break;
562 case uno::TypeClass_UNSIGNED_LONG:
564 Sequence< sal_uInt32 > aElements;
565 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
566 _rValue <<= aElements;
568 break;
569 case uno::TypeClass_BYTE:
571 Sequence< sal_Int8 > aElements;
572 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
573 _rValue <<= aElements;
575 break;
576 default:
577 bCanConvert = false;
578 break;
581 break;
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,
589 // is YYYYMMDD.
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);
602 else
603 bCanConvert = false;
604 break;
606 default:
607 bCanConvert = false;
608 break;
611 return bCanConvert;
613 //------------------------------------------------------------------------
614 //------------------------------------------------------------------------
615 } // pcr
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"));
632 return s;
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