diff options
author | Oliver Bolte <obo@openoffice.org> | 2008-02-26 14:15:27 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2008-02-26 14:15:27 +0000 |
commit | be5168bfb9757d7293398f07615e204b89c0020e (patch) | |
tree | 064443f156a5b2d0ee2ae6c5306c97c3d892bf4a /comphelper | |
parent | e6d9e0b2a029aa12c0fb6776e3efd4425a8eeb6d (diff) |
INTEGRATION: CWS custommeta (1.1.2); FILE ADDED
2008/02/11 09:43:58 mst 1.1.2.3: - comphelper/source/property/opropertybag.cxx:
+ remove use of debug stuff from module tools
2008/02/05 16:43:45 mst 1.1.2.2: - comphelper/source/property/opropertybag.cxx:
+ wntmsci11 warning fix
2008/02/05 10:52:48 mst 1.1.2.1: move service Propertybag from dbaccess to comphelper
- comphelper/source/property/opropertybag.{hxx,cxx}:
+ move OPropertyBag here (from dbaccess)
- comphelper/source/misc/facreg.cxx:
+ register PropertyBag service
- comphelper/source/property/makefile.mk:
+ add opropertybag.cxx
Diffstat (limited to 'comphelper')
-rw-r--r-- | comphelper/source/property/opropertybag.cxx | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/comphelper/source/property/opropertybag.cxx b/comphelper/source/property/opropertybag.cxx new file mode 100644 index 000000000000..f18d36ad3d6d --- /dev/null +++ b/comphelper/source/property/opropertybag.cxx @@ -0,0 +1,528 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: opropertybag.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: obo $ $Date: 2008-02-26 15:15:27 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_comphelper.hxx" + +#include "opropertybag.hxx" + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/NamedValue.hpp> + +#include <comphelper/namedvaluecollection.hxx> + +#include <cppuhelper/exc_hlp.hxx> +#include <osl/thread.h> + +#include <algorithm> +#include <functional> + + +//-------------------------------------------------------------------------- +#if 0 +extern "C" void SAL_CALL createRegistryInfo_OPropertyBag() +{ + static ::comphelper::OAutoRegistration< ::comphelper::OPropertyBag > aAutoRegistration; +} +#endif + +using namespace ::com::sun::star; + +uno::Sequence< ::rtl::OUString > SAL_CALL PropertyBag_getSupportedServiceNames() throw() +{ + return ::comphelper::OPropertyBag::getSupportedServiceNames_static(); +} + +::rtl::OUString SAL_CALL PropertyBag_getImplementationName() throw() +{ + return ::comphelper::OPropertyBag::getImplementationName_static(); +} + +uno::Reference< uno::XInterface > SAL_CALL PropertyBag_createInstance(const uno::Reference< uno::XComponentContext >& rxContext) throw( uno::Exception ) +{ + return ::comphelper::OPropertyBag::Create( rxContext ); +} + +//........................................................................ +namespace comphelper +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::util; + + //==================================================================== + //= OPropertyBag + //==================================================================== + //-------------------------------------------------------------------- + OPropertyBag::OPropertyBag( const Reference< XComponentContext >& _rxContext ) + :OPropertyBag_PBase( GetBroadcastHelper(), this ) + ,::cppu::IEventNotificationHook() + ,m_aContext( _rxContext ) + ,m_bAutoAddProperties( false ) + ,m_NotifyListeners(m_aMutex) + ,m_isModified(false) + + { + } + + //-------------------------------------------------------------------- + OPropertyBag::~OPropertyBag() + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OPropertyBag, OPropertyBag_Base, OPropertyBag_PBase ) + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OPropertyBag, OPropertyBag_Base, OPropertyBag_PBase ) + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > OPropertyBag::getSupportedServiceNames_static() throw( RuntimeException ) + { + Sequence< ::rtl::OUString > aServices(1); + aServices[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.PropertyBag" ) ); + return aServices; + } + + //-------------------------------------------------------------------- + void SAL_CALL OPropertyBag::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException) + { + ::comphelper::NamedValueCollection aArguments( _rArguments ); + + Sequence< Type > aTypes; + if ( aArguments.get_ensureType( "AllowedTypes", aTypes ) ) + ::std::copy( + aTypes.getConstArray(), + aTypes.getConstArray() + aTypes.getLength(), + ::std::insert_iterator< TypeBag >( m_aAllowedTypes, m_aAllowedTypes.begin() ) + ); + + aArguments.get_ensureType( "AutomaticAddition", m_bAutoAddProperties ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString OPropertyBag::getImplementationName_static() throw( RuntimeException ) + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.comphelper.OPropertyBag" ) ); + } + + //-------------------------------------------------------------------- + Reference< XInterface > SAL_CALL OPropertyBag::Create( const Reference< XComponentContext >& _rxContext ) + { + return *new OPropertyBag( _rxContext ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OPropertyBag::getImplementationName() throw (RuntimeException) + { + return getImplementationName_static(); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL OPropertyBag::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aServices( getSupportedServiceNames_static() ); + const ::rtl::OUString* pStart = aServices.getConstArray(); + const ::rtl::OUString* pEnd = aServices.getConstArray() + aServices.getLength(); + return ::std::find( pStart, pEnd, rServiceName ) != pEnd; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OPropertyBag::getSupportedServiceNames( ) throw (RuntimeException) + { + return getSupportedServiceNames_static(); + } + + //-------------------------------------------------------------------- + void OPropertyBag::fireEvents( + sal_Int32 * /*pnHandles*/, + sal_Int32 nCount, + sal_Bool bVetoable, + bool bIgnoreRuntimeExceptionsWhileFiring) + { + if (nCount && !bVetoable) { + setModifiedImpl(sal_True, bIgnoreRuntimeExceptionsWhileFiring); + } + } + + void OPropertyBag::setModifiedImpl(::sal_Bool bModified, + bool bIgnoreRuntimeExceptionsWhileFiring) + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_isModified = bModified; + if (bModified) { + try { + Reference<XInterface> xThis(*this); + EventObject event(xThis); + m_NotifyListeners.notifyEach( + &XModifyListener::modified, event); + } catch (RuntimeException &) { + if (!bIgnoreRuntimeExceptionsWhileFiring) { + throw; + } + } catch (Exception &) { + // ignore + } + } + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL OPropertyBag::isModified() + throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return m_isModified; + } + + void SAL_CALL OPropertyBag::setModified( ::sal_Bool bModified ) + throw (PropertyVetoException, RuntimeException) + { + setModifiedImpl(bModified, false); + } + + void SAL_CALL OPropertyBag::addModifyListener( + const Reference< XModifyListener > & xListener) + throw (RuntimeException) + { + m_NotifyListeners.addInterface(xListener); + } + + void SAL_CALL OPropertyBag::removeModifyListener( + const Reference< XModifyListener > & xListener) + throw (RuntimeException) + { + m_NotifyListeners.removeInterface(xListener); + } + + //-------------------------------------------------------------------- + Reference< XPropertySetInfo > SAL_CALL OPropertyBag::getPropertySetInfo( ) throw(RuntimeException) + { + return createPropertySetInfo( getInfoHelper() ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OPropertyBag::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + m_aDynamicProperties.getFastPropertyValue( _nHandle, _rValue ); + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OPropertyBag::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw (IllegalArgumentException) + { + return m_aDynamicProperties.convertFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OPropertyBag::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) + { + m_aDynamicProperties.setFastPropertyValue( nHandle, rValue ); + } + + //-------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper& SAL_CALL OPropertyBag::getInfoHelper() + { + if ( !m_pArrayHelper.get() ) + { + Sequence< Property > aProperties; + m_aDynamicProperties.describeProperties( aProperties ); + m_pArrayHelper.reset( new ::cppu::OPropertyArrayHelper( aProperties ) ); + } + return *m_pArrayHelper; + + } + + //-------------------------------------------------------------------- + sal_Int32 OPropertyBag::findFreeHandle() const + { + const sal_Int32 nPrime = 1009; + const sal_Int32 nSeed = 11; + + sal_Int32 nCheck = nSeed; + while ( m_aDynamicProperties.hasPropertyByHandle( nCheck ) && ( nCheck != 1 ) ) + { + nCheck = ( nCheck * nSeed ) % nPrime; + } + + if ( nCheck == 1 ) + { // uh ... we already have 1008 handles used up + // -> simply count upwards + while ( m_aDynamicProperties.hasPropertyByHandle( nCheck ) ) + ++nCheck; + } + + return nCheck; + } + + //-------------------------------------------------------------------- + void SAL_CALL OPropertyBag::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // check whether the type is allowed, everything else will be checked + // by m_aDynamicProperties + Type aPropertyType = _rInitialValue.getValueType(); + if ( _rInitialValue.hasValue() + && !m_aAllowedTypes.empty() + && m_aAllowedTypes.find( aPropertyType ) == m_aAllowedTypes.end() + ) + throw IllegalTypeException( ::rtl::OUString(), *this ); + + m_aDynamicProperties.addProperty( _rName, findFreeHandle(), _nAttributes, _rInitialValue ); + + // our property info is dirty + m_pArrayHelper.reset(); + + setModified(sal_True); + } + + //-------------------------------------------------------------------- + void SAL_CALL OPropertyBag::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + m_aDynamicProperties.removeProperty( _rName ); + + // our property info is dirty + m_pArrayHelper.reset(); + + setModified(sal_True); + } + + //-------------------------------------------------------------------- + namespace + { + struct ComparePropertyValueByName : public ::std::binary_function< PropertyValue, PropertyValue, bool > + { + bool operator()( const PropertyValue& _rLHS, const PropertyValue& _rRHS ) + { + return _rLHS.Name < _rRHS.Name; + } + }; + + template< typename CLASS > + struct TransformPropertyToName : public ::std::unary_function< CLASS, ::rtl::OUString > + { + const ::rtl::OUString& operator()( const CLASS& _rProp ) + { + return _rProp.Name; + } + }; + + struct ExtractPropertyValue : public ::std::unary_function< PropertyValue, Any > + { + const Any& operator()( const PropertyValue& _rProp ) + { + return _rProp.Value; + } + }; + } + + //-------------------------------------------------------------------- + Sequence< PropertyValue > SAL_CALL OPropertyBag::getPropertyValues( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + // all registered properties + Sequence< Property > aProperties; + m_aDynamicProperties.describeProperties( aProperties ); + + // their names + Sequence< ::rtl::OUString > aNames( aProperties.getLength() ); + ::std::transform( + aProperties.getConstArray(), + aProperties.getConstArray() + aProperties.getLength(), + aNames.getArray(), + TransformPropertyToName< Property >() + ); + + // their values + Sequence< Any > aValues; + try + { + aValues = OPropertyBag_PBase::getPropertyValues( aNames ); + if ( aValues.getLength() != aNames.getLength() ) + throw RuntimeException(); + } + catch( const RuntimeException& ) + { + throw; + } + catch( const Exception& ) + { + // ignore + } + + // merge names and values, and retrieve the state/handle + ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper(); + + Sequence< PropertyValue > aPropertyValues( aNames.getLength() ); + const ::rtl::OUString* pName = aNames.getConstArray(); + const ::rtl::OUString* pNamesEnd = aNames.getConstArray() + aNames.getLength(); + const Any* pValue = aValues.getArray(); + PropertyValue* pPropertyValue = aPropertyValues.getArray(); + + for ( ; pName != pNamesEnd; ++pName, ++pValue, ++pPropertyValue ) + { + pPropertyValue->Name = *pName; + pPropertyValue->Handle = rPropInfo.getHandleByName( *pName ); + pPropertyValue->Value = *pValue; + pPropertyValue->State = getPropertyStateByHandle( pPropertyValue->Handle ); + } + + return aPropertyValues; + } + + //-------------------------------------------------------------------- + void OPropertyBag::impl_setPropertyValues_throw( const Sequence< PropertyValue >& _rProps ) + { + // sort (the XMultiPropertySet interface requires this) + Sequence< PropertyValue > aProperties( _rProps ); + ::std::sort( + aProperties.getArray(), + aProperties.getArray() + aProperties.getLength(), + ComparePropertyValueByName() + ); + + // a sequence of names + Sequence< ::rtl::OUString > aNames( aProperties.getLength() ); + ::std::transform( + aProperties.getConstArray(), + aProperties.getConstArray() + aProperties.getLength(), + aNames.getArray(), + TransformPropertyToName< PropertyValue >() + ); + + try + { + ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper(); + + // check for unknown properties + // we cannot simply rely on the XMultiPropertySet::setPropertyValues + // implementation of our base class, since it does not throw + // an UnknownPropertyException. More precise, XMultiPropertySet::setPropertyValues + // does not allow to throw this exception, while XPropertyAccess::setPropertyValues + // requires it + sal_Int32 nCount = aNames.getLength(); + + Sequence< sal_Int32 > aHandles( nCount ); + sal_Int32* pHandle = aHandles.getArray(); + const PropertyValue* pProperty = aProperties.getConstArray(); + for ( const ::rtl::OUString* pName = aNames.getConstArray(); + pName != aNames.getConstArray() + aNames.getLength(); + ++pName, ++pHandle, ++pProperty + ) + { + *pHandle = rPropInfo.getHandleByName( *pName ); + if ( *pHandle != -1 ) + continue; + + // there's a property requested which we do not know + if ( m_bAutoAddProperties ) + { + // add the property + sal_Int16 nAttributes = PropertyAttribute::BOUND | PropertyAttribute::REMOVEABLE | PropertyAttribute::MAYBEDEFAULT; + addProperty( *pName, nAttributes, pProperty->Value ); + // rPropInfo is invalid, refetch + rPropInfo = getInfoHelper(); + *pHandle = rPropInfo.getHandleByName( *pName ); + continue; + } + + // no way out + throw UnknownPropertyException( *pName, *this ); + } + + // a sequence of values + Sequence< Any > aValues( aProperties.getLength() ); + ::std::transform( + aProperties.getConstArray(), + aProperties.getConstArray() + aProperties.getLength(), + aValues.getArray(), + ExtractPropertyValue() + ); + + setFastPropertyValues( nCount, aHandles.getArray(), aValues.getConstArray(), nCount ); + } + catch( const PropertyVetoException& ) { throw; } + catch( const IllegalArgumentException& ) { throw; } + catch( const WrappedTargetException& ) { throw; } + catch( const RuntimeException& ) { throw; } + catch( const UnknownPropertyException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OPropertyBag::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_setPropertyValues_throw( _rProps ); + } + + //-------------------------------------------------------------------- + PropertyState OPropertyBag::getPropertyStateByHandle( sal_Int32 _nHandle ) + { + // for properties which do not support the MAYBEDEFAULT attribute, don't rely on the base class, but + // assume they're always in DIRECT state. + // (Note that this probably would belong into the base class. However, this would mean we would need + // to check all existent usages of the base class, where MAYBEDEFAULT is *not* set, but + // a default is nonetheless supplied/used. This is hard to accomplish reliably, in the + // current phase. + // #i78593# / 2007-07-07 / frank.schoenheit@sun.com + + ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper(); + sal_Int16 nAttributes(0); + OSL_VERIFY( rPropInfo.fillPropertyMembersByHandle( NULL, &nAttributes, _nHandle ) ); + if ( ( nAttributes & PropertyAttribute::MAYBEDEFAULT ) == 0 ) + return PropertyState_DIRECT_VALUE; + + return OPropertyBag_PBase::getPropertyStateByHandle( _nHandle ); + } + + //-------------------------------------------------------------------- + Any OPropertyBag::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const + { + Any aDefault; + m_aDynamicProperties.getPropertyDefaultByHandle( _nHandle, aDefault ); + return aDefault; + } + +//........................................................................ +} // namespace comphelper +//........................................................................ + |