Bump for 3.6-28
[LibreOffice.git] / extensions / source / propctrlr / stringrepresentation.cxx
blobb44230ac07cf0b49f5decdb999d0999bfdc5e81e
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"
52 #include <functional>
53 #include <algorithm>
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
68 namespace pcr{
70 using namespace ::com::sun::star;
71 using namespace ::com::sun::star::uno;
73 class StringRepresentation:
74 public ::cppu::WeakImplHelper3<
75 lang::XServiceInfo,
76 inspection::XStringRepresentation,
77 lang::XInitialization>
79 public:
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);
94 private:
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
105 @return <TRUE/>
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
118 @return <TRUE/>
119 if and only if the value could be converted
121 bool convertStringToGenericValue(
122 const ::rtl::OUString& _rStringRep,
123 uno::Any& _rValue,
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) :
150 m_xContext(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 );
176 #ifdef DBG_UTIL
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() );
184 #endif
187 return sReturn;
190 uno::Any SAL_CALL StringRepresentation::convertToPropertyValue(const ::rtl::OUString & ControlValue, const uno::Type & ControlValueType) throw (uno::RuntimeException, uno::Exception)
192 uno::Any aReturn;
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& ) { }
212 break;
214 default:
215 #if OSL_DEBUG_LEVEL > 0
216 bool bCanConvert =
217 #endif
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() );
229 #endif
232 return aReturn;
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();
239 if ( nLength )
241 const uno::Any* pIter = aArguments.getConstArray();
242 m_xTypeConverter.set(*pIter++,uno::UNO_QUERY);
243 if ( nLength == 3 )
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];
282 break;
288 if ( sReturn.isEmpty() )
289 m_xTypeConverter->convertToSimpleType( _rValue, uno::TypeClass_STRING ) >>= sReturn;
291 catch( const script::CannotConvertException& ) { }
292 catch( const lang::IllegalArgumentException& ) { }
294 return sReturn;
297 //--------------------------------------------------------------------
298 namespace
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
316 return _rValue;
320 template < class ElementType, class Transformer >
321 ::rtl::OUString composeSequenceElements( const Sequence< ElementType >& _rElements, const Transformer& _rTransformer )
323 String sCompose;
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 )
333 sCompose += '\n';
336 return sCompose;
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() )
344 return;
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;
364 break;
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;
371 _rValue >>= bValue;
372 _rStringRep = bValue ? aListEntries[1] : aListEntries[0];
374 break;
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;
386 // string sequences
387 if ( _rValue >>= aStringValues )
389 _rStringRep = composeSequenceElements( aStringValues, StringIdentity() );
391 // byte sequences
392 else if ( _rValue >>= aInt8Values )
394 _rStringRep = composeSequenceElements( aInt8Values, ConvertIntegerFromAndToString() );
396 // uInt16 sequences
397 else if ( _rValue >>= aUInt16Values )
399 _rStringRep = composeSequenceElements( aUInt16Values, ConvertIntegerFromAndToString() );
401 // Int16 sequences
402 else if ( _rValue >>= aInt16Values )
404 _rStringRep = composeSequenceElements( aInt16Values, ConvertIntegerFromAndToString() );
406 // uInt32 sequences
407 else if ( _rValue >>= aUInt32Values )
409 _rStringRep = composeSequenceElements( aUInt32Values, ConvertIntegerFromAndToString() );
411 // Int32 sequences
412 else if ( _rValue >>= aInt32Values )
414 _rStringRep = composeSequenceElements( aInt32Values, ConvertIntegerFromAndToString() );
416 else
417 bCanConvert = false;
419 break;
420 case uno::TypeClass_CONSTANT:
422 int i = 0;
423 ++i;
425 break;
427 // some structs
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,
434 // is YYYYMMDD.
435 util::Date aUnoDate;
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)
442 util::Time aUnoTime;
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);
452 else
453 bCanConvert = false;
454 break;
456 default:
457 bCanConvert = false;
458 break;
461 return bCanConvert;
463 //------------------------------------------------------------------------
464 uno::Any StringRepresentation::convertStringToSimple( const ::rtl::OUString& _rValue,const uno::TypeClass& _ePropertyType )
466 uno::Any aReturn;
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();
481 break;
486 if ( !aReturn.hasValue() )
487 aReturn = m_xTypeConverter->convertToSimpleType( makeAny( _rValue ), _ePropertyType );
489 catch( const script::CannotConvertException& ) { }
490 catch( const lang::IllegalArgumentException& ) { }
492 return aReturn;
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;
503 break;
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;
511 else
512 _rValue <<= (sal_Bool)sal_True;
514 break;
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;
529 break;
530 case uno::TypeClass_SHORT:
532 Sequence< sal_Int16 > aElements;
533 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
534 _rValue <<= aElements;
536 break;
537 case uno::TypeClass_UNSIGNED_SHORT:
539 Sequence< sal_uInt16 > aElements;
540 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
541 _rValue <<= aElements;
543 break;
544 case uno::TypeClass_LONG:
546 Sequence< sal_Int32 > aElements;
547 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
548 _rValue <<= aElements;
550 break;
551 case uno::TypeClass_UNSIGNED_LONG:
553 Sequence< sal_uInt32 > aElements;
554 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
555 _rValue <<= aElements;
557 break;
558 case uno::TypeClass_BYTE:
560 Sequence< sal_Int8 > aElements;
561 splitComposedStringToSequence( aStr, aElements, ConvertIntegerFromAndToString() );
562 _rValue <<= aElements;
564 break;
565 default:
566 bCanConvert = false;
567 break;
570 break;
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,
578 // is YYYYMMDD.
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);
591 else
592 bCanConvert = false;
593 break;
595 default:
596 bCanConvert = false;
597 break;
600 return bCanConvert;
602 //------------------------------------------------------------------------
603 //------------------------------------------------------------------------
604 } // pcr
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"));
621 return s;
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: */