merged tag LIBREOFFICE_3_2_99_3
[LibreOffice.git] / extensions / source / propctrlr / stringrepresentation.cxx
blobf07d4d60f75624de7a567c1649bc74957ff93f51
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 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
31 #include "sal/config.h"
32 #include "cppuhelper/factory.hxx"
33 #include "cppuhelper/implementationentry.hxx"
34 #include "cppuhelper/implbase3.hxx"
35 #include "com/sun/star/lang/XServiceInfo.hpp"
36 #include "com/sun/star/inspection/XStringRepresentation.hpp"
37 #include "com/sun/star/lang/XInitialization.hpp"
38 #include "com/sun/star/script/XTypeConverter.hpp"
39 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
40 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
41 #include <com/sun/star/beans/XIntrospection.hpp>
42 #include <com/sun/star/util/DateTime.hpp>
43 #include <com/sun/star/util/Date.hpp>
44 #include <com/sun/star/util/Time.hpp>
45 #include <comphelper/sequence.hxx>
46 #include <connectivity/dbconversion.hxx>
47 #include "modulepcr.hxx"
48 #include "formresid.hrc"
49 #include <tools/debug.hxx>
50 #include <tools/string.hxx>
51 #include <tools/StringListResource.hxx>
52 #include <comphelper/types.hxx>
53 #include "modulepcr.hxx"
55 #include <functional>
56 #include <algorithm>
58 // component helper namespace
59 namespace comp_StringRepresentation {
61 using namespace ::com::sun::star;
63 // component and service helper functions:
64 ::rtl::OUString SAL_CALL _getImplementationName();
65 uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames();
66 uno::Reference< uno::XInterface > SAL_CALL _create( uno::Reference< uno::XComponentContext > const & context );
68 } // closing component helper namespace
71 namespace pcr{
73 using namespace ::com::sun::star;
74 using namespace ::com::sun::star::uno;
76 class StringRepresentation:
77 public ::cppu::WeakImplHelper3<
78 lang::XServiceInfo,
79 inspection::XStringRepresentation,
80 lang::XInitialization>
82 public:
83 explicit StringRepresentation(uno::Reference< uno::XComponentContext > const & context);
85 // lang::XServiceInfo:
86 virtual ::rtl::OUString SAL_CALL getImplementationName() throw (uno::RuntimeException);
87 virtual ::sal_Bool SAL_CALL supportsService(const ::rtl::OUString & ServiceName) throw (uno::RuntimeException);
88 virtual uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (uno::RuntimeException);
90 // inspection::XStringRepresentation:
91 virtual ::rtl::OUString SAL_CALL convertToControlValue(const uno::Any & PropertyValue) throw (uno::RuntimeException, uno::Exception);
92 virtual uno::Any SAL_CALL convertToPropertyValue(const ::rtl::OUString & ControlValue, const uno::Type & ControlValueType) throw (uno::RuntimeException, uno::Exception);
94 // lang::XInitialization:
95 virtual void SAL_CALL initialize(const uno::Sequence< uno::Any > & aArguments) throw (uno::RuntimeException, uno::Exception);
97 private:
98 StringRepresentation(StringRepresentation &); // not defined
99 void operator =(StringRepresentation &); // not defined
101 virtual ~StringRepresentation() {}
103 /** converts a generic value into a string representation
105 If you want to convert values whose string representation does not depend
106 on a concrete property, use this version
108 @return <TRUE/>
109 if and only if the value could be converted
111 bool convertGenericValueToString(
112 const uno::Any& _rValue,
113 ::rtl::OUString& _rStringRep
116 /** converts string representation into generic value
118 If you want to convert values whose string representation does not depend
119 on a concrete property, use this version
121 @return <TRUE/>
122 if and only if the value could be converted
124 bool convertStringToGenericValue(
125 const ::rtl::OUString& _rStringRep,
126 uno::Any& _rValue,
127 const uno::Type& _rTargetType
130 /** uses the simple convert method from the type converter
132 * \param _rValue the value to be converted
133 * \return the converted string.
135 ::rtl::OUString convertSimpleToString( const uno::Any& _rValue );
137 /** converts a string into his constant value if it exists, otherwise the type converter is used.
138 * \param _rValue the value to be converted
139 * \param _ePropertyType teh type of the propery to be converted into
140 * \return the converted value
142 uno::Any convertStringToSimple( const ::rtl::OUString& _rValue,const uno::TypeClass& _ePropertyType );
144 uno::Reference< uno::XComponentContext > m_xContext;
145 uno::Reference< script::XTypeConverter > m_xTypeConverter;
146 uno::Reference< reflection::XConstantsTypeDescription > m_xTypeDescription;
147 uno::Sequence< ::rtl::OUString > m_aValues;
148 uno::Sequence< uno::Reference< reflection::XConstantTypeDescription> > m_aConstants;
152 StringRepresentation::StringRepresentation(uno::Reference< uno::XComponentContext > const & context) :
153 m_xContext(context)
156 // com.sun.star.uno.XServiceInfo:
157 ::rtl::OUString SAL_CALL StringRepresentation::getImplementationName() throw (uno::RuntimeException)
159 return comp_StringRepresentation::_getImplementationName();
162 ::sal_Bool SAL_CALL StringRepresentation::supportsService(::rtl::OUString const & serviceName) throw (uno::RuntimeException)
164 return ::comphelper::existsValue(serviceName,comp_StringRepresentation::_getSupportedServiceNames());
167 uno::Sequence< ::rtl::OUString > SAL_CALL StringRepresentation::getSupportedServiceNames() throw (uno::RuntimeException)
169 return comp_StringRepresentation::_getSupportedServiceNames();
172 // inspection::XStringRepresentation:
173 ::rtl::OUString SAL_CALL StringRepresentation::convertToControlValue(const uno::Any & PropertyValue) throw (uno::RuntimeException, uno::Exception)
175 ::rtl::OUString sReturn;
176 if ( !convertGenericValueToString( PropertyValue, sReturn ) )
178 sReturn = convertSimpleToString( PropertyValue );
179 #ifdef DBG_UTIL
180 if ( !sReturn.getLength() && PropertyValue.hasValue() )
182 ::rtl::OString sMessage( "StringRepresentation::convertPropertyValueToStringRepresentation: cannot convert values of type '" );
183 sMessage += ::rtl::OString( PropertyValue.getValueType().getTypeName().getStr(), PropertyValue.getValueType().getTypeName().getLength(), RTL_TEXTENCODING_ASCII_US );
184 sMessage += ::rtl::OString( "'!" );
185 DBG_ERROR( sMessage.getStr() );
187 #endif
190 return sReturn;
193 uno::Any SAL_CALL StringRepresentation::convertToPropertyValue(const ::rtl::OUString & ControlValue, const uno::Type & ControlValueType) throw (uno::RuntimeException, uno::Exception)
195 uno::Any aReturn;
197 uno::TypeClass ePropertyType = ControlValueType.getTypeClass();
198 switch ( ePropertyType )
200 case uno::TypeClass_FLOAT:
201 case uno::TypeClass_DOUBLE:
202 case uno::TypeClass_BYTE:
203 case uno::TypeClass_SHORT:
204 case uno::TypeClass_LONG:
205 case uno::TypeClass_HYPER:
206 case uno::TypeClass_UNSIGNED_SHORT:
207 case uno::TypeClass_UNSIGNED_LONG:
208 case uno::TypeClass_UNSIGNED_HYPER:
211 aReturn = convertStringToSimple(ControlValue, ePropertyType);
213 catch( const script::CannotConvertException& ) { }
214 catch( const lang::IllegalArgumentException& ) { }
215 break;
217 default:
218 #if OSL_DEBUG_LEVEL > 0
219 bool bCanConvert =
220 #endif
221 convertStringToGenericValue( ControlValue, aReturn, ControlValueType );
223 #if OSL_DEBUG_LEVEL > 0
224 // could not convert ...
225 if ( !bCanConvert && ControlValue.getLength() )
227 ::rtl::OString sMessage( "StringRepresentation::convertStringRepresentationToPropertyValue: cannot convert into values of type '" );
228 sMessage += ::rtl::OString( ControlValueType.getTypeName().getStr(), ControlValueType.getTypeName().getLength(), RTL_TEXTENCODING_ASCII_US );
229 sMessage += ::rtl::OString( "'!" );
230 DBG_ERROR( sMessage.getStr() );
232 #endif
235 return aReturn;
238 // lang::XInitialization:
239 void SAL_CALL StringRepresentation::initialize(const uno::Sequence< uno::Any > & aArguments) throw (uno::RuntimeException, uno::Exception)
241 sal_Int32 nLength = aArguments.getLength();
242 if ( nLength )
244 const uno::Any* pIter = aArguments.getConstArray();
245 m_xTypeConverter.set(*pIter++,uno::UNO_QUERY);
246 if ( nLength == 3 )
248 ::rtl::OUString sConstantName;
249 *pIter++ >>= sConstantName;
250 *pIter >>= m_aValues;
252 if ( m_xContext.is() )
254 uno::Reference< container::XHierarchicalNameAccess > xTypeDescProv(
255 m_xContext->getValueByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) ) ),
256 uno::UNO_QUERY_THROW );
258 m_xTypeDescription.set( xTypeDescProv->getByHierarchicalName( sConstantName ), uno::UNO_QUERY_THROW );
259 m_aConstants = m_xTypeDescription->getConstants();
264 //------------------------------------------------------------------------
265 ::rtl::OUString StringRepresentation::convertSimpleToString( const uno::Any& _rValue )
267 ::rtl::OUString sReturn;
268 if ( m_xTypeConverter.is() && _rValue.hasValue() )
272 if ( m_aConstants.getLength() )
274 sal_Int16 nConstantValue = 0;
275 if ( _rValue >>= nConstantValue )
277 const uno::Reference< reflection::XConstantTypeDescription>* pIter = m_aConstants.getConstArray();
278 const uno::Reference< reflection::XConstantTypeDescription>* pEnd = pIter + m_aConstants.getLength();
279 for(sal_Int32 i = 0;pIter != pEnd;++pIter,++i)
281 if ( (*pIter)->getConstantValue() == _rValue )
283 OSL_ENSURE(i < m_aValues.getLength() ,"StringRepresentation::convertSimpleToString: Index is not in range of m_aValues");
284 sReturn = m_aValues[i];
285 break;
291 if ( !sReturn.getLength() )
292 m_xTypeConverter->convertToSimpleType( _rValue, uno::TypeClass_STRING ) >>= sReturn;
294 catch( script::CannotConvertException& ) { }
295 catch( lang::IllegalArgumentException& ) { }
297 return sReturn;
300 //--------------------------------------------------------------------
301 namespace
303 struct ConvertIntegerFromAndToString
305 ::rtl::OUString operator()( sal_Int32 _rIntValue ) const
307 return ::rtl::OUString::valueOf( (sal_Int32)_rIntValue );
309 sal_Int32 operator()( const ::rtl::OUString& _rStringValue ) const
311 return _rStringValue.toInt32();
315 struct StringIdentity
317 ::rtl::OUString operator()( const ::rtl::OUString& _rValue ) const
319 return _rValue;
323 template < class ElementType, class Transformer >
324 ::rtl::OUString composeSequenceElements( const Sequence< ElementType >& _rElements, const Transformer& _rTransformer )
326 String sCompose;
328 // loop through the elements and concatenate the string representations of the integers
329 // (separated by a line break)
330 const ElementType* pElements = _rElements.getConstArray();
331 const ElementType* pElementsEnd = pElements + _rElements.getLength();
332 for ( ; pElements != pElementsEnd; ++pElements )
334 sCompose += String( _rTransformer( *pElements ) );
335 if ( pElements != pElementsEnd )
336 sCompose += '\n';
339 return sCompose;
342 template < class ElementType, class Transformer >
343 void splitComposedStringToSequence( const ::rtl::OUString& _rComposed, Sequence< ElementType >& _out_SplitUp, const Transformer& _rTransformer )
345 _out_SplitUp.realloc( 0 );
346 if ( !_rComposed.getLength() )
347 return;
348 sal_Int32 tokenPos = 0;
351 _out_SplitUp.realloc( _out_SplitUp.getLength() + 1 );
352 _out_SplitUp[ _out_SplitUp.getLength() - 1 ] = (ElementType)_rTransformer( _rComposed.getToken( 0, '\n', tokenPos ) );
354 while ( tokenPos != -1 );
358 //--------------------------------------------------------------------
359 bool StringRepresentation::convertGenericValueToString( const uno::Any& _rValue, ::rtl::OUString& _rStringRep )
361 bool bCanConvert = true;
363 switch ( _rValue.getValueTypeClass() )
365 case uno::TypeClass_STRING:
366 _rValue >>= _rStringRep;
367 break;
369 case uno::TypeClass_BOOLEAN:
371 ::std::vector< ::rtl::OUString > aListEntries;
372 tools::StringListResource aRes(PcrRes(RID_RSC_ENUM_YESNO),aListEntries);
373 sal_Bool bValue = sal_False;
374 _rValue >>= bValue;
375 _rStringRep = bValue ? aListEntries[1] : aListEntries[0];
377 break;
379 // some sequence types
380 case uno::TypeClass_SEQUENCE:
382 Sequence< ::rtl::OUString > aStringValues;
383 Sequence< sal_Int8 > aInt8Values;
384 Sequence< sal_uInt16 > aUInt16Values;
385 Sequence< sal_Int16 > aInt16Values;
386 Sequence< sal_uInt32 > aUInt32Values;
387 Sequence< sal_Int32 > aInt32Values;
389 // string sequences
390 if ( _rValue >>= aStringValues )
392 _rStringRep = composeSequenceElements( aStringValues, StringIdentity() );
394 // byte sequences
395 else if ( _rValue >>= aInt8Values )
397 _rStringRep = composeSequenceElements( aInt8Values, ConvertIntegerFromAndToString() );
399 // uInt16 sequences
400 else if ( _rValue >>= aUInt16Values )
402 _rStringRep = composeSequenceElements( aUInt16Values, ConvertIntegerFromAndToString() );
404 // Int16 sequences
405 else if ( _rValue >>= aInt16Values )
407 _rStringRep = composeSequenceElements( aInt16Values, ConvertIntegerFromAndToString() );
409 // uInt32 sequences
410 else if ( _rValue >>= aUInt32Values )
412 _rStringRep = composeSequenceElements( aUInt32Values, ConvertIntegerFromAndToString() );
414 // Int32 sequences
415 else if ( _rValue >>= aInt32Values )
417 _rStringRep = composeSequenceElements( aInt32Values, ConvertIntegerFromAndToString() );
419 else
420 bCanConvert = false;
422 break;
423 case uno::TypeClass_CONSTANT:
425 int i = 0;
426 ++i;
428 break;
430 // some structs
431 case uno::TypeClass_STRUCT:
432 OSL_ENSURE( false, "StringRepresentation::convertGenericValueToString(STRUCT): this is dead code - isn't it?" );
433 if ( _rValue.getValueType().equals( ::getCppuType( static_cast< util::Date* >( NULL ) ) ) )
435 // weird enough, the string representation of dates, as used
436 // by the control displaying dates, and thus as passed through the layers,
437 // is YYYYMMDD.
438 util::Date aUnoDate;
439 _rValue >>= aUnoDate;
440 _rStringRep = ::dbtools::DBTypeConversion::toDateString(aUnoDate);
442 else if ( _rValue.getValueType().equals( ::getCppuType( static_cast< util::Time* >( NULL ) ) ) )
444 // similar for time (HHMMSSHH)
445 util::Time aUnoTime;
446 _rValue >>= aUnoTime;
447 _rStringRep = ::dbtools::DBTypeConversion::toTimeString(aUnoTime);
449 else if ( _rValue.getValueType().equals( ::getCppuType( static_cast< util::DateTime* >( NULL ) ) ) )
451 util::DateTime aUnoDateTime;
452 _rValue >>= aUnoDateTime;
453 _rStringRep = ::dbtools::DBTypeConversion::toDateTimeString(aUnoDateTime);
455 else
456 bCanConvert = false;
457 break;
459 default:
460 bCanConvert = false;
461 break;
464 return bCanConvert;
466 //------------------------------------------------------------------------
467 uno::Any StringRepresentation::convertStringToSimple( const ::rtl::OUString& _rValue,const uno::TypeClass& _ePropertyType )
469 uno::Any aReturn;
470 if ( m_xTypeConverter.is() && _rValue.getLength() )
474 if ( m_aConstants.getLength() && m_aValues.getLength() )
476 const ::rtl::OUString* pIter = m_aValues.getConstArray();
477 const ::rtl::OUString* pEnd = pIter + m_aValues.getLength();
478 for(sal_Int32 i = 0;pIter != pEnd;++pIter,++i)
480 if ( *pIter == _rValue )
482 OSL_ENSURE(i < m_aConstants.getLength() ,"StringRepresentation::convertSimpleToString: Index is not in range of m_aValues");
483 aReturn <<= m_aConstants[i]->getConstantValue();
484 break;
489 if ( !aReturn.hasValue() )
490 aReturn = m_xTypeConverter->convertToSimpleType( makeAny( _rValue ), _ePropertyType );
492 catch( script::CannotConvertException& ) { }
493 catch( lang::IllegalArgumentException& ) { }
495 return aReturn;
497 //--------------------------------------------------------------------
498 bool StringRepresentation::convertStringToGenericValue( const ::rtl::OUString& _rStringRep, uno::Any& _rValue, const uno::Type& _rTargetType )
500 bool bCanConvert = true;
502 switch ( _rTargetType.getTypeClass() )
504 case uno::TypeClass_STRING:
505 _rValue <<= _rStringRep;
506 break;
508 case uno::TypeClass_BOOLEAN:
510 ::std::vector< ::rtl::OUString > aListEntries;
511 tools::StringListResource aRes(PcrRes(RID_RSC_ENUM_YESNO),aListEntries);
512 if ( aListEntries[0] == _rStringRep )
513 _rValue <<= (sal_Bool)sal_False;
514 else
515 _rValue <<= (sal_Bool)sal_True;
517 break;
519 case uno::TypeClass_SEQUENCE:
521 uno::Type aElementType = ::comphelper::getSequenceElementType( _rTargetType );
523 String aStr( _rStringRep );
524 switch ( aElementType.getTypeClass() )
526 case uno::TypeClass_STRING:
528 Sequence< ::rtl::OUString > aElements;
529 splitComposedStringToSequence( aStr, aElements, StringIdentity() );
530 _rValue <<= aElements;
532 break;
533 case uno::TypeClass_SHORT:
535 Sequence< sal_Int16 > aElements;
536 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
537 _rValue <<= aElements;
539 break;
540 case uno::TypeClass_UNSIGNED_SHORT:
542 Sequence< sal_uInt16 > aElements;
543 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
544 _rValue <<= aElements;
546 break;
547 case uno::TypeClass_LONG:
549 Sequence< sal_Int32 > aElements;
550 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
551 _rValue <<= aElements;
553 break;
554 case uno::TypeClass_UNSIGNED_LONG:
556 Sequence< sal_uInt32 > aElements;
557 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
558 _rValue <<= aElements;
560 break;
561 case uno::TypeClass_BYTE:
563 Sequence< sal_Int8 > aElements;
564 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
565 _rValue <<= aElements;
567 break;
568 default:
569 bCanConvert = false;
570 break;
573 break;
575 case uno::TypeClass_STRUCT:
576 OSL_ENSURE( false, "StringRepresentation::convertStringToGenericValue(STRUCT): this is dead code - isn't it?" );
577 if ( _rTargetType.equals( ::getCppuType( static_cast< util::Date* >( NULL ) ) ) )
579 // weird enough, the string representation of dates, as used
580 // by the control displaying dates, and thus as passed through the layers,
581 // is YYYYMMDD.
583 _rValue <<= ::dbtools::DBTypeConversion::toDate(_rStringRep);
585 else if ( _rTargetType.equals( ::getCppuType( static_cast< util::Time* >( NULL ) ) ) )
587 // similar for time (HHMMSSHH)
588 _rValue <<= ::dbtools::DBTypeConversion::toTime(_rStringRep);
590 else if ( _rTargetType.equals( ::getCppuType( static_cast< util::DateTime* >( NULL ) ) ) )
592 _rValue <<= ::dbtools::DBTypeConversion::toDateTime(_rStringRep);
594 else
595 bCanConvert = false;
596 break;
598 default:
599 bCanConvert = false;
600 break;
603 return bCanConvert;
605 //------------------------------------------------------------------------
606 //------------------------------------------------------------------------
607 } // pcr
608 //------------------------------------------------------------------------
611 // component helper namespace
612 namespace comp_StringRepresentation {
614 ::rtl::OUString SAL_CALL _getImplementationName() {
615 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
616 "StringRepresentation"));
619 uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
621 uno::Sequence< ::rtl::OUString > s(1);
622 s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
623 "com.sun.star.inspection.StringRepresentation"));
624 return s;
627 uno::Reference< uno::XInterface > SAL_CALL _create(
628 const uno::Reference< uno::XComponentContext > & context)
629 SAL_THROW((uno::Exception))
631 return static_cast< ::cppu::OWeakObject * >(new pcr::StringRepresentation(context));
634 } // closing component helper namespace
636 //------------------------------------------------------------------------
637 extern "C" void SAL_CALL createRegistryInfo_StringRepresentation()
639 ::pcr::PcrModule::getInstance().registerImplementation(
640 comp_StringRepresentation::_getImplementationName(),
641 comp_StringRepresentation::_getSupportedServiceNames(),
642 comp_StringRepresentation::_create
646 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */