summaryrefslogtreecommitdiff
path: root/comphelper/source/property
diff options
context:
space:
mode:
Diffstat (limited to 'comphelper/source/property')
-rw-r--r--comphelper/source/property/ChainablePropertySet.cxx321
-rw-r--r--comphelper/source/property/ChainablePropertySetInfo.cxx142
-rw-r--r--comphelper/source/property/MasterPropertySet.cxx505
-rw-r--r--comphelper/source/property/MasterPropertySetInfo.cxx170
-rw-r--r--comphelper/source/property/TypeGeneration.cxx237
-rw-r--r--comphelper/source/property/composedprops.cxx357
-rw-r--r--comphelper/source/property/genericpropertyset.cxx301
-rw-r--r--comphelper/source/property/makefile.mk65
-rw-r--r--comphelper/source/property/opropertybag.cxx585
-rw-r--r--comphelper/source/property/opropertybag.hxx242
-rw-r--r--comphelper/source/property/propagg.cxx1047
-rw-r--r--comphelper/source/property/property.cxx245
-rw-r--r--comphelper/source/property/propertybag.cxx221
-rw-r--r--comphelper/source/property/propertycontainer.cxx105
-rw-r--r--comphelper/source/property/propertycontainerhelper.cxx552
-rw-r--r--comphelper/source/property/propertysethelper.cxx328
-rw-r--r--comphelper/source/property/propertysetinfo.cxx214
-rw-r--r--comphelper/source/property/propertystatecontainer.cxx339
-rw-r--r--comphelper/source/property/propmultiplex.cxx182
-rw-r--r--comphelper/source/property/propstate.cxx261
20 files changed, 6419 insertions, 0 deletions
diff --git a/comphelper/source/property/ChainablePropertySet.cxx b/comphelper/source/property/ChainablePropertySet.cxx
new file mode 100644
index 000000000000..936510f21309
--- /dev/null
+++ b/comphelper/source/property/ChainablePropertySet.cxx
@@ -0,0 +1,321 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include <comphelper/ChainablePropertySet.hxx>
+#include <comphelper/ChainablePropertySetInfo.hxx>
+#include <vos/mutex.hxx>
+
+#include <memory> // STL auto_ptr
+
+
+using namespace ::rtl;
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using ::vos::IMutex;
+
+ChainablePropertySet::ChainablePropertySet( comphelper::ChainablePropertySetInfo* pInfo, vos::IMutex *pMutex )
+ throw()
+: mpInfo ( pInfo )
+, mpMutex ( pMutex )
+, mxInfo ( pInfo )
+{
+}
+
+ChainablePropertySet::~ChainablePropertySet()
+ throw()
+{
+}
+
+// XPropertySet
+Reference< XPropertySetInfo > SAL_CALL ChainablePropertySet::getPropertySetInfo( )
+ throw(RuntimeException)
+{
+ return mxInfo;
+}
+
+void ChainablePropertySet::lockMutex()
+{
+ if (mpMutex)
+ mpMutex->acquire();
+}
+
+void ChainablePropertySet::unlockMutex()
+{
+ if (mpMutex)
+ mpMutex->release();
+}
+
+void SAL_CALL ChainablePropertySet::setPropertyValue( const ::rtl::OUString& rPropertyName, const Any& rValue )
+ throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard;
+ if (mpMutex)
+ pMutexGuard.reset( new vos::OGuard(mpMutex) );
+
+ PropertyInfoHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
+
+ if( aIter == mpInfo->maMap.end())
+ throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
+
+ _preSetValues();
+ _setSingleValue( *((*aIter).second), rValue );
+ _postSetValues();
+}
+
+Any SAL_CALL ChainablePropertySet::getPropertyValue( const ::rtl::OUString& rPropertyName )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard;
+ if (mpMutex)
+ pMutexGuard.reset( new vos::OGuard(mpMutex) );
+
+ PropertyInfoHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
+
+ if( aIter == mpInfo->maMap.end())
+ throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
+
+ Any aAny;
+ _preGetValues ();
+ _getSingleValue( *((*aIter).second), aAny );
+ _postGetValues ();
+
+ return aAny;
+}
+
+void SAL_CALL ChainablePropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL ChainablePropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL ChainablePropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL ChainablePropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+// XMultiPropertySet
+void SAL_CALL ChainablePropertySet::setPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames, const Sequence< Any >& aValues )
+ throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard;
+ if (mpMutex)
+ pMutexGuard.reset( new vos::OGuard(mpMutex) );
+
+ const sal_Int32 nCount = aPropertyNames.getLength();
+
+ if( nCount != aValues.getLength() )
+ throw IllegalArgumentException();
+
+ if( nCount )
+ {
+ _preSetValues();
+
+ const Any * pAny = aValues.getConstArray();
+ const OUString * pString = aPropertyNames.getConstArray();
+ PropertyInfoHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
+
+ for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny )
+ {
+ aIter = mpInfo->maMap.find ( *pString );
+ if ( aIter == aEnd )
+ throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
+
+ _setSingleValue ( *((*aIter).second), *pAny );
+ }
+
+ _postSetValues();
+ }
+}
+
+Sequence< Any > SAL_CALL ChainablePropertySet::getPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames )
+ throw(RuntimeException)
+{
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard;
+ if (mpMutex)
+ pMutexGuard.reset( new vos::OGuard(mpMutex) );
+
+ const sal_Int32 nCount = aPropertyNames.getLength();
+
+ Sequence < Any > aValues ( nCount );
+
+ if( nCount )
+ {
+ _preGetValues();
+
+ Any * pAny = aValues.getArray();
+ const OUString * pString = aPropertyNames.getConstArray();
+ PropertyInfoHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
+
+ for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny )
+ {
+ aIter = mpInfo->maMap.find ( *pString );
+ if ( aIter == aEnd )
+ throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
+
+ _getSingleValue ( *((*aIter).second), *pAny );
+ }
+
+ _postGetValues();
+ }
+ return aValues;
+}
+
+void SAL_CALL ChainablePropertySet::addPropertiesChangeListener( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& )
+ throw(RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL ChainablePropertySet::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& )
+ throw(RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL ChainablePropertySet::firePropertiesChangeEvent( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& )
+ throw(RuntimeException)
+{
+ // todo
+}
+
+// XPropertyState
+PropertyState SAL_CALL ChainablePropertySet::getPropertyState( const ::rtl::OUString& PropertyName )
+ throw(UnknownPropertyException, RuntimeException)
+{
+ PropertyInfoHash::const_iterator aIter = mpInfo->maMap.find( PropertyName );
+ if( aIter == mpInfo->maMap.end())
+ throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) );
+
+ PropertyState aState;
+
+ _preGetPropertyState();
+ _getPropertyState( *((*aIter).second), aState );
+ _postGetPropertyState();
+
+ return aState;
+}
+
+Sequence< PropertyState > SAL_CALL ChainablePropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& rPropertyNames )
+ throw(UnknownPropertyException, RuntimeException)
+{
+ const sal_Int32 nCount = rPropertyNames.getLength();
+
+ Sequence< PropertyState > aStates( nCount );
+ if( nCount )
+ {
+ PropertyState * pState = aStates.getArray();
+ const OUString * pString = rPropertyNames.getConstArray();
+ PropertyInfoHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
+ _preGetPropertyState();
+
+ for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pState )
+ {
+ aIter = mpInfo->maMap.find ( *pString );
+ if ( aIter == aEnd )
+ throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
+
+ _getPropertyState ( *((*aIter).second), *pState );
+ }
+ _postGetPropertyState();
+ }
+ return aStates;
+}
+
+void SAL_CALL ChainablePropertySet::setPropertyToDefault( const ::rtl::OUString& rPropertyName )
+ throw(UnknownPropertyException, RuntimeException)
+{
+ PropertyInfoHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
+
+ if( aIter == mpInfo->maMap.end())
+ throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
+ _setPropertyToDefault( *((*aIter).second) );
+}
+
+Any SAL_CALL ChainablePropertySet::getPropertyDefault( const ::rtl::OUString& rPropertyName )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ PropertyInfoHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
+
+ if( aIter == mpInfo->maMap.end())
+ throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
+ return _getPropertyDefault( *((*aIter).second) );
+}
+
+void ChainablePropertySet::_preGetPropertyState ()
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+}
+
+void ChainablePropertySet::_getPropertyState( const comphelper::PropertyInfo&, PropertyState& )
+ throw(UnknownPropertyException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+}
+
+void ChainablePropertySet::_postGetPropertyState ()
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+}
+
+void ChainablePropertySet::_setPropertyToDefault( const comphelper::PropertyInfo& )
+ throw(UnknownPropertyException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+}
+
+Any ChainablePropertySet::_getPropertyDefault( const comphelper::PropertyInfo& )
+ throw(UnknownPropertyException, WrappedTargetException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+
+ Any aAny;
+ return aAny;
+}
diff --git a/comphelper/source/property/ChainablePropertySetInfo.cxx b/comphelper/source/property/ChainablePropertySetInfo.cxx
new file mode 100644
index 000000000000..6660517ef97e
--- /dev/null
+++ b/comphelper/source/property/ChainablePropertySetInfo.cxx
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include <comphelper/ChainablePropertySetInfo.hxx>
+#include <comphelper/TypeGeneration.hxx>
+
+using ::rtl::OUString;
+using ::comphelper::PropertyInfo;
+using ::comphelper::GenerateCppuType;
+using ::comphelper::ChainablePropertySetInfo;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Type;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::XInterface;
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::beans::XPropertySetInfo;
+using ::com::sun::star::beans::UnknownPropertyException;
+
+ChainablePropertySetInfo::ChainablePropertySetInfo()
+ throw()
+{
+}
+
+ChainablePropertySetInfo::ChainablePropertySetInfo( PropertyInfo* pMap )
+ throw()
+{
+ add ( pMap );
+}
+
+ChainablePropertySetInfo::~ChainablePropertySetInfo()
+ throw()
+{
+}
+
+void ChainablePropertySetInfo::add( PropertyInfo* pMap, sal_Int32 nCount )
+ throw()
+{
+ // nCount < 0 => add all
+ // nCount == 0 => add nothing
+ // nCount > 0 => add at most nCount entries
+ if( maProperties.getLength() )
+ maProperties.realloc( 0 );
+
+ while( pMap->mpName && ( ( nCount < 0) || ( nCount-- > 0 ) ) )
+ {
+ OUString aName( pMap->mpName, pMap->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+
+#ifdef DBG_UTIL
+ PropertyInfoHash::iterator aIter = maMap.find( aName );
+ if( aIter != maMap.end() )
+ OSL_ENSURE( sal_False, "Warning: PropertyInfo added twice, possible error!");
+#endif
+ maMap[aName] = pMap++;
+ }
+}
+
+void ChainablePropertySetInfo::remove( const rtl::OUString& aName )
+ throw()
+{
+ maMap.erase ( aName );
+ if ( maProperties.getLength() )
+ maProperties.realloc( 0 );
+}
+
+Sequence< ::Property > SAL_CALL ChainablePropertySetInfo::getProperties()
+ throw(::com::sun::star::uno::RuntimeException)
+{
+ sal_Int32 nSize = maMap.size();
+ if( maProperties.getLength() != nSize )
+ {
+ maProperties.realloc ( nSize );
+ Property* pProperties = maProperties.getArray();
+
+ PropertyInfoHash::iterator aIter = maMap.begin();
+ const PropertyInfoHash::iterator aEnd = maMap.end();
+ for ( ; aIter != aEnd; ++aIter, ++pProperties)
+ {
+ PropertyInfo* pInfo = (*aIter).second;
+
+ pProperties->Name = OUString( pInfo->mpName, pInfo->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+ pProperties->Handle = pInfo->mnHandle;
+ const Type* pType;
+ GenerateCppuType ( pInfo->meCppuType, pType);
+ pProperties->Type = *pType;
+ pProperties->Attributes = pInfo->mnAttributes;
+ }
+ }
+ return maProperties;
+}
+
+Property SAL_CALL ChainablePropertySetInfo::getPropertyByName( const ::rtl::OUString& rName )
+ throw(::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
+{
+ PropertyInfoHash::iterator aIter = maMap.find( rName );
+
+ if ( maMap.end() == aIter )
+ throw UnknownPropertyException( rName, *this );
+
+ PropertyInfo *pInfo = (*aIter).second;
+ Property aProperty;
+ aProperty.Name = OUString( pInfo->mpName, pInfo->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+ aProperty.Handle = pInfo->mnHandle;
+ const Type* pType = &aProperty.Type;
+ GenerateCppuType ( pInfo->meCppuType, pType );
+ aProperty.Type = *pType;
+ aProperty.Attributes = pInfo->mnAttributes;
+ return aProperty;
+}
+
+sal_Bool SAL_CALL ChainablePropertySetInfo::hasPropertyByName( const ::rtl::OUString& rName )
+ throw(::com::sun::star::uno::RuntimeException)
+{
+ return static_cast < sal_Bool > ( maMap.find ( rName ) != maMap.end() );
+}
diff --git a/comphelper/source/property/MasterPropertySet.cxx b/comphelper/source/property/MasterPropertySet.cxx
new file mode 100644
index 000000000000..28078a8019fc
--- /dev/null
+++ b/comphelper/source/property/MasterPropertySet.cxx
@@ -0,0 +1,505 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+
+#ifndef _COMPHELPER_MASTERPROPERTYSET_HXX_
+#include <comphelper/MasterPropertySet.hxx>
+#endif
+#include <comphelper/MasterPropertySetInfo.hxx>
+#include <comphelper/ChainablePropertySet.hxx>
+#include <comphelper/ChainablePropertySetInfo.hxx>
+#include <vos/mutex.hxx>
+
+#include <memory> // STL auto_ptr
+
+//////////////////////////////////////////////////////////////////////
+
+class AutoOGuardArray
+{
+ sal_Int32 nSize;
+ std::auto_ptr< vos::OGuard > * pGuardArray;
+
+public:
+ AutoOGuardArray( sal_Int32 nNumElements );
+ ~AutoOGuardArray();
+
+ std::auto_ptr< vos::OGuard > & operator[] ( sal_Int32 i ) { return pGuardArray[i]; }
+};
+
+AutoOGuardArray::AutoOGuardArray( sal_Int32 nNumElements )
+{
+ nSize = nNumElements;
+ pGuardArray = new std::auto_ptr< vos::OGuard >[ nSize ];
+}
+
+AutoOGuardArray::~AutoOGuardArray()
+{
+ //!! release auto_ptr's and thus the mutexes locks
+ delete [] pGuardArray;
+
+}
+
+//////////////////////////////////////////////////////////////////////
+
+using namespace ::rtl;
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using vos::IMutex;
+
+SlaveData::SlaveData ( ChainablePropertySet *pSlave)
+: mpSlave ( pSlave )
+, mxSlave ( pSlave )
+, mbInit ( sal_False )
+{
+}
+
+MasterPropertySet::MasterPropertySet( comphelper::MasterPropertySetInfo* pInfo, IMutex *pMutex )
+ throw()
+: mpInfo ( pInfo )
+, mpMutex ( pMutex )
+, mnLastId ( 0 )
+, mxInfo ( pInfo )
+{
+}
+
+void MasterPropertySet::lockMutex()
+{
+ if (mpMutex)
+ mpMutex->acquire();
+}
+void MasterPropertySet::unlockMutex()
+{
+ if (mpMutex)
+ mpMutex->release();
+}
+
+MasterPropertySet::~MasterPropertySet()
+ throw()
+{
+ SlaveMap::iterator aEnd = maSlaveMap.end(), aIter = maSlaveMap.begin();
+ while (aIter != aEnd )
+ {
+ delete (*aIter).second;
+ aIter++;
+ }
+}
+
+// XPropertySet
+Reference< XPropertySetInfo > SAL_CALL MasterPropertySet::getPropertySetInfo( )
+ throw(RuntimeException)
+{
+ return mxInfo;
+}
+
+void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet )
+ throw()
+{
+ maSlaveMap [ ++mnLastId ] = new SlaveData ( pNewSet );
+ mpInfo->add ( pNewSet->mpInfo->maMap, mnLastId );
+}
+
+void SAL_CALL MasterPropertySet::setPropertyValue( const ::rtl::OUString& rPropertyName, const Any& rValue )
+ throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard;
+ if (mpMutex)
+ pMutexGuard.reset( new vos::OGuard(mpMutex) );
+
+ PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
+
+ if( aIter == mpInfo->maMap.end())
+ throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
+
+ if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
+ {
+ _preSetValues();
+ _setSingleValue( *((*aIter).second->mpInfo), rValue );
+ _postSetValues();
+ }
+ else
+ {
+ ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
+
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard2;
+ if (pSlave->mpMutex)
+ pMutexGuard2.reset( new vos::OGuard(pSlave->mpMutex) );
+
+ pSlave->_preSetValues();
+ pSlave->_setSingleValue( *((*aIter).second->mpInfo), rValue );
+ pSlave->_postSetValues();
+ }
+}
+
+Any SAL_CALL MasterPropertySet::getPropertyValue( const ::rtl::OUString& rPropertyName )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard;
+ if (mpMutex)
+ pMutexGuard.reset( new vos::OGuard(mpMutex) );
+
+ PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
+
+ if( aIter == mpInfo->maMap.end())
+ throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
+
+ Any aAny;
+ if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
+ {
+ _preGetValues();
+ _getSingleValue( *((*aIter).second->mpInfo), aAny );
+ _postGetValues();
+ }
+ else
+ {
+ ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
+
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard2;
+ if (pSlave->mpMutex)
+ pMutexGuard2.reset( new vos::OGuard(pSlave->mpMutex) );
+
+ pSlave->_preGetValues();
+ pSlave->_getSingleValue( *((*aIter).second->mpInfo), aAny );
+ pSlave->_postGetValues();
+ }
+ return aAny;
+}
+
+void SAL_CALL MasterPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL MasterPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL MasterPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL MasterPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+// XMultiPropertySet
+void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames, const Sequence< Any >& aValues )
+ throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard;
+ if (mpMutex)
+ pMutexGuard.reset( new vos::OGuard(mpMutex) );
+
+ const sal_Int32 nCount = aPropertyNames.getLength();
+
+ if( nCount != aValues.getLength() )
+ throw IllegalArgumentException();
+
+ if( nCount )
+ {
+ _preSetValues();
+
+ const Any * pAny = aValues.getConstArray();
+ const OUString * pString = aPropertyNames.getConstArray();
+ PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
+
+ //!! have an auto_ptr to an array of OGuards in order to have the
+ //!! allocated memory properly freed (exception safe!).
+ //!! Since the array itself has auto_ptrs as members we have to use a
+ //!! helper class 'AutoOGuardArray' in order to have
+ //!! the acquired locks properly released.
+ AutoOGuardArray aOGuardArray( nCount );
+
+ for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny )
+ {
+ aIter = mpInfo->maMap.find ( *pString );
+ if ( aIter == aEnd )
+ throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
+
+ if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
+ _setSingleValue( *((*aIter).second->mpInfo), *pAny );
+ else
+ {
+ SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
+ if (!pSlave->IsInit())
+ {
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ if (pSlave->mpSlave->mpMutex)
+ aOGuardArray[i].reset( new vos::OGuard(pSlave->mpSlave->mpMutex) );
+
+ pSlave->mpSlave->_preSetValues();
+ pSlave->SetInit ( sal_True );
+ }
+ pSlave->mpSlave->_setSingleValue( *((*aIter).second->mpInfo), *pAny );
+ }
+ }
+
+ _postSetValues();
+ SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
+ while (aSlaveIter != aSlaveEnd)
+ {
+ if ( (*aSlaveIter).second->IsInit())
+ {
+ (*aSlaveIter).second->mpSlave->_postSetValues();
+ (*aSlaveIter).second->SetInit ( sal_False );
+ }
+ ++aSlaveIter;
+ }
+ }
+}
+
+Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames )
+ throw(RuntimeException)
+{
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard;
+ if (mpMutex)
+ pMutexGuard.reset( new vos::OGuard(mpMutex) );
+
+ const sal_Int32 nCount = aPropertyNames.getLength();
+
+ Sequence < Any > aValues ( nCount );
+
+ if( nCount )
+ {
+ _preGetValues();
+
+ Any * pAny = aValues.getArray();
+ const OUString * pString = aPropertyNames.getConstArray();
+ PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
+
+ //!! have an auto_ptr to an array of OGuards in order to have the
+ //!! allocated memory properly freed (exception safe!).
+ //!! Since the array itself has auto_ptrs as members we have to use a
+ //!! helper class 'AutoOGuardArray' in order to have
+ //!! the acquired locks properly released.
+ AutoOGuardArray aOGuardArray( nCount );
+
+ for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny )
+ {
+ aIter = mpInfo->maMap.find ( *pString );
+ if ( aIter == aEnd )
+ throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
+
+ if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
+ _getSingleValue( *((*aIter).second->mpInfo), *pAny );
+ else
+ {
+ SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
+ if (!pSlave->IsInit())
+ {
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ if (pSlave->mpSlave->mpMutex)
+ aOGuardArray[i].reset( new vos::OGuard(pSlave->mpSlave->mpMutex) );
+
+ pSlave->mpSlave->_preGetValues();
+ pSlave->SetInit ( sal_True );
+ }
+ pSlave->mpSlave->_getSingleValue( *((*aIter).second->mpInfo), *pAny );
+ }
+ }
+
+ _postSetValues();
+ SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
+ while (aSlaveIter != aSlaveEnd)
+ {
+ if ( (*aSlaveIter).second->IsInit())
+ {
+ (*aSlaveIter).second->mpSlave->_postSetValues();
+ (*aSlaveIter).second->SetInit ( sal_False );
+ }
+ ++aSlaveIter;
+ }
+ }
+ return aValues;
+}
+
+void SAL_CALL MasterPropertySet::addPropertiesChangeListener( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& )
+ throw(RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL MasterPropertySet::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& )
+ throw(RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL MasterPropertySet::firePropertiesChangeEvent( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& )
+ throw(RuntimeException)
+{
+ // todo
+}
+
+// XPropertyState
+PropertyState SAL_CALL MasterPropertySet::getPropertyState( const ::rtl::OUString& PropertyName )
+ throw(UnknownPropertyException, RuntimeException)
+{
+ PropertyDataHash::const_iterator aIter = mpInfo->maMap.find( PropertyName );
+ if( aIter == mpInfo->maMap.end())
+ throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) );
+
+ PropertyState aState;
+
+ if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
+ {
+ _preGetPropertyState();
+ _getPropertyState( *((*aIter).second->mpInfo), aState );
+ _postGetPropertyState();
+ }
+ else
+ {
+ ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
+
+ // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
+ std::auto_ptr< vos::OGuard > pMutexGuard;
+ if (pSlave->mpMutex)
+ pMutexGuard.reset( new vos::OGuard(pSlave->mpMutex) );
+
+ pSlave->_preGetPropertyState();
+ pSlave->_getPropertyState( *((*aIter).second->mpInfo), aState );
+ pSlave->_postGetPropertyState();
+ }
+
+ return aState;
+}
+
+Sequence< PropertyState > SAL_CALL MasterPropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& rPropertyNames )
+ throw(UnknownPropertyException, RuntimeException)
+{
+ const sal_Int32 nCount = rPropertyNames.getLength();
+
+ Sequence< PropertyState > aStates( nCount );
+ if( nCount )
+ {
+ PropertyState * pState = aStates.getArray();
+ const OUString * pString = rPropertyNames.getConstArray();
+ PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
+ _preGetPropertyState();
+
+ for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pState )
+ {
+ aIter = mpInfo->maMap.find ( *pString );
+ if ( aIter == aEnd )
+ throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
+
+ if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
+ _getPropertyState( *((*aIter).second->mpInfo), *pState );
+ else
+ {
+ SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
+ if (!pSlave->IsInit())
+ {
+ pSlave->mpSlave->_preGetPropertyState();
+ pSlave->SetInit ( sal_True );
+ }
+ pSlave->mpSlave->_getPropertyState( *((*aIter).second->mpInfo), *pState );
+ }
+ }
+ _postGetPropertyState();
+ SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
+ while (aSlaveIter != aSlaveEnd)
+ {
+ if ( (*aSlaveIter).second->IsInit())
+ {
+ (*aSlaveIter).second->mpSlave->_postGetPropertyState();
+ (*aSlaveIter).second->SetInit ( sal_False );
+ }
+ ++aSlaveIter;
+ }
+ }
+ return aStates;
+}
+
+void SAL_CALL MasterPropertySet::setPropertyToDefault( const ::rtl::OUString& rPropertyName )
+ throw(UnknownPropertyException, RuntimeException)
+{
+ PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
+
+ if( aIter == mpInfo->maMap.end())
+ throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
+ _setPropertyToDefault( *((*aIter).second->mpInfo) );
+}
+
+Any SAL_CALL MasterPropertySet::getPropertyDefault( const ::rtl::OUString& rPropertyName )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
+
+ if( aIter == mpInfo->maMap.end())
+ throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
+ return _getPropertyDefault( *((*aIter).second->mpInfo) );
+}
+
+void MasterPropertySet::_preGetPropertyState ()
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+}
+
+void MasterPropertySet::_getPropertyState( const comphelper::PropertyInfo&, PropertyState& )
+ throw(UnknownPropertyException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+}
+
+void MasterPropertySet::_postGetPropertyState ()
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+}
+
+void MasterPropertySet::_setPropertyToDefault( const comphelper::PropertyInfo& )
+ throw(UnknownPropertyException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+}
+
+Any MasterPropertySet::_getPropertyDefault( const comphelper::PropertyInfo& )
+ throw(UnknownPropertyException, WrappedTargetException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+ Any aAny;
+ return aAny;
+}
diff --git a/comphelper/source/property/MasterPropertySetInfo.cxx b/comphelper/source/property/MasterPropertySetInfo.cxx
new file mode 100644
index 000000000000..57cf22b77508
--- /dev/null
+++ b/comphelper/source/property/MasterPropertySetInfo.cxx
@@ -0,0 +1,170 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#ifndef _COMPHELPER_CHAINABLEPROPERTYSETINFO_HXX_
+#include <comphelper/MasterPropertySetInfo.hxx>
+#endif
+#include <comphelper/TypeGeneration.hxx>
+
+using ::rtl::OUString;
+using ::comphelper::PropertyInfo;
+using ::comphelper::GenerateCppuType;
+using ::comphelper::MasterPropertySetInfo;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Type;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::XInterface;
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::beans::XPropertySetInfo;
+using ::com::sun::star::beans::UnknownPropertyException;
+
+MasterPropertySetInfo::MasterPropertySetInfo()
+ throw()
+{
+}
+
+MasterPropertySetInfo::MasterPropertySetInfo( PropertyInfo* pMap )
+ throw()
+{
+ add ( pMap );
+}
+
+MasterPropertySetInfo::~MasterPropertySetInfo()
+ throw()
+{
+ PropertyDataHash::iterator aEnd = maMap.end(), aIter = maMap.begin();
+ while (aIter != aEnd )
+ {
+ delete (*aIter).second;
+ aIter++;
+ }
+}
+
+void MasterPropertySetInfo::add( PropertyInfo* pMap, sal_Int32 nCount, sal_uInt8 nMapId )
+ throw()
+{
+ // nCount < 0 => add all
+ // nCount == 0 => add nothing
+ // nCount > 0 => add at most nCount entries
+ if( maProperties.getLength() )
+ maProperties.realloc( 0 );
+
+ for ( ; pMap->mpName && ( ( nCount < 0 ) || ( nCount > 0 ) ); --nCount, ++pMap )
+ {
+ OUString aName( pMap->mpName, pMap->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+
+#ifdef DBG_UTIL
+ PropertyDataHash::iterator aIter = maMap.find( aName );
+ if( aIter != maMap.end() )
+ OSL_ENSURE( sal_False, "Warning: PropertyInfo added twice, possible error!");
+#endif
+ maMap[aName] = new PropertyData ( nMapId, pMap );
+ }
+}
+
+void MasterPropertySetInfo::add( PropertyInfoHash &rHash, sal_uInt8 nMapId )
+ throw()
+{
+ if( maProperties.getLength() )
+ maProperties.realloc( 0 );
+ PropertyInfoHash::iterator aIter = rHash.begin(), aEnd = rHash.end();
+
+ while ( aIter != aEnd )
+ {
+#ifdef DBG_UTIL
+ PropertyDataHash::iterator aDebugIter = maMap.find( (*aIter).first );
+ if( aDebugIter != maMap.end() )
+ OSL_ENSURE( sal_False, "Warning: PropertyInfo added twice, possible error!");
+#endif
+ maMap[(*aIter).first] = new PropertyData ( nMapId, (*aIter).second );
+ aIter++;
+ }
+}
+
+void MasterPropertySetInfo::remove( const rtl::OUString& aName )
+ throw()
+{
+ maMap.erase ( aName );
+ if ( maProperties.getLength() )
+ maProperties.realloc( 0 );
+}
+
+Sequence< ::Property > SAL_CALL MasterPropertySetInfo::getProperties()
+ throw(::com::sun::star::uno::RuntimeException)
+{
+ sal_Int32 nSize = maMap.size();
+ if( maProperties.getLength() != nSize )
+ {
+ maProperties.realloc ( nSize );
+ Property* pProperties = maProperties.getArray();
+
+ PropertyDataHash::iterator aIter = maMap.begin();
+ const PropertyDataHash::iterator aEnd = maMap.end();
+ for ( ; aIter != aEnd; ++aIter, ++pProperties)
+ {
+ PropertyInfo* pInfo = (*aIter).second->mpInfo;
+
+ pProperties->Name = OUString( pInfo->mpName, pInfo->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+ pProperties->Handle = pInfo->mnHandle;
+ const Type* pType;
+ GenerateCppuType ( pInfo->meCppuType, pType);
+ pProperties->Type = *pType;
+ pProperties->Attributes = pInfo->mnAttributes;
+ }
+ }
+ return maProperties;
+}
+
+Property SAL_CALL MasterPropertySetInfo::getPropertyByName( const ::rtl::OUString& rName )
+ throw(::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
+{
+ PropertyDataHash::iterator aIter = maMap.find( rName );
+
+ if ( maMap.end() == aIter )
+ throw UnknownPropertyException( rName, *this );
+
+ PropertyInfo *pInfo = (*aIter).second->mpInfo;
+ Property aProperty;
+ aProperty.Name = OUString( pInfo->mpName, pInfo->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+ aProperty.Handle = pInfo->mnHandle;
+ const Type* pType;
+ GenerateCppuType ( pInfo->meCppuType, pType );
+ aProperty.Type = *pType;
+
+ aProperty.Attributes = pInfo->mnAttributes;
+ return aProperty;
+}
+
+sal_Bool SAL_CALL MasterPropertySetInfo::hasPropertyByName( const ::rtl::OUString& rName )
+ throw(::com::sun::star::uno::RuntimeException)
+{
+ return static_cast < sal_Bool > ( maMap.find ( rName ) != maMap.end() );
+}
diff --git a/comphelper/source/property/TypeGeneration.cxx b/comphelper/source/property/TypeGeneration.cxx
new file mode 100644
index 000000000000..bf880330ce75
--- /dev/null
+++ b/comphelper/source/property/TypeGeneration.cxx
@@ -0,0 +1,237 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#ifndef _COMPHELPER_TYPEGENERATION_HXX
+#include <comphelper/TypeGeneration.hxx>
+#endif
+#include <com/sun/star/script/XLibraryContainer.hpp>
+#include <com/sun/star/style/LineSpacingMode.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/style/DropCapFormat.hpp>
+#include <com/sun/star/style/LineSpacing.hpp>
+#include <com/sun/star/style/TabStop.hpp>
+#include <com/sun/star/style/TabAlign.hpp>
+#include <com/sun/star/style/PageStyleLayout.hpp>
+#include <com/sun/star/style/BreakType.hpp>
+#include <com/sun/star/text/XModule.hpp>
+#include <com/sun/star/text/XTextRangeMover.hpp>
+#include <com/sun/star/text/XFootnotesSettingsSupplier.hpp>
+#include <com/sun/star/text/XFootnote.hpp>
+#include <com/sun/star/text/XFootnotesSupplier.hpp>
+#include <com/sun/star/text/XEndnotesSupplier.hpp>
+#include <com/sun/star/text/XEndnotesSettingsSupplier.hpp>
+#include <com/sun/star/text/FootnoteNumbering.hpp>
+#include <com/sun/star/text/XTextSectionsSupplier.hpp>
+#include <com/sun/star/text/XTextSection.hpp>
+#include <com/sun/star/text/SectionFileLink.hpp>
+#include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/HorizontalAdjust.hpp>
+#include <com/sun/star/text/DocumentStatistic.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/HoriOrientationFormat.hpp>
+#include <com/sun/star/text/NotePrintMode.hpp>
+#include <com/sun/star/text/SizeType.hpp>
+#include <com/sun/star/text/VertOrientationFormat.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+//undef to prevent error (from sfx2/docfile.cxx)
+#undef SEQUENCE
+#include <com/sun/star/text/SetVariableType.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
+#include <com/sun/star/text/UserDataPart.hpp>
+#include <com/sun/star/text/ChapterFormat.hpp>
+#include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/text/PlaceholderType.hpp>
+#include <com/sun/star/text/TemplateDisplayFormat.hpp>
+#include <com/sun/star/text/UserFieldFormat.hpp>
+#include <com/sun/star/text/PageNumberType.hpp>
+#include <com/sun/star/text/ReferenceFieldPart.hpp>
+#include <com/sun/star/text/FilenameDisplayFormat.hpp>
+#include <com/sun/star/text/XDependentTextField.hpp>
+#include <com/sun/star/text/GraphicCrop.hpp>
+#include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
+#include <com/sun/star/text/XTextTableCursor.hpp>
+#include <com/sun/star/text/XTextTablesSupplier.hpp>
+#include <com/sun/star/text/TableColumnSeparator.hpp>
+#include <com/sun/star/text/XTextTable.hpp>
+#include <com/sun/star/text/XDocumentIndexMark.hpp>
+#include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
+#include <com/sun/star/text/XDocumentIndex.hpp>
+#include <com/sun/star/text/XTextColumns.hpp>
+#include <com/sun/star/text/TextColumnSequence.hpp>
+#include <com/sun/star/text/XTextFramesSupplier.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
+#include <com/sun/star/beans/PropertyValues.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/beans/XVetoableChangeListener.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XPropertyStateChangeListener.hpp>
+#ifndef _COM_SUN_STAR_BEANS_PropertyAttribute_HPP_
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#endif
+#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/beans/XPropertyContainer.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyStateChangeEvent.hpp>
+#include <com/sun/star/beans/PropertyChangeEvent.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/style/GraphicLocation.hpp>
+#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/table/ShadowFormat.hpp>
+#include <com/sun/star/table/BorderLine.hpp>
+#include <com/sun/star/table/TableBorder.hpp>
+#include <com/sun/star/table/TableBorderDistances.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/i18n/XForbiddenCharacters.hpp>
+#include <com/sun/star/drawing/ColorMode.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+// --> OD 2004-08-09 #i28749#
+#include <com/sun/star/drawing/HomogenMatrix3.hpp>
+// <--
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::i18n;
+using namespace ::comphelper;
+
+namespace comphelper
+{
+ void GenerateCppuType (
+ CppuTypes eType, const com::sun::star::uno::Type*& pType )
+ {
+ switch( eType )
+ {
+ case CPPUTYPE_BOOLEAN: pType = &::getBooleanCppuType(); break;
+ case CPPUTYPE_INT8: pType = &::getCppuType( (sal_Int8*)0 ); break;
+ case CPPUTYPE_INT16: pType = &::getCppuType( (sal_Int16*)0 ); break;
+ case CPPUTYPE_INT32: pType = &::getCppuType( (sal_Int32*)0 ); break;
+
+ case CPPUTYPE_DOUBLE: pType = &::getCppuType( (double*)0 ); break;
+ case CPPUTYPE_FLOAT: pType = &::getCppuType( (float*)0 ); break;
+ case CPPUTYPE_OUSTRING: pType = &::getCppuType( (OUString*)0 ); break;
+ case CPPUTYPE_FONTSLANT: pType = &::getCppuType( (FontSlant*)0 ); break;
+ case CPPUTYPE_LOCALE: pType = &::getCppuType( (Locale*)0 ); break;
+ case CPPUTYPE_PROPERTYVALUE:pType = &::getCppuType( (Sequence<PropertyValue>*)0 ); break;
+ case CPPUTYPE_PROPERTYVALUES: pType = &::getCppuType( (Sequence<PropertyValues>*)0 ); break;
+ case CPPUTYPE_BORDERLINE: pType = &::getCppuType( (table::BorderLine*)0 ); break;
+ case CPPUTYPE_BREAK: pType = &::getCppuType( (style::BreakType*)0 ); break;
+ case CPPUTYPE_GRAPHICLOC: pType = &::getCppuType( (style::GraphicLocation*)0 ); break;
+ case CPPUTYPE_DROPCAPFMT: pType = &::getCppuType( (style::DropCapFormat*)0 ); break;
+ case CPPUTYPE_LINESPACE: pType = &::getCppuType( (style::LineSpacing*)0 ); break;
+
+ case CPPUTYPE_AWTSIZE: pType = &::getCppuType( (awt::Size*)0 ); break;
+ case CPPUTYPE_SHADOWFMT: pType = &::getCppuType( (table::ShadowFormat*)0 ); break;
+ case CPPUTYPE_TBLCOLSEP: pType = &::getCppuType( (Sequence<text::TableColumnSeparator>*)0 ); break;
+ case CPPUTYPE_PNTSEQSEQ: pType = &::getCppuType( (PointSequenceSequence*)0 ); break;
+ case CPPUTYPE_DOCIDXMRK: pType = &::getCppuType( (Sequence< Reference< XDocumentIndexMark > >*)0 ); break;
+ case CPPUTYPE_SEQINT8: pType = &::getCppuType( (Sequence<sal_Int8>*)0 ); break;
+ case CPPUTYPE_SEQTABSTOP: pType = &::getCppuType( (Sequence<style::TabStop>*)0 ); break;
+ case CPPUTYPE_SEQANCHORTYPE:pType = &::getCppuType( (Sequence<text::TextContentAnchorType>*)0 ); break;
+ case CPPUTYPE_SEQDEPTXTFLD: pType = &::getCppuType( (Sequence<Reference<XDependentTextField> >*)0); break;
+ case CPPUTYPE_TXTCNTANCHOR: pType = &::getCppuType( (text::TextContentAnchorType*)0 ); break;
+ case CPPUTYPE_WRAPTXTMODE: pType = &::getCppuType( (text::WrapTextMode*)0 ); break;
+
+ case CPPUTYPE_COLORMODE: pType = &::getCppuType( (drawing::ColorMode*)0 ); break;
+ case CPPUTYPE_PAGESTYLELAY: pType = &::getCppuType( (style::PageStyleLayout*)0 ); break;
+ case CPPUTYPE_VERTALIGN: pType = &::getCppuType( (style::VerticalAlignment*)0 ); break;
+ case CPPUTYPE_TABLEBORDER: pType = &::getCppuType( (table::TableBorder*)0 ); break;
+ case CPPUTYPE_GRFCROP: pType = &::getCppuType( (text::GraphicCrop*)0 ); break;
+ case CPPUTYPE_SECTFILELNK: pType = &::getCppuType( (text::SectionFileLink*)0 ); break;
+ case CPPUTYPE_PAGENUMTYPE: pType = &::getCppuType( (text::PageNumberType*)0); break;
+ case CPPUTYPE_DATETIME: pType = &::getCppuType( (util::DateTime*)0 ); break;
+ case CPPUTYPE_DATE: pType = &::getCppuType( (util::Date*)0 ); break;
+
+ case CPPUTYPE_REFINTERFACE: pType = &::getCppuType( (Reference<XInterface>*)0 ); break;
+ case CPPUTYPE_REFIDXREPL: pType = &::getCppuType( (Reference<container::XIndexReplace>*)0 ); break;
+ case CPPUTYPE_REFNAMECNT: pType = &::getCppuType( (Reference<container::XNameContainer>*)0 ); break;
+ case CPPUTYPE_REFTEXTFRAME: pType = &::getCppuType( (Reference<text::XTextFrame>*)0 ); break;
+ case CPPUTYPE_REFTEXTSECTION: pType = &::getCppuType( (Reference<text::XTextSection>*)0 ); break;
+ case CPPUTYPE_REFFOOTNOTE: pType = &::getCppuType( (Reference<text::XFootnote>*)0 ); break;
+ case CPPUTYPE_REFTEXT: pType = &::getCppuType( (Reference<text::XText>*)0 ); break;
+ case CPPUTYPE_REFTEXTCOL: pType = &::getCppuType( (Reference<text::XTextColumns>*)0 ); break;
+ case CPPUTYPE_REFFORBCHARS: pType = &::getCppuType( (Reference<XForbiddenCharacters>*)0 ); break;
+ case CPPUTYPE_REFIDXCNTNR: pType = &::getCppuType( (Reference<XIndexContainer>*)0 ); break;
+ case CPPUTYPE_REFTEXTCNTNT: pType = &::getCppuType( (Reference<XTextContent>*)0 ); break;
+ case CPPUTYPE_REFBITMAP: pType = &::getCppuType( (Reference<awt::XBitmap>*)0 ); break;
+ case CPPUTYPE_REFNMREPLACE: pType = &::getCppuType( (Reference<container::XNameReplace>*)0 ); break;
+ case CPPUTYPE_REFCELL: pType = &::getCppuType( (Reference<table::XCell>*)0 ); break;
+ case CPPUTYPE_REFDOCINDEX: pType = &::getCppuType( (Reference<text::XDocumentIndex>*)0 ); break;
+ case CPPUTYPE_REFDOCIDXMRK: pType = &::getCppuType( (Reference<text::XDocumentIndexMark>*)0 ); break;
+ case CPPUTYPE_REFTXTFIELD: pType = &::getCppuType( (Reference<text::XTextField>*)0 ); break;
+ case CPPUTYPE_REFTXTRANGE: pType = &::getCppuType( (Reference<text::XTextRange>*)0 ); break;
+ case CPPUTYPE_REFTXTTABLE: pType = &::getCppuType( (Reference<text::XTextTable>*)0 ); break;
+ case CPPUTYPE_AWTPOINT: pType = &::getCppuType( (awt::Point*)0 ); break;
+ case CPPUTYPE_REFLIBCONTAINER: pType = &::getCppuType( (Reference< script::XLibraryContainer >*)0); break;
+ case CPPUTYPE_OUSTRINGS: pType = &::getCppuType( (Sequence< ::rtl::OUString >*)0); break;
+ case CPPUTYPE_SEQANY: pType = &::getCppuType( (Sequence< uno::Any >*)0); break;
+ case CPPUTYPE_REFRESULTSET: pType = &::getCppuType( (Reference< sdbc::XResultSet >*)0); break;
+ case CPPUTYPE_REFCONNECTION: pType = &::getCppuType( (Reference< sdbc::XConnection >*)0); break;
+ case CPPUTYPE_REFMODEL: pType = &::getCppuType( (Reference< frame::XModel >*)0); break;
+ case CPPUTYPE_REFCOMPONENT: pType = &::getCppuType( (Reference< lang::XComponent >*)0 ); break;
+ // --> OD 2004-08-09 #i28749#
+ case CPPUTYPE_TRANSFORMATIONINHORIL2R:
+ {
+ pType = &::getCppuType( (drawing::HomogenMatrix3*)0 );
+ }
+ break;
+ // <--
+ case CPPUTYPE_SEQNAMEDVALUE: pType = &::getCppuType( (Sequence<beans::NamedValue>*)0 ); break;
+ case CPPUTYPE_REFXGRAPHIC: pType = &::getCppuType( (Reference< graphic::XGraphic >*)0); break;
+ case CPPUTYPE_TABLEBORDERDISTANCES: pType = &::getCppuType( (table::TableBorderDistances*)0 ); break;
+ default:
+ OSL_ASSERT( "Unknown CPPU type" );
+ }
+ }
+}
diff --git a/comphelper/source/property/composedprops.cxx b/comphelper/source/property/composedprops.cxx
new file mode 100644
index 000000000000..4b44a8fb474e
--- /dev/null
+++ b/comphelper/source/property/composedprops.cxx
@@ -0,0 +1,357 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include <comphelper/composedprops.hxx>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+//.........................................................................
+namespace comphelper
+{
+//.........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+
+ //=====================================================================
+ //= OComposedPropertySetInfo
+ //=====================================================================
+ class OComposedPropertySetInfo : public ::cppu::WeakImplHelper1< XPropertySetInfo >
+ {
+ private:
+ Sequence< Property> m_aProperties;
+
+ public:
+ OComposedPropertySetInfo(const Sequence< Property>& _rProperties);
+
+ virtual Sequence< Property > SAL_CALL getProperties( ) throw(RuntimeException);
+ virtual Property SAL_CALL getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException);
+ virtual sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException);
+ };
+
+ //=====================================================================
+ //= OComposedPropertySet
+ //=====================================================================
+ //---------------------------------------------------------------------
+ OComposedPropertySet::OComposedPropertySet(
+ const Sequence< Reference< XPropertySet> > & _rElements,
+ const IPropertySetComposerCallback* _pPropertyMetaData)
+ :m_pInfo(NULL)
+ {
+ // copy the sequence
+ sal_Int32 nSingleSets = _rElements.getLength();
+ if (nSingleSets)
+ {
+ m_aSingleSets.resize(nSingleSets);
+ const Reference< XPropertySet >* pSingleSets = _rElements.getConstArray();
+ ::std::copy(pSingleSets, pSingleSets + nSingleSets, m_aSingleSets.begin());
+ }
+
+ // impl ctor
+ compose(_pPropertyMetaData);
+ }
+
+ //---------------------------------------------------------------------
+ OComposedPropertySet::~OComposedPropertySet()
+ {
+ if (m_pInfo)
+ m_pInfo->release();
+ }
+
+ //---------------------------------------------------------------------
+ void OComposedPropertySet::compose(const IPropertySetComposerCallback* _pMetaData)
+ {
+ sal_Int32 nSingleSets = m_aSingleSets.size();
+
+ if (nSingleSets>0)
+ {
+ // get the properties of the first set
+ Reference< XPropertySet > xMasterSet = m_aSingleSets[0];
+ Sequence< Property> aMasterProps;
+ if (xMasterSet.is())
+ aMasterProps = xMasterSet->getPropertySetInfo()->getProperties();
+ sal_Int32 nMasterPropsCount = aMasterProps.getLength();
+ const Property* pMasterProps = aMasterProps.getConstArray();
+
+ // check which of the master properties should be included
+ Sequence<sal_Bool> aInclusionFlags(nMasterPropsCount);
+ sal_Bool* pInclusionFlags = aInclusionFlags.getArray();
+
+ // the states of all these properties
+ Sequence< PropertyState > aPropertyStates(nMasterPropsCount);
+
+ for (sal_Int32 i=0; i<nMasterPropsCount; ++i)
+ pInclusionFlags[i] = sal_True;
+
+ Reference< XPropertySet > xSecondarySet;
+ sal_Int32 nSecondaryPropertyCount;
+ Sequence< Property > aSecondaryProperties;
+ const Property* pPrimaryProperty = aMasterProps.getConstArray();
+ for (sal_Int32 nPrimary=0; nPrimary<nMasterPropsCount; ++nPrimary, ++pPrimaryProperty)
+ {
+ if (_pMetaData && !_pMetaData->isComposeable(pPrimaryProperty->Name))
+ // do not include this property
+ pInclusionFlags[nPrimary] = sal_False;
+ else
+ {
+ // search the property in all secondary sets
+ for (sal_Int32 i=1; i<nSingleSets; ++i)
+ {
+ xSecondarySet = m_aSingleSets[i];
+ aSecondaryProperties = xSecondarySet->getPropertySetInfo()->getProperties();
+ nSecondaryPropertyCount = aSecondaryProperties.getLength();
+ const Property* pSecondaryProperties = aSecondaryProperties.getConstArray();
+
+ // search the current primary property in the secondary property sequence
+ sal_Int32 k=0;
+ while (k<nSecondaryPropertyCount && (pSecondaryProperties[k].Name != pPrimaryProperty->Name))
+ ++k;
+
+ if (k >= nSecondaryPropertyCount)
+ // not found -> do not include
+ pInclusionFlags[nPrimary] = sal_False;
+ }
+ }
+ }
+
+ // count what's left ....
+ sal_Int32 nOverallProperties = 0;
+ for (sal_Int32 nCounter=0; nCounter<nMasterPropsCount; ++nCounter)
+ {
+ if (pInclusionFlags[nCounter])
+ ++nOverallProperties;
+ }
+
+ // and finally construct our sequence
+ m_aProperties = Sequence< Property >(nOverallProperties);
+ Property* pProperties = m_aProperties.getArray();
+ const Property* pMasterProperties = pMasterProps;
+ sal_Int32 nOwnProperties = 0;
+ for (sal_Int32 nCopy = 0; nCopy < nMasterPropsCount; ++nCopy, ++pMasterProperties)
+ {
+ if (pInclusionFlags[nCopy])
+ pProperties[nOwnProperties++] = *pMasterProperties;
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ Reference< XPropertySetInfo > SAL_CALL OComposedPropertySet::getPropertySetInfo( ) throw(RuntimeException)
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if (!m_pInfo)
+ {
+ m_pInfo = new OComposedPropertySetInfo(m_aProperties);
+ m_pInfo->acquire();
+ }
+ return m_pInfo;
+ }
+
+ //------------------------------------------------------------------------------
+ PropertyState SAL_CALL OComposedPropertySet::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
+ {
+ // assume DIRECT for the moment
+ PropertyState eState = PropertyState_DIRECT_VALUE;
+
+ sal_Int32 nSingleSets = m_aSingleSets.size();
+ if (nSingleSets>0)
+ {
+ // check the master state
+ Reference< XPropertySet > xMasterSet(m_aSingleSets[0]);
+ Any aPrimaryValue;
+ if (xMasterSet.is())
+ {
+ Reference< XPropertyState > xMasterState(xMasterSet,UNO_QUERY);
+ aPrimaryValue = xMasterSet->getPropertyValue(_rPropertyName);
+
+ if (xMasterState.is())
+ eState = xMasterState->getPropertyState(_rPropertyName);
+ }
+
+ // loop through the secondary sets
+ PropertyState eSecondaryState;
+ for (sal_Int32 i=1; i<nSingleSets; ++i)
+ {
+ Reference< XPropertySet > xSecondary(m_aSingleSets[i]);
+ Reference< XPropertyState > xSecondaryState(xSecondary, UNO_QUERY);
+
+ // the secondary state
+ eSecondaryState = PropertyState_DIRECT_VALUE;
+ if(xSecondaryState.is())
+ eSecondaryState = xSecondaryState->getPropertyState(_rPropertyName);
+
+ // the secondary value
+ Any aSecondaryValue(xSecondary->getPropertyValue(_rPropertyName));
+
+ if ( (PropertyState_AMBIGUOUS_VALUE == eSecondaryState) // secondary is ambiguous
+ || !::comphelper::compare(aPrimaryValue, aSecondaryValue) // unequal values
+ )
+ {
+ eState = PropertyState_AMBIGUOUS_VALUE;
+ break;
+ }
+ }
+ }
+ else
+ {
+ throw UnknownPropertyException( _rPropertyName, *this );
+ }
+
+ return eState;
+ }
+
+ //---------------------------------------------------------------------
+ Sequence< PropertyState > SAL_CALL OComposedPropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
+ {
+ sal_Int32 nCount = _rPropertyName.getLength();
+ Sequence< PropertyState > aReturn(nCount);
+ const ::rtl::OUString* pNames = _rPropertyName.getConstArray();
+ PropertyState* pStates = aReturn.getArray();
+ for (sal_Int32 i=0; i<nCount; ++i, ++pNames, ++pStates)
+ *pStates = getPropertyState(*pNames);
+ return aReturn;
+ }
+
+ //---------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::setPropertyToDefault( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, RuntimeException)
+ {
+ sal_Int32 nSingleSets = m_aSingleSets.size();
+ for (sal_Int32 i=0; i<nSingleSets; ++i)
+ {
+ Reference< XPropertyState > xState(m_aSingleSets[i], UNO_QUERY);
+ if(xState.is())
+ xState->setPropertyToDefault(_rPropertyName);
+ }
+ }
+
+ //---------------------------------------------------------------------
+ Any SAL_CALL OComposedPropertySet::getPropertyDefault( const ::rtl::OUString& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ return Any();
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+ {
+ sal_Int32 nSingleSets = m_aSingleSets.size();
+ for (sal_Int32 i=0; i<nSingleSets; ++i)
+ {
+ if (m_aSingleSets[i].is())
+ m_aSingleSets[i]->setPropertyValue(_rPropertyName, _rValue);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ Any SAL_CALL OComposedPropertySet::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ sal_Int32 nSingleSets = m_aSingleSets.size();
+
+ if ((nSingleSets>0) && (m_aSingleSets[0].is()))
+ return m_aSingleSets[0]->getPropertyValue(_rPropertyName);
+ return Any();
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ // TODO:
+ // hold the single property sets weak
+ // be a property change listener on all single property sets (for all composed properties)
+ // upon property change
+ // determine the new state/value of the composed property
+ // broadcast the new composed property value
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ // TODO
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ OSL_ENSURE(sal_False, "OComposedPropertySet::addVetoableChangeListener: no implemented (yet)!");
+ }
+
+ //------------------------------------------------------------------------------
+ void SAL_CALL OComposedPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ OSL_ENSURE(sal_False, "OComposedPropertySet::removeVetoableChangeListener: no implemented (yet)!");
+ }
+
+ //------------------------------------------------------------------------------
+ OComposedPropertySetInfo::OComposedPropertySetInfo(const Sequence< Property>& rSeq)
+ :m_aProperties(rSeq)
+ {
+ }
+
+ //------------------------------------------------------------------------------
+ Sequence< Property> SAL_CALL OComposedPropertySetInfo::getProperties() throw(RuntimeException)
+ {
+ return m_aProperties;
+ }
+
+ //------------------------------------------------------------------------------
+ Property SAL_CALL OComposedPropertySetInfo::getPropertyByName( const ::rtl::OUString& _rName ) throw(UnknownPropertyException, RuntimeException)
+ {
+ sal_Int32 nLength = m_aProperties.getLength();
+ const Property* pProps = m_aProperties.getConstArray();
+ // TODO TODO TODO: this O(n) search really sucks ...
+ for (sal_Int32 i=0; i<nLength; ++i, ++pProps)
+ {
+ if (pProps->Name == _rName)
+ return *pProps;
+ }
+
+ throw UnknownPropertyException( _rName, *this );
+ }
+
+ //------------------------------------------------------------------------------
+ sal_Bool SAL_CALL OComposedPropertySetInfo::hasPropertyByName( const ::rtl::OUString& _rName ) throw(RuntimeException)
+ {
+ sal_Int32 nLength = m_aProperties.getLength();
+ const Property* pProps = m_aProperties.getConstArray();
+ // TODO TODO TODO: this O(n) search really sucks ...
+ for( sal_Int32 i=0; i<nLength; ++i,++pProps )
+ {
+ if(pProps->Name == _rName)
+ return sal_True;
+ }
+
+ return sal_False;
+ }
+
+//.........................................................................
+} // namespace comphelper
+//.........................................................................
+
+
diff --git a/comphelper/source/property/genericpropertyset.cxx b/comphelper/source/property/genericpropertyset.cxx
new file mode 100644
index 000000000000..b7fb09912153
--- /dev/null
+++ b/comphelper/source/property/genericpropertyset.cxx
@@ -0,0 +1,301 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <cppuhelper/weakagg.hxx>
+#include <cppuhelper/interfacecontainer.hxx>
+#include <comphelper/propertysethelper.hxx>
+#include <osl/mutex.hxx>
+#include <comphelper/genericpropertyset.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/stl_types.hxx>
+#include <vos/mutex.hxx>
+#include <rtl/uuid.h>
+#include <boost/mem_fn.hpp>
+#include <boost/bind.hpp>
+#include <boost/utility.hpp>
+
+///////////////////////////////////////////////////////////////////////
+
+using namespace ::rtl;
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+
+DECLARE_STL_USTRINGACCESS_MAP( Any, GenericAnyMapImpl );
+
+namespace comphelper
+{
+ struct IMPL_GenericPropertySet_MutexContainer
+ {
+ Mutex maMutex ;
+ } ;
+
+ class GenericPropertySet : public OWeakAggObject,
+ public XServiceInfo,
+ public XTypeProvider,
+ public PropertySetHelper,
+ private IMPL_GenericPropertySet_MutexContainer
+ {
+ private:
+ GenericAnyMapImpl maAnyMap;
+ ::cppu::OMultiTypeInterfaceContainerHelperVar< ::rtl::OUString,UStringHash,UStringEqual> m_aListener;
+
+ protected:
+ virtual void _setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues ) throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException );
+ virtual void _getPropertyValues( const PropertyMapEntry** ppEntries, Any* pValue ) throw( UnknownPropertyException, WrappedTargetException );
+
+ public:
+ GenericPropertySet( PropertySetInfo* pInfo ) throw();
+ virtual ~GenericPropertySet() throw();
+
+ // XInterface
+ virtual Any SAL_CALL queryAggregation( const Type & rType ) throw( RuntimeException);
+ virtual Any SAL_CALL queryInterface( const Type & rType ) throw( RuntimeException);
+ virtual void SAL_CALL acquire() throw();
+ virtual void SAL_CALL release() throw();
+
+ // XTypeProvider
+ virtual Sequence< Type > SAL_CALL getTypes( ) throw( RuntimeException);
+ virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw( RuntimeException);
+
+ // XServiceInfo
+ virtual rtl::OUString SAL_CALL getImplementationName() throw( RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const rtl::OUString& ServiceName ) throw( RuntimeException );
+ virtual Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() throw( RuntimeException );
+
+ // XPropertySet
+ virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ };
+
+}
+
+///////////////////////////////////////////////////////////////////////
+
+GenericPropertySet::GenericPropertySet( PropertySetInfo* pInfo ) throw()
+: PropertySetHelper( pInfo )
+,m_aListener(maMutex)
+{
+}
+
+GenericPropertySet::~GenericPropertySet() throw()
+{
+}
+void SAL_CALL GenericPropertySet::addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ Reference < XPropertySetInfo > xInfo = getPropertySetInfo( );
+ if ( xInfo.is() )
+ {
+ if ( !aPropertyName.getLength() )
+ {
+ Sequence< Property> aSeq = xInfo->getProperties();
+ const Property* pIter = aSeq.getConstArray();
+ const Property* pEnd = pIter + aSeq.getLength();
+ for( ; pIter != pEnd ; ++pIter)
+ {
+ m_aListener.addInterface(pIter->Name,xListener);
+ }
+ }
+ else if ( xInfo->hasPropertyByName(aPropertyName) )
+ m_aListener.addInterface(aPropertyName,xListener);
+ else
+ throw UnknownPropertyException( aPropertyName, *this );
+ }
+}
+
+void SAL_CALL GenericPropertySet::removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ ResettableMutexGuard aGuard( maMutex );
+ Reference < XPropertySetInfo > xInfo = getPropertySetInfo( );
+ aGuard.clear();
+ if ( xInfo.is() )
+ {
+ if ( !aPropertyName.getLength() )
+ {
+ Sequence< Property> aSeq = xInfo->getProperties();
+ const Property* pIter = aSeq.getConstArray();
+ const Property* pEnd = pIter + aSeq.getLength();
+ for( ; pIter != pEnd ; ++pIter)
+ {
+ m_aListener.removeInterface(pIter->Name,xListener);
+ }
+ }
+ else if ( xInfo->hasPropertyByName(aPropertyName) )
+ m_aListener.removeInterface(aPropertyName,xListener);
+ else
+ throw UnknownPropertyException( aPropertyName, *this );
+ }
+}
+
+void GenericPropertySet::_setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues )
+ throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException )
+{
+ ResettableMutexGuard aGuard( maMutex );
+
+ while( *ppEntries )
+ {
+ const OUString aPropertyName( (*ppEntries)->mpName, (*ppEntries)->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+ OInterfaceContainerHelper * pHelper = m_aListener.getContainer(aPropertyName);
+
+ maAnyMap[ aPropertyName ] = *pValues;
+
+ if ( pHelper )
+ {
+ PropertyChangeEvent aEvt;
+ aEvt.PropertyName = aPropertyName;
+ aEvt.NewValue = *pValues;
+ aGuard.clear();
+ pHelper->notifyEach( &XPropertyChangeListener::propertyChange, aEvt );
+ aGuard.reset();
+ }
+
+ ppEntries++;
+ pValues++;
+ }
+}
+
+void GenericPropertySet::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, Any* pValue )
+ throw( UnknownPropertyException, WrappedTargetException )
+{
+ MutexGuard aGuard( maMutex );
+
+ while( *ppEntries )
+ {
+ const OUString aPropertyName( (*ppEntries)->mpName, (*ppEntries)->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+ *pValue = maAnyMap[ aPropertyName ];
+
+ ppEntries++;
+ pValue++;
+ }
+}
+
+// XInterface
+
+Any SAL_CALL GenericPropertySet::queryInterface( const Type & rType )
+ throw( RuntimeException )
+{
+ return OWeakAggObject::queryInterface( rType );
+}
+
+Any SAL_CALL GenericPropertySet::queryAggregation( const Type & rType )
+ throw(RuntimeException)
+{
+ Any aAny;
+
+ if( rType == ::getCppuType((const Reference< XServiceInfo >*)0) )
+ aAny <<= Reference< XServiceInfo >(this);
+ else if( rType == ::getCppuType((const Reference< XTypeProvider >*)0) )
+ aAny <<= Reference< XTypeProvider >(this);
+ else if( rType == ::getCppuType((const Reference< XPropertySet >*)0) )
+ aAny <<= Reference< XPropertySet >(this);
+ else if( rType == ::getCppuType((const Reference< XMultiPropertySet >*)0) )
+ aAny <<= Reference< XMultiPropertySet >(this);
+ else
+ aAny <<= OWeakAggObject::queryAggregation( rType );
+
+ return aAny;
+}
+
+void SAL_CALL GenericPropertySet::acquire() throw()
+{
+ OWeakAggObject::acquire();
+}
+
+void SAL_CALL GenericPropertySet::release() throw()
+{
+ OWeakAggObject::release();
+}
+
+uno::Sequence< uno::Type > SAL_CALL GenericPropertySet::getTypes()
+ throw (uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( 5 );
+ uno::Type* pTypes = aTypes.getArray();
+
+ *pTypes++ = ::getCppuType((const uno::Reference< XAggregation>*)0);
+ *pTypes++ = ::getCppuType((const uno::Reference< XServiceInfo>*)0);
+ *pTypes++ = ::getCppuType((const uno::Reference< XTypeProvider>*)0);
+ *pTypes++ = ::getCppuType((const uno::Reference< XPropertySet>*)0);
+ *pTypes++ = ::getCppuType((const uno::Reference< XMultiPropertySet>*)0);
+
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL GenericPropertySet::getImplementationId()
+ throw (uno::RuntimeException)
+{
+ MutexGuard aGuard( maMutex );
+
+ static uno::Sequence< sal_Int8 > aId;
+ if( aId.getLength() == 0 )
+ {
+ aId.realloc( 16 );
+ rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True );
+ }
+ return aId;
+}
+
+// XServiceInfo
+
+sal_Bool SAL_CALL GenericPropertySet::supportsService( const OUString& ServiceName ) throw(RuntimeException)
+{
+ Sequence< OUString > aSNL( getSupportedServiceNames() );
+ const OUString * pArray = aSNL.getConstArray();
+
+ for( sal_Int32 i = 0; i < aSNL.getLength(); ++i )
+ if( pArray[i] == ServiceName )
+ return sal_True;
+
+ return sal_False;
+}
+
+OUString SAL_CALL GenericPropertySet::getImplementationName() throw( RuntimeException )
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.comphelper.GenericPropertySet") );
+}
+
+Sequence< OUString > SAL_CALL GenericPropertySet::getSupportedServiceNames( )
+ throw( RuntimeException )
+{
+ Sequence< OUString > aSNS( 1 );
+ aSNS.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.XPropertySet" ));
+ return aSNS;
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > comphelper::GenericPropertySet_CreateInstance( comphelper::PropertySetInfo* pInfo )
+{
+ return (XPropertySet*)new GenericPropertySet( pInfo );
+}
+
diff --git a/comphelper/source/property/makefile.mk b/comphelper/source/property/makefile.mk
new file mode 100644
index 000000000000..1bcdb4c8dd63
--- /dev/null
+++ b/comphelper/source/property/makefile.mk
@@ -0,0 +1,65 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+PRJINC=..$/..$/inc
+PRJNAME=comphelper
+TARGET=property
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings ----------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files -------------------------------------
+
+SLOFILES= \
+ $(SLO)$/MasterPropertySetInfo.obj \
+ $(SLO)$/MasterPropertySet.obj \
+ $(SLO)$/ChainablePropertySetInfo.obj \
+ $(SLO)$/ChainablePropertySet.obj \
+ $(SLO)$/TypeGeneration.obj \
+ $(SLO)$/genericpropertyset.obj\
+ $(SLO)$/propertysethelper.obj \
+ $(SLO)$/propertysetinfo.obj \
+ $(SLO)$/composedprops.obj \
+ $(SLO)$/propagg.obj \
+ $(SLO)$/property.obj \
+ $(SLO)$/propmultiplex.obj \
+ $(SLO)$/propstate.obj \
+ $(SLO)$/propertystatecontainer.obj \
+ $(SLO)$/propertycontainer.obj \
+ $(SLO)$/propertycontainerhelper.obj \
+ $(SLO)$/propertybag.obj \
+ $(SLO)$/opropertybag.obj
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/comphelper/source/property/opropertybag.cxx b/comphelper/source/property/opropertybag.cxx
new file mode 100644
index 000000000000..f1282a48c2dd
--- /dev/null
+++ b/comphelper/source/property/opropertybag.cxx
@@ -0,0 +1,585 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+
+#include "opropertybag.hxx"
+#include "comphelper_module.hxx"
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/Property.hpp>
+
+#include <comphelper/namedvaluecollection.hxx>
+
+#include <cppuhelper/exc_hlp.hxx>
+#include <osl/thread.h>
+
+#include <algorithm>
+#include <functional>
+
+
+//--------------------------------------------------------------------------
+using namespace ::com::sun::star;
+
+void createRegistryInfo_OPropertyBag()
+{
+ static ::comphelper::module::OAutoRegistration< ::comphelper::OPropertyBag > aAutoRegistration;
+}
+
+//........................................................................
+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;
+ using namespace ::com::sun::star::container;
+
+ //====================================================================
+ //= 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 );
+ bool AllowEmptyPropertyName(false);
+ aArguments.get_ensureType( "AllowEmptyPropertyName",
+ AllowEmptyPropertyName );
+ if (AllowEmptyPropertyName) {
+ m_aDynamicProperties.setAllowEmptyPropertyName(
+ AllowEmptyPropertyName);
+ }
+ }
+
+ //--------------------------------------------------------------------
+ ::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)
+ {
+ { // do not lock mutex while notifying (#i93514#) to prevent deadlock
+ ::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() );
+ }
+
+ //--------------------------------------------------------------------
+ ::sal_Bool SAL_CALL OPropertyBag::has( const Any& /*aElement*/ ) throw (RuntimeException)
+ {
+ // XSet is only a workaround for addProperty not being able to add default-void properties.
+ // So, everything of XSet except insert is implemented empty
+ return sal_False;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OPropertyBag::insert( const Any& _element ) throw (IllegalArgumentException, ElementExistException, RuntimeException)
+ {
+ // This is a workaround for addProperty not being able to add default-void properties.
+ // If we ever have a smarter XPropertyContainer::addProperty interface, we can remove this, ehm, well, hack.
+ Property aProperty;
+ if ( !( _element >>= aProperty ) )
+ throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
+
+ ::osl::ClearableMutexGuard g( m_aMutex );
+
+ // check whether the type is allowed, everything else will be checked
+ // by m_aDynamicProperties
+ if ( !m_aAllowedTypes.empty()
+ && m_aAllowedTypes.find( aProperty.Type ) == m_aAllowedTypes.end()
+ )
+ throw IllegalTypeException( ::rtl::OUString(), *this );
+
+ m_aDynamicProperties.addVoidProperty( aProperty.Name, aProperty.Type, findFreeHandle(), aProperty.Attributes );
+
+ // our property info is dirty
+ m_pArrayHelper.reset();
+
+ g.clear();
+ setModified(sal_True);
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OPropertyBag::remove( const Any& /*aElement*/ ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
+ {
+ // XSet is only a workaround for addProperty not being able to add default-void properties.
+ // So, everything of XSet except insert is implemented empty
+ throw NoSuchElementException( ::rtl::OUString(), *this );
+ }
+
+
+ //--------------------------------------------------------------------
+ Reference< XEnumeration > SAL_CALL OPropertyBag::createEnumeration( ) throw (RuntimeException)
+ {
+ // XSet is only a workaround for addProperty not being able to add default-void properties.
+ // So, everything of XSet except insert is implemented empty
+ return NULL;
+ }
+
+ //--------------------------------------------------------------------
+ Type SAL_CALL OPropertyBag::getElementType( ) throw (RuntimeException)
+ {
+ // XSet is only a workaround for addProperty not being able to add default-void properties.
+ // So, everything of XSet except insert is implemented empty
+ return Type();
+ }
+
+ //--------------------------------------------------------------------
+ ::sal_Bool SAL_CALL OPropertyBag::hasElements( ) throw (RuntimeException)
+ {
+ // XSet is only a workaround for addProperty not being able to add default-void properties.
+ // So, everything of XSet except insert is implemented empty
+ return sal_False;
+ }
+
+ //--------------------------------------------------------------------
+ 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::ClearableMutexGuard g( 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();
+
+ g.clear();
+ setModified(sal_True);
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OPropertyBag::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException)
+ {
+ ::osl::ClearableMutexGuard g( m_aMutex );
+
+ m_aDynamicProperties.removeProperty( _rName );
+
+ // our property info is dirty
+ m_pArrayHelper.reset();
+
+ g.clear();
+ 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
+//........................................................................
+
diff --git a/comphelper/source/property/opropertybag.hxx b/comphelper/source/property/opropertybag.hxx
new file mode 100644
index 000000000000..3b9549f7c023
--- /dev/null
+++ b/comphelper/source/property/opropertybag.hxx
@@ -0,0 +1,242 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef COMPHELPER_OPROPERTYBAG_HXX
+#define COMPHELPER_OPROPERTYBAG_HXX
+
+/** === begin UNO includes === **/
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyContainer.hpp>
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/container/XSet.hpp>
+/** === end UNO includes === **/
+
+#include <cppuhelper/implbase6.hxx>
+#include <comphelper/propstate.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/propertybag.hxx>
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <map>
+#include <set>
+#include <memory>
+
+//........................................................................
+namespace comphelper
+{
+//........................................................................
+
+ struct SAL_DLLPRIVATE UnoTypeLess : public ::std::unary_function< ::com::sun::star::uno::Type, bool >
+ {
+ inline bool operator()( const ::com::sun::star::uno::Type& _rLHS, const ::com::sun::star::uno::Type& _rRHS ) const
+ {
+ return rtl_ustr_compare(
+ _rLHS.getTypeLibType()->pTypeName->buffer,
+ _rRHS.getTypeLibType()->pTypeName->buffer
+ ) < 0;
+ }
+ };
+
+ typedef ::std::map< sal_Int32, ::com::sun::star::uno::Any > MapInt2Any;
+ typedef ::std::set< ::com::sun::star::uno::Type, UnoTypeLess > TypeBag;
+
+ //====================================================================
+ //= OPropertyBag
+ //====================================================================
+ typedef ::cppu::WeakAggImplHelper6 < ::com::sun::star::beans::XPropertyContainer
+ , ::com::sun::star::beans::XPropertyAccess
+ , ::com::sun::star::util::XModifiable
+ , ::com::sun::star::lang::XServiceInfo
+ , ::com::sun::star::lang::XInitialization
+ , ::com::sun::star::container::XSet
+ > OPropertyBag_Base;
+ typedef ::comphelper::OPropertyStateHelper OPropertyBag_PBase;
+
+ class OPropertyBag :public ::comphelper::OMutexAndBroadcastHelper // must be before OPropertyBag_PBase
+ ,public OPropertyBag_PBase
+ ,public OPropertyBag_Base
+ ,public ::cppu::IEventNotificationHook
+ {
+ private:
+ ::comphelper::ComponentContext
+ m_aContext;
+
+ /// our IPropertyArrayHelper implementation
+ ::std::auto_ptr< ::cppu::OPropertyArrayHelper >
+ m_pArrayHelper;
+ ::comphelper::PropertyBag
+ m_aDynamicProperties;
+ /// set of allowed property types
+ TypeBag m_aAllowedTypes;
+ /// should we automatically add properties which are tried to set, if they don't exist previously?
+ bool m_bAutoAddProperties;
+
+ /// for notification
+ ::cppu::OInterfaceContainerHelper m_NotifyListeners;
+ /// modify flag
+ bool m_isModified;
+
+ public:
+ OPropertyBag( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext );
+
+ // XServiceInfo - static versions
+ static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static(void) throw( ::com::sun::star::uno::RuntimeException );
+ static ::rtl::OUString getImplementationName_static(void) throw( ::com::sun::star::uno::RuntimeException );
+ static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
+ SAL_CALL Create(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >&);
+
+ protected:
+ virtual ~OPropertyBag();
+ DECLARE_XINTERFACE()
+ DECLARE_XTYPEPROVIDER()
+
+ /** === begin UNO interface implementations == **/
+ // XInitialization
+ virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XModifiable:
+ virtual ::sal_Bool SAL_CALL isModified( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setModified( ::sal_Bool bModified )
+ throw (::com::sun::star::beans::PropertyVetoException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // XModifyBroadcaster
+ virtual void SAL_CALL addModifyListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::util::XModifyListener > & xListener)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeModifyListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::util::XModifyListener > & xListener)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XPropertyContainer
+ virtual void SAL_CALL addProperty( const ::rtl::OUString& Name, ::sal_Int16 Attributes, const ::com::sun::star::uno::Any& DefaultValue ) throw (::com::sun::star::beans::PropertyExistException, ::com::sun::star::beans::IllegalTypeException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeProperty( const ::rtl::OUString& Name ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::NotRemoveableException, ::com::sun::star::uno::RuntimeException);
+
+ // XPropertyAccess
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPropertyValues( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setPropertyValues( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aProps ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+
+ // XPropertySet
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException);
+
+ // XSet
+ virtual ::sal_Bool SAL_CALL has( const ::com::sun::star::uno::Any& aElement ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL insert( const ::com::sun::star::uno::Any& aElement ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL remove( const ::com::sun::star::uno::Any& aElement ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
+
+ // XEnumerationAccess (base of XSet)
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createEnumeration( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XElementAccess (basf of XEnumerationAccess
+ virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException);
+ /** === UNO interface implementations == **/
+
+ // XPropertyState
+ virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 _nHandle ) const;
+
+ // OPropertyStateHelper
+ virtual ::com::sun::star::beans::PropertyState getPropertyStateByHandle( sal_Int32 _nHandle );
+
+ // OPropertySetHelper
+ virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const;
+ virtual sal_Bool SAL_CALL convertFastPropertyValue( ::com::sun::star::uno::Any & rConvertedValue, ::com::sun::star::uno::Any & rOldValue, sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) throw (::com::sun::star::lang::IllegalArgumentException);
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) throw (::com::sun::star::uno::Exception);
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
+
+ // IEventNotificationHook
+ virtual void fireEvents(
+ sal_Int32 * pnHandles,
+ sal_Int32 nCount,
+ sal_Bool bVetoable,
+ bool bIgnoreRuntimeExceptionsWhileFiring);
+
+ void SAL_CALL setModifiedImpl( ::sal_Bool bModified,
+ bool bIgnoreRuntimeExceptionsWhileFiring);
+
+ private:
+ /** finds a free property handle
+ @precond
+ our mutex is locked
+ */
+ sal_Int32 findFreeHandle() const;
+
+ /** implements the setPropertyValues method
+ @param _rProps
+ the property values to set
+
+ @throws PropertyVetoException
+ if the XMultiPropertySet::setPropertyValues call does so
+
+ @throws ::com::sun::star::lang::IllegalArgumentException
+ if the XMultiPropertySet::setPropertyValues call does so
+
+ @throws ::com::sun::star::lang::WrappedTargetException
+ if the XMultiPropertySet::setPropertyValues call does so
+
+ @throws ::com::sun::star::uno::RuntimeException
+ if the XMultiPropertySet::setPropertyValues call does so
+
+ @throws ::com::sun::star::beans::UnknownPropertyException
+ if the XMultiPropertySet::setPropertyValues call does so, and <arg>_bTolerateUnknownProperties</arg>
+ was set to <FALSE/>
+
+ @throws ::com::sun::star::lang::WrappedTargetException
+ if the XMultiPropertySet::setPropertyValues call did throw an exception not listed
+ above
+ */
+ void impl_setPropertyValues_throw( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rProps );
+
+ private:
+ OPropertyBag(); // never implemented
+ OPropertyBag( const OPropertyBag& ); // never implemented
+ OPropertyBag& operator=( const OPropertyBag& ); // never implemented
+ protected:
+ using ::cppu::OPropertySetHelper::getPropertyValues;
+ using ::cppu::OPropertySetHelper::setPropertyValues;
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+ };
+
+//........................................................................
+} // namespace comphelper
+//........................................................................
+
+#endif // COMPHELPER_OPROPERTYBAG_HXX
diff --git a/comphelper/source/property/propagg.cxx b/comphelper/source/property/propagg.cxx
new file mode 100644
index 000000000000..9c2fd868d973
--- /dev/null
+++ b/comphelper/source/property/propagg.cxx
@@ -0,0 +1,1047 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include "comphelper/propagg.hxx"
+#include "comphelper/property.hxx"
+#include <cppuhelper/queryinterface.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#if OSL_DEBUG_LEVEL > 0
+#include <typeinfo>
+#include <rtl/strbuf.hxx>
+#endif
+
+#include <algorithm>
+#include <set>
+
+//.........................................................................
+namespace comphelper
+{
+//.........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+
+ using namespace internal;
+
+ //------------------------------------------------------------------------------
+ namespace
+ {
+ const Property* lcl_findPropertyByName( const Sequence< Property >& _rProps, const ::rtl::OUString& _rName )
+ {
+ sal_Int32 nLen = _rProps.getLength();
+ const Property* pProperties = _rProps.getConstArray();
+ const Property* pResult = ::std::lower_bound(pProperties, pProperties + nLen,_rName, ::comphelper::PropertyStringLessFunctor());
+ if ( pResult && ( pResult == pProperties + nLen || pResult->Name != _rName) )
+ pResult = NULL;
+
+ return pResult;
+ }
+ }
+//==================================================================
+//= OPropertyArrayAggregationHelper
+//==================================================================
+
+//------------------------------------------------------------------------------
+OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper(
+ const Sequence< Property >& _rProperties, const Sequence< Property >& _rAggProperties,
+ IPropertyInfoService* _pInfoService, sal_Int32 _nFirstAggregateId )
+ :m_aProperties( _rProperties )
+{
+ sal_Int32 nDelegatorProps = _rProperties.getLength();
+ sal_Int32 nAggregateProps = _rAggProperties.getLength();
+
+ // make room for all properties
+ sal_Int32 nMergedProps = nDelegatorProps + nAggregateProps;
+ m_aProperties.realloc( nMergedProps );
+
+ const Property* pAggregateProps = _rAggProperties.getConstArray();
+ const Property* pDelegateProps = _rProperties.getConstArray();
+ Property* pMergedProps = m_aProperties.getArray();
+
+ // if properties are present both at the delegatee and the aggregate, then the former are supposed to win.
+ // So, we'll need an existence check.
+ ::std::set< ::rtl::OUString > aDelegatorProps;
+
+ // create the map for the delegator properties
+ sal_Int32 nMPLoop = 0;
+ for ( ; nMPLoop < nDelegatorProps; ++nMPLoop, ++pDelegateProps )
+ {
+ m_aPropertyAccessors[ pDelegateProps->Handle ] = OPropertyAccessor( -1, nMPLoop, sal_False );
+ OSL_ENSURE( aDelegatorProps.find( pDelegateProps->Name ) == aDelegatorProps.end(),
+ "OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper: duplicate delegatee property!" );
+ aDelegatorProps.insert( pDelegateProps->Name );
+ }
+
+ // create the map for the aggregate properties
+ sal_Int32 nAggregateHandle = _nFirstAggregateId;
+ pMergedProps += nDelegatorProps;
+ for ( ; nMPLoop < nMergedProps; ++pAggregateProps )
+ {
+ // if the aggregate property is present at the delegatee already, ignore it
+ if ( aDelegatorProps.find( pAggregateProps->Name ) != aDelegatorProps.end() )
+ {
+ --nMergedProps;
+ continue;
+ }
+
+ // next aggregate property - remember it
+ *pMergedProps = *pAggregateProps;
+
+ // determine the handle for the property which we will expose to the outside world
+ sal_Int32 nHandle = -1;
+ // ask the infor service first
+ if ( _pInfoService )
+ nHandle = _pInfoService->getPreferedPropertyId( pMergedProps->Name );
+
+ if ( -1 == nHandle )
+ // no handle from the info service -> default
+ nHandle = nAggregateHandle++;
+ else
+ { // check if we alread have a property with the given handle
+ const Property* pPropsTilNow = m_aProperties.getConstArray();
+ for ( sal_Int32 nCheck = 0; nCheck < nMPLoop; ++nCheck, ++pPropsTilNow )
+ if ( pPropsTilNow->Handle == nHandle )
+ { // conflicts -> use another one (which we don't check anymore, assuming _nFirstAggregateId was large enough)
+ nHandle = nAggregateHandle++;
+ break;
+ }
+ }
+
+ // remember the accessor for this property
+ m_aPropertyAccessors[ nHandle ] = OPropertyAccessor( pMergedProps->Handle, nMPLoop, sal_True );
+ pMergedProps->Handle = nHandle;
+
+ ++nMPLoop;
+ ++pMergedProps;
+ }
+ m_aProperties.realloc( nMergedProps );
+ pMergedProps = m_aProperties.getArray(); // reset, needed again below
+
+ // sortieren der Properties nach Namen
+ ::std::sort( pMergedProps, pMergedProps+nMergedProps, PropertyCompareByName());
+
+ pMergedProps = m_aProperties.getArray();
+
+ // Positionen in der Map abgleichen
+ for ( nMPLoop = 0; nMPLoop < nMergedProps; ++nMPLoop, ++pMergedProps )
+ m_aPropertyAccessors[ pMergedProps->Handle ].nPos = nMPLoop;
+}
+
+//------------------------------------------------------------------
+OPropertyArrayAggregationHelper::PropertyOrigin OPropertyArrayAggregationHelper::classifyProperty( const ::rtl::OUString& _rName )
+{
+ PropertyOrigin eOrigin = UNKNOWN_PROPERTY;
+ // look up the name
+ const Property* pPropertyDescriptor = lcl_findPropertyByName( m_aProperties, _rName );
+ if ( pPropertyDescriptor )
+ {
+ // look up the handle for this name
+ ConstPropertyAccessorMapIterator aPos = m_aPropertyAccessors.find( pPropertyDescriptor->Handle );
+ OSL_ENSURE( m_aPropertyAccessors.end() != aPos, "OPropertyArrayAggregationHelper::classifyProperty: should have this handle in my map!" );
+ if ( m_aPropertyAccessors.end() != aPos )
+ {
+ eOrigin = aPos->second.bAggregate ? AGGREGATE_PROPERTY : DELEGATOR_PROPERTY;
+ }
+ }
+ return eOrigin;
+}
+
+//------------------------------------------------------------------
+Property OPropertyArrayAggregationHelper::getPropertyByName( const ::rtl::OUString& _rPropertyName ) throw( UnknownPropertyException )
+{
+ const Property* pProperty = findPropertyByName( _rPropertyName );
+
+ if ( !pProperty )
+ throw UnknownPropertyException();
+
+ return *pProperty;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool OPropertyArrayAggregationHelper::hasPropertyByName(const ::rtl::OUString& _rPropertyName)
+{
+ return NULL != findPropertyByName( _rPropertyName );
+}
+
+//------------------------------------------------------------------------------
+const Property* OPropertyArrayAggregationHelper::findPropertyByName(const :: rtl::OUString& _rName ) const
+{
+ return lcl_findPropertyByName( m_aProperties, _rName );
+}
+
+//------------------------------------------------------------------------------
+sal_Int32 OPropertyArrayAggregationHelper::getHandleByName(const ::rtl::OUString& _rPropertyName)
+{
+ const Property* pProperty = findPropertyByName( _rPropertyName );
+ return pProperty ? pProperty->Handle : -1;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool OPropertyArrayAggregationHelper::fillPropertyMembersByHandle(
+ ::rtl::OUString* _pPropName, sal_Int16* _pAttributes, sal_Int32 _nHandle)
+{
+ ConstPropertyAccessorMapIterator i = m_aPropertyAccessors.find(_nHandle);
+ sal_Bool bRet = i != m_aPropertyAccessors.end();
+ if (bRet)
+ {
+ const ::com::sun::star::beans::Property& rProperty = m_aProperties.getConstArray()[(*i).second.nPos];
+ if (_pPropName)
+ *_pPropName = rProperty.Name;
+ if (_pAttributes)
+ *_pAttributes = rProperty.Attributes;
+ }
+ return bRet;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle, Property& _rProperty ) const
+{
+ ConstPropertyAccessorMapIterator pos = m_aPropertyAccessors.find(_nHandle);
+ if ( pos != m_aPropertyAccessors.end() )
+ {
+ _rProperty = m_aProperties[ pos->second.nPos ];
+ return sal_True;
+ }
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle(
+ ::rtl::OUString* _pPropName, sal_Int32* _pOriginalHandle, sal_Int32 _nHandle) const
+{
+ ConstPropertyAccessorMapIterator i = m_aPropertyAccessors.find(_nHandle);
+ sal_Bool bRet = i != m_aPropertyAccessors.end() && (*i).second.bAggregate;
+ if (bRet)
+ {
+ if (_pOriginalHandle)
+ *_pOriginalHandle = (*i).second.nOriginalHandle;
+ if (_pPropName)
+ {
+ OSL_ENSURE((*i).second.nPos < m_aProperties.getLength(),"Invalid index for sequence!");
+ const ::com::sun::star::beans::Property& rProperty = m_aProperties.getConstArray()[(*i).second.nPos];
+ *_pPropName = rProperty.Name;
+ }
+ }
+ return bRet;
+}
+
+
+//------------------------------------------------------------------------------
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property> OPropertyArrayAggregationHelper::getProperties()
+{
+ return m_aProperties;
+}
+
+
+//------------------------------------------------------------------------------
+sal_Int32 OPropertyArrayAggregationHelper::fillHandles(
+ sal_Int32* _pHandles, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rPropNames )
+{
+ sal_Int32 nHitCount = 0;
+ const ::rtl::OUString* pReqProps = _rPropNames.getConstArray();
+ sal_Int32 nReqLen = _rPropNames.getLength();
+
+#if OSL_DEBUG_LEVEL > 0
+ // assure that the sequence is sorted
+ {
+ const ::rtl::OUString* pLookup = _rPropNames.getConstArray();
+ const ::rtl::OUString* pEnd = _rPropNames.getConstArray() + _rPropNames.getLength() - 1;
+ for (; pLookup < pEnd; ++pLookup)
+ {
+ const ::rtl::OUString* pCompare = pLookup + 1;
+ const ::rtl::OUString* pCompareEnd = pEnd + 1;
+ for (; pCompare < pCompareEnd; ++pCompare)
+ {
+ OSL_ENSURE(pLookup->compareTo(*pCompare) < 0, "OPropertyArrayAggregationHelper::fillHandles : property names are not sorted!");
+ }
+ }
+ }
+#endif
+
+ const ::com::sun::star::beans::Property* pCur = m_aProperties.getConstArray();
+ const ::com::sun::star::beans::Property* pEnd = m_aProperties.getConstArray() + m_aProperties.getLength();
+
+ for( sal_Int32 i = 0; i < nReqLen; ++i )
+ {
+ // Logarithmus ermitteln
+ sal_uInt32 n = (sal_uInt32)(pEnd - pCur);
+ sal_Int32 nLog = 0;
+ while( n )
+ {
+ nLog += 1;
+ n = n >> 1;
+ }
+
+ // Anzahl der noch zu suchenden Properties * dem Log2 der verbleibenden
+ // zu dursuchenden Properties.
+ if( (nReqLen - i) * nLog >= pEnd - pCur )
+ {
+ // linear search is better
+ while( pCur < pEnd && pReqProps[i] > pCur->Name )
+ {
+ pCur++;
+ }
+ if( pCur < pEnd && pReqProps[i] == pCur->Name )
+ {
+ _pHandles[i] = pCur->Handle;
+ nHitCount++;
+ }
+ else
+ _pHandles[i] = -1;
+ }
+ else
+ {
+ // binary search is better
+ sal_Int32 nCompVal = 1;
+ const ::com::sun::star::beans::Property* pOldEnd = pEnd--;
+ const ::com::sun::star::beans::Property* pMid = pCur;
+
+ while( nCompVal != 0 && pCur <= pEnd )
+ {
+ pMid = (pEnd - pCur) / 2 + pCur;
+
+ nCompVal = pReqProps[i].compareTo( pMid->Name );
+
+ if( nCompVal > 0 )
+ pCur = pMid + 1;
+ else
+ pEnd = pMid - 1;
+ }
+
+ if( nCompVal == 0 )
+ {
+ _pHandles[i] = pMid->Handle;
+ nHitCount++;
+ pCur = pMid +1;
+ }
+ else if( nCompVal > 0 )
+ {
+ _pHandles[i] = -1;
+ pCur = pMid + 1;
+ }
+ else
+ {
+ _pHandles[i] = -1;
+ pCur = pMid;
+ }
+ pEnd = pOldEnd;
+ }
+ }
+ return nHitCount;
+}
+
+//==================================================================
+//= PropertyForwarder
+//==================================================================
+namespace internal
+{
+ class PropertyForwarder
+ {
+ private:
+ OPropertySetAggregationHelper& m_rAggregationHelper;
+ ::std::set< sal_Int32 > m_aProperties;
+ sal_Int32 m_nCurrentlyForwarding;
+
+ public:
+ PropertyForwarder( OPropertySetAggregationHelper& _rAggregationHelper );
+ ~PropertyForwarder();
+
+ /** declares that the forwarder should be responsible for the given property
+
+ @param _nHandle
+ the public handle (<em>not</em> the original handle!) of the property
+ */
+ void takeResponsibilityFor( sal_Int32 _nHandle );
+
+ /** checks whether the forwarder is responsible for the given property
+ */
+ bool isResponsibleFor( sal_Int32 _nHandle );
+
+ /// actually forwards a property value to the aggregate
+ void doForward( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception );
+
+ sal_Int32 getCurrentlyForwardedProperty( ) const { return m_nCurrentlyForwarding; }
+ };
+
+ //--------------------------------------------------------------------------
+ PropertyForwarder::PropertyForwarder( OPropertySetAggregationHelper& _rAggregationHelper )
+ :m_rAggregationHelper( _rAggregationHelper )
+ ,m_nCurrentlyForwarding( -1 )
+ {
+ }
+
+ //--------------------------------------------------------------------------
+ PropertyForwarder::~PropertyForwarder()
+ {
+ }
+
+ //--------------------------------------------------------------------------
+ void PropertyForwarder::takeResponsibilityFor( sal_Int32 _nHandle )
+ {
+ m_aProperties.insert( _nHandle );
+ }
+
+ //--------------------------------------------------------------------------
+ bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle )
+ {
+ return m_aProperties.find( _nHandle ) != m_aProperties.end();
+ }
+
+ //--------------------------------------------------------------------------
+ void PropertyForwarder::doForward( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception )
+ {
+ OSL_ENSURE( m_rAggregationHelper.m_xAggregateSet.is(), "PropertyForwarder::doForward: no property set!" );
+ if ( m_rAggregationHelper.m_xAggregateSet.is() )
+ {
+ m_rAggregationHelper.forwardingPropertyValue( _nHandle );
+
+ OSL_ENSURE( m_nCurrentlyForwarding == -1, "PropertyForwarder::doForward: reentrance?" );
+ m_nCurrentlyForwarding = _nHandle;
+
+ try
+ {
+ m_rAggregationHelper.m_xAggregateSet->setPropertyValue( m_rAggregationHelper.getPropertyName( _nHandle ), _rValue );
+ // TODO: cache the property name? (it's a O(log n) search)
+ }
+ catch( const Exception& )
+ {
+ m_rAggregationHelper.forwardedPropertyValue( _nHandle, false );
+ throw;
+ }
+
+ m_nCurrentlyForwarding = -1;
+
+ m_rAggregationHelper.forwardedPropertyValue( _nHandle, true );
+ }
+ }
+}
+
+//==================================================================
+//= OPropertySetAggregationHelper
+//==================================================================
+
+//------------------------------------------------------------------------------
+OPropertySetAggregationHelper::OPropertySetAggregationHelper( ::cppu::OBroadcastHelper& rBHlp )
+ :OPropertyStateHelper( rBHlp )
+ ,m_bListening( sal_False )
+{
+ m_pForwarder = new PropertyForwarder( *this );
+}
+
+//------------------------------------------------------------------------------
+OPropertySetAggregationHelper::~OPropertySetAggregationHelper()
+{
+ delete m_pForwarder;
+}
+
+//------------------------------------------------------------------------------
+ ::com::sun::star::uno::Any SAL_CALL OPropertySetAggregationHelper::queryInterface(const ::com::sun::star::uno::Type& _rType) throw( ::com::sun::star::uno::RuntimeException)
+{
+ ::com::sun::star::uno::Any aReturn = OPropertyStateHelper::queryInterface(_rType);
+
+ if ( !aReturn.hasValue() )
+ aReturn = cppu::queryInterface(_rType
+ ,static_cast< ::com::sun::star::beans::XPropertiesChangeListener*>(this)
+ ,static_cast< ::com::sun::star::beans::XVetoableChangeListener*>(this)
+ ,static_cast< ::com::sun::star::lang::XEventListener*>(static_cast< ::com::sun::star::beans::XPropertiesChangeListener*>(this))
+ );
+
+ return aReturn;
+}
+
+//------------------------------------------------------------------------------
+void OPropertySetAggregationHelper::disposing()
+{
+ osl::MutexGuard aGuard(rBHelper.rMutex);
+
+ if ( m_xAggregateSet.is() && m_bListening )
+ {
+ // als einziger Listener anmelden
+ m_xAggregateMultiSet->removePropertiesChangeListener(this);
+ m_xAggregateSet->removeVetoableChangeListener(::rtl::OUString(), this);
+ m_bListening = sal_False;
+ }
+
+ OPropertyStateHelper::disposing();
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::disposing(const ::com::sun::star::lang::EventObject& _rSource) throw ( ::com::sun::star::uno::RuntimeException)
+{
+ OSL_ENSURE(m_xAggregateSet.is(), "OPropertySetAggregationHelper::disposing : don't have an aggregate anymore !");
+ if (_rSource.Source == m_xAggregateSet)
+ m_bListening = sal_False;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::propertiesChange(const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyChangeEvent>& _rEvents) throw( ::com::sun::star::uno::RuntimeException)
+{
+ OSL_ENSURE(m_xAggregateSet.is(), "OPropertySetAggregationHelper::propertiesChange : have no aggregate !");
+
+ sal_Int32 nLen = _rEvents.getLength();
+ cppu::IPropertyArrayHelper& rPH = getInfoHelper();
+
+ if (1 == nLen)
+ {
+ const ::com::sun::star::beans::PropertyChangeEvent& evt = _rEvents.getConstArray()[0];
+ OSL_ENSURE(evt.PropertyName.getLength() > 0, "OPropertySetAggregationHelper::propertiesChange : invalid event !");
+ // we had a bug where this assertion would have us saved a whole day :) (72514)
+ sal_Int32 nHandle = rPH.getHandleByName( evt.PropertyName );
+
+ // If nHandle is -1 the event marks a (aggregate) property which we hide to callers
+ // If isCurrentlyForwardingProperty( nHandle ) is <TRUE/>, then we ourself triggered
+ // setting this property. In this case, it will be notified later (by the OPropertySetHelper
+ // implementation)
+
+ if ( ( nHandle != -1 ) && !isCurrentlyForwardingProperty( nHandle ) )
+ fire(&nHandle, &evt.NewValue, &evt.OldValue, 1, sal_False);
+ }
+ else
+ {
+ sal_Int32* pHandles = new sal_Int32[nLen];
+ ::com::sun::star::uno::Any* pNewValues = new ::com::sun::star::uno::Any[nLen];
+ ::com::sun::star::uno::Any* pOldValues = new ::com::sun::star::uno::Any[nLen];
+
+ const ::com::sun::star::beans::PropertyChangeEvent* pEvents = _rEvents.getConstArray();
+ sal_Int32 nDest = 0;
+ for (sal_Int32 nSource=0; nSource<nLen; ++nSource, ++pEvents)
+ {
+ sal_Int32 nHandle = rPH.getHandleByName(pEvents->PropertyName);
+ if ( ( nHandle != -1 ) && !isCurrentlyForwardingProperty( nHandle ) )
+ { // same as above : -1 is valid (73247) ...
+ pHandles[nDest] = nHandle;
+ pNewValues[nDest] = pEvents->NewValue;
+ pOldValues[nDest] = pEvents->OldValue;
+ ++nDest;
+ }
+ }
+
+ if (nDest)
+ fire(pHandles, pNewValues, pOldValues, nDest, sal_False);
+
+ delete[] pHandles;
+ delete[] pNewValues;
+ delete[] pOldValues;
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::vetoableChange(const ::com::sun::star::beans::PropertyChangeEvent& _rEvent) throw( ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException)
+{
+ OSL_ENSURE(m_xAggregateSet.is(), "OPropertySetAggregationHelper::vetoableChange : have no aggregate !");
+
+ cppu::IPropertyArrayHelper& rPH = getInfoHelper();
+
+ sal_Int32 nHandle = rPH.getHandleByName(_rEvent.PropertyName);
+ fire(&nHandle, &_rEvent.NewValue, &_rEvent.OldValue, 1, sal_True);
+}
+
+//------------------------------------------------------------------------------
+void OPropertySetAggregationHelper::setAggregation(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxDelegate)
+ throw( ::com::sun::star::lang::IllegalArgumentException )
+{
+ osl::MutexGuard aGuard(rBHelper.rMutex);
+
+ if (m_bListening && m_xAggregateSet.is())
+ {
+ m_xAggregateMultiSet->removePropertiesChangeListener(this);
+ m_xAggregateSet->removeVetoableChangeListener(::rtl::OUString(), this);
+ m_bListening = sal_False;
+ }
+
+ m_xAggregateState = m_xAggregateState.query( _rxDelegate );
+ m_xAggregateSet = m_xAggregateSet.query( _rxDelegate );
+ m_xAggregateMultiSet = m_xAggregateMultiSet.query( _rxDelegate );
+ m_xAggregateFastSet = m_xAggregateFastSet.query( _rxDelegate );
+
+ // must support XPropertySet and XMultiPropertySet
+ if ( m_xAggregateSet.is() && !m_xAggregateMultiSet.is() )
+ throw ::com::sun::star::lang::IllegalArgumentException();
+}
+
+//------------------------------------------------------------------------------
+void OPropertySetAggregationHelper::startListening()
+{
+ osl::MutexGuard aGuard(rBHelper.rMutex);
+
+ if (!m_bListening && m_xAggregateSet.is())
+ {
+ // als einziger Listener anmelden
+ ::com::sun::star::uno::Sequence< ::rtl::OUString > aPropertyNames;
+ m_xAggregateMultiSet->addPropertiesChangeListener(aPropertyNames, this);
+ m_xAggregateSet->addVetoableChangeListener(::rtl::OUString(), this);
+
+ m_bListening = sal_True;
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::addVetoableChangeListener(const ::rtl::OUString& _rPropertyName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener>& _rxListener)
+ throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
+{
+ OPropertySetHelper::addVetoableChangeListener(_rPropertyName, _rxListener);
+ if (!m_bListening)
+ startListening();
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::addPropertyChangeListener(const ::rtl::OUString& _rPropertyName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener>& _rxListener)
+ throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
+{
+ OPropertySetHelper::addPropertyChangeListener(_rPropertyName, _rxListener);
+ if (!m_bListening)
+ startListening();
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::addPropertiesChangeListener(const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rPropertyNames,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener>& _rxListener)
+ throw( ::com::sun::star::uno::RuntimeException)
+{
+ OPropertySetHelper::addPropertiesChangeListener(_rPropertyNames, _rxListener);
+ if (!m_bListening)
+ startListening();
+}
+
+//------------------------------------------------------------------------------
+sal_Int32 OPropertySetAggregationHelper::getOriginalHandle(sal_Int32 nHandle) const
+{
+ OPropertyArrayAggregationHelper& rPH = (OPropertyArrayAggregationHelper&)const_cast<OPropertySetAggregationHelper*>(this)->getInfoHelper();
+ sal_Int32 nOriginalHandle = -1;
+ rPH.fillAggregatePropertyInfoByHandle(NULL, &nOriginalHandle, nHandle);
+ return nOriginalHandle;
+}
+
+//--------------------------------------------------------------------------
+::rtl::OUString OPropertySetAggregationHelper::getPropertyName( sal_Int32 _nHandle ) const
+{
+ OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( const_cast<OPropertySetAggregationHelper*>(this)->getInfoHelper() );
+ Property aProperty;
+ OSL_VERIFY( rPH.getPropertyByHandle( _nHandle, aProperty ) );
+ return aProperty.Name;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::setFastPropertyValue(sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue)
+ throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException,
+ ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
+ ::rtl::OUString aPropName;
+ sal_Int32 nOriginalHandle = -1;
+
+ // does the handle belong to the aggregation ?
+ if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, _nHandle))
+ if (m_xAggregateFastSet.is())
+ m_xAggregateFastSet->setFastPropertyValue(nOriginalHandle, _rValue);
+ else
+ m_xAggregateSet->setPropertyValue(aPropName, _rValue);
+ else
+ OPropertySetHelper::setFastPropertyValue(_nHandle, _rValue);
+}
+
+//------------------------------------------------------------------------------
+void OPropertySetAggregationHelper::getFastPropertyValue( ::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const
+{
+ OPropertyArrayAggregationHelper& rPH = (OPropertyArrayAggregationHelper&)const_cast<OPropertySetAggregationHelper*>(this)->getInfoHelper();
+ ::rtl::OUString aPropName;
+ sal_Int32 nOriginalHandle = -1;
+
+ if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
+ {
+ if (m_xAggregateFastSet.is())
+ rValue = m_xAggregateFastSet->getFastPropertyValue(nOriginalHandle);
+ else
+ rValue = m_xAggregateSet->getPropertyValue(aPropName);
+ }
+ else if ( m_pForwarder->isResponsibleFor( nHandle ) )
+ {
+ // this is a property which has been "overwritten" in our instance (thus
+ // fillAggregatePropertyInfoByHandle didn't find it)
+ rValue = m_xAggregateSet->getPropertyValue( getPropertyName( nHandle ) );
+ }
+}
+
+//------------------------------------------------------------------------------
+ ::com::sun::star::uno::Any SAL_CALL OPropertySetAggregationHelper::getFastPropertyValue(sal_Int32 nHandle)
+ throw( ::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
+ ::rtl::OUString aPropName;
+ sal_Int32 nOriginalHandle = -1;
+ ::com::sun::star::uno::Any aValue;
+
+ if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
+ {
+ if (m_xAggregateFastSet.is())
+ aValue = m_xAggregateFastSet->getFastPropertyValue(nOriginalHandle);
+ else
+ aValue = m_xAggregateSet->getPropertyValue(aPropName);
+ }
+ else
+ aValue = OPropertySetHelper::getFastPropertyValue(nHandle);
+
+ return aValue;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::setPropertyValues(
+ const Sequence< ::rtl::OUString >& _rPropertyNames, const Sequence< Any >& _rValues )
+ throw ( PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException )
+{
+ OSL_ENSURE( !rBHelper.bInDispose, "OPropertySetAggregationHelper::setPropertyValues : do not use within the dispose call !");
+ OSL_ENSURE( !rBHelper.bDisposed, "OPropertySetAggregationHelper::setPropertyValues : object is disposed" );
+
+ // check where the properties come from
+ if (!m_xAggregateSet.is())
+ OPropertySetHelper::setPropertyValues(_rPropertyNames, _rValues);
+ else if (_rPropertyNames.getLength() == 1) // use the more efficient way
+ {
+ try
+ {
+ setPropertyValue( _rPropertyNames[0], _rValues[0] );
+ }
+ catch( const UnknownPropertyException& )
+ {
+ // by definition of XMultiPropertySet::setPropertyValues, unknown properties are to be ignored
+ #if OSL_DEBUG_LEVEL > 0
+ ::rtl::OStringBuffer aMessage;
+ aMessage.append( "OPropertySetAggregationHelper::setPropertyValues: unknown property '" );
+ aMessage.append( ::rtl::OUStringToOString( _rPropertyNames[0], RTL_TEXTENCODING_ASCII_US ) );
+ aMessage.append( "'" );
+ aMessage.append( "\n(implementation " );
+ aMessage.append( typeid( *this ).name() );
+ aMessage.append( ")" );
+ OSL_ENSURE( false, aMessage.getStr() );
+ #endif
+ }
+ }
+ else
+ {
+ OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
+
+ // determine which properties belong to the aggregate, and which ones to the delegator
+ const ::rtl::OUString* pNames = _rPropertyNames.getConstArray();
+ sal_Int32 nAggCount(0);
+ sal_Int32 nLen(_rPropertyNames.getLength());
+
+ for ( sal_Int32 i = 0; i < nLen; ++i, ++pNames )
+ {
+ OPropertyArrayAggregationHelper::PropertyOrigin ePropOrg = rPH.classifyProperty( *pNames );
+ if ( OPropertyArrayAggregationHelper::UNKNOWN_PROPERTY == ePropOrg )
+ throw WrappedTargetException( ::rtl::OUString(), static_cast< XMultiPropertySet* >( this ), makeAny( UnknownPropertyException( ) ) );
+ // due to a flaw in the API design, this method is not allowed to throw an UnknownPropertyException
+ // so we wrap it into a WrappedTargetException
+ // #107545# - 2002-02-20 - fs@openoffice.org
+
+ if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY == ePropOrg )
+ ++nAggCount;
+ }
+
+ pNames = _rPropertyNames.getConstArray(); // reset, we'll need it again below ...
+
+ // all properties belong to the aggregate
+ if (nAggCount == nLen)
+ m_xAggregateMultiSet->setPropertyValues(_rPropertyNames, _rValues);
+
+ // all properties belong to the aggregating object
+ else if (nAggCount == 0)
+ OPropertySetHelper::setPropertyValues(_rPropertyNames, _rValues);
+
+ // mixed
+ else
+ {
+ const ::com::sun::star::uno::Any* pValues = _rValues.getConstArray();
+ ::com::sun::star::uno::Any* pConvertedValues = NULL;
+ ::com::sun::star::uno::Any* pOldValues = NULL;
+ sal_Int32* pHandles = NULL;
+
+ try
+ {
+ // dividing the Names and _rValues
+
+ // aggregate's names
+ Sequence< ::rtl::OUString > AggPropertyNames( nAggCount );
+ ::rtl::OUString* pAggNames = AggPropertyNames.getArray();
+ // aggregate's values
+ Sequence< Any > AggValues( nAggCount );
+ Any* pAggValues = AggValues.getArray();
+
+ // delegator names
+ Sequence< ::rtl::OUString > DelPropertyNames( nLen - nAggCount );
+ ::rtl::OUString* pDelNames = DelPropertyNames.getArray();
+
+ // delegator values
+ Sequence< Any > DelValues( nLen - nAggCount );
+ Any* pDelValues = DelValues.getArray();
+
+ for ( sal_Int32 i = 0; i < nLen; ++i, ++pNames, ++pValues )
+ {
+ if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY == rPH.classifyProperty( *pNames ) )
+ {
+ *pAggNames++ = *pNames;
+ *pAggValues++ = *pValues;
+ }
+ else
+ {
+ *pDelNames++ = *pNames;
+ *pDelValues++ = *pValues;
+ }
+ }
+
+ // reset, needed below
+ pDelValues = DelValues.getArray();
+
+ pHandles = new sal_Int32[ nLen - nAggCount ];
+
+ // get the map table
+ cppu::IPropertyArrayHelper& rPH2 = getInfoHelper();
+
+ // fill the handle array
+ sal_Int32 nHitCount = rPH2.fillHandles( pHandles, DelPropertyNames );
+ if (nHitCount != 0)
+ {
+
+ pConvertedValues = new ::com::sun::star::uno::Any[ nHitCount ];
+ pOldValues = new ::com::sun::star::uno::Any[ nHitCount ];
+ nHitCount = 0;
+ sal_Int32 i;
+
+ {
+ // must lock the mutex outside the loop. So all values are consistent.
+ osl::MutexGuard aGuard( rBHelper.rMutex );
+ for( i = 0; i < (nLen - nAggCount); ++i )
+ {
+ if( pHandles[i] != -1 )
+ {
+ sal_Int16 nAttributes;
+ rPH2.fillPropertyMembersByHandle( NULL, &nAttributes, pHandles[i] );
+ if( nAttributes & ::com::sun::star::beans::PropertyAttribute::READONLY )
+ throw ::com::sun::star::beans::PropertyVetoException();
+ // Will the property change?
+ if( convertFastPropertyValue( pConvertedValues[ nHitCount ], pOldValues[nHitCount],
+ pHandles[i], pDelValues[i] ) )
+ {
+ // only increment if the property really change
+ pHandles[nHitCount] = pHandles[i];
+ nHitCount++;
+ }
+ }
+ }
+ // release guard to fire events
+ }
+
+ // fire vetoable events
+ fire( pHandles, pConvertedValues, pOldValues, nHitCount, sal_True );
+
+ // setting the agg Properties
+ m_xAggregateMultiSet->setPropertyValues(AggPropertyNames, AggValues);
+
+ {
+ // must lock the mutex outside the loop.
+ osl::MutexGuard aGuard( rBHelper.rMutex );
+ // Loop over all changed properties
+ for( i = 0; i < nHitCount; i++ )
+ {
+ // Will the property change?
+ setFastPropertyValue_NoBroadcast( pHandles[i], pConvertedValues[i] );
+ }
+ // release guard to fire events
+ }
+
+ // fire change events
+ fire( pHandles, pConvertedValues, pOldValues, nHitCount, sal_False );
+ }
+ else
+ m_xAggregateMultiSet->setPropertyValues(AggPropertyNames, AggValues);
+
+ }
+ catch(::com::sun::star::uno::Exception&)
+ {
+ delete [] pHandles;
+ delete [] pOldValues;
+ delete [] pConvertedValues;
+ throw;
+ }
+
+ delete [] pHandles;
+ delete [] pOldValues;
+ delete [] pConvertedValues;
+ }
+ }
+}
+
+// XPropertyState
+//------------------------------------------------------------------------------
+ ::com::sun::star::beans::PropertyState SAL_CALL OPropertySetAggregationHelper::getPropertyState(const ::rtl::OUString& _rPropertyName)
+ throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
+{
+ OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
+ sal_Int32 nHandle = rPH.getHandleByName( _rPropertyName );
+
+ if (nHandle == -1)
+ {
+ throw ::com::sun::star::beans::UnknownPropertyException();
+ }
+
+ ::rtl::OUString aPropName;
+ sal_Int32 nOriginalHandle = -1;
+ if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
+ {
+ if (m_xAggregateState.is())
+ return m_xAggregateState->getPropertyState(_rPropertyName);
+ else
+ return ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
+ }
+ else
+ return getPropertyStateByHandle(nHandle);
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::setPropertyToDefault(const ::rtl::OUString& _rPropertyName)
+ throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
+{
+ OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
+ sal_Int32 nHandle = rPH.getHandleByName(_rPropertyName);
+ if (nHandle == -1)
+ {
+ throw ::com::sun::star::beans::UnknownPropertyException();
+ }
+
+ ::rtl::OUString aPropName;
+ sal_Int32 nOriginalHandle = -1;
+ if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
+ {
+ if (m_xAggregateState.is())
+ m_xAggregateState->setPropertyToDefault(_rPropertyName);
+ }
+ else
+ {
+ try
+ {
+ setPropertyToDefaultByHandle( nHandle );
+ }
+ catch( const UnknownPropertyException& ) { throw; }
+ catch( const RuntimeException& ) { throw; }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "OPropertySetAggregationHelper::setPropertyToDefault: caught an exception which is not allowed to leave here!" );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+ ::com::sun::star::uno::Any SAL_CALL OPropertySetAggregationHelper::getPropertyDefault(const ::rtl::OUString& aPropertyName)
+ throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
+{
+ OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
+ sal_Int32 nHandle = rPH.getHandleByName( aPropertyName );
+
+ if ( nHandle == -1 )
+ throw ::com::sun::star::beans::UnknownPropertyException();
+
+ ::rtl::OUString aPropName;
+ sal_Int32 nOriginalHandle = -1;
+ if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
+ {
+ if (m_xAggregateState.is())
+ return m_xAggregateState->getPropertyDefault(aPropertyName);
+ else
+ return ::com::sun::star::uno::Any();
+ }
+ else
+ return getPropertyDefaultByHandle(nHandle);
+}
+
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL OPropertySetAggregationHelper::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw(IllegalArgumentException)
+{
+ sal_Bool bModified = sal_False;
+
+ OSL_ENSURE( m_pForwarder->isResponsibleFor( _nHandle ), "OPropertySetAggregationHelper::convertFastPropertyValue: this is no forwarded property - did you use declareForwardedProperty for it?" );
+ if ( m_pForwarder->isResponsibleFor( _nHandle ) )
+ {
+ // need to determine the type of the property for conversion
+ OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
+ Property aProperty;
+ OSL_VERIFY( rPH.getPropertyByHandle( _nHandle, aProperty ) );
+
+ Any aCurrentValue;
+ getFastPropertyValue( aCurrentValue, _nHandle );
+ bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, aCurrentValue, aProperty.Type );
+ }
+
+ return bModified;
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw ( Exception )
+{
+ OSL_ENSURE( m_pForwarder->isResponsibleFor( _nHandle ), "OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast: this is no forwarded property - did you use declareForwardedProperty for it?" );
+ if ( m_pForwarder->isResponsibleFor( _nHandle ) )
+ m_pForwarder->doForward( _nHandle, _rValue );
+}
+
+//------------------------------------------------------------------------------
+void OPropertySetAggregationHelper::declareForwardedProperty( sal_Int32 _nHandle )
+{
+ OSL_ENSURE( !m_pForwarder->isResponsibleFor( _nHandle ), "OPropertySetAggregationHelper::declareForwardedProperty: already declared!" );
+ m_pForwarder->takeResponsibilityFor( _nHandle );
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::forwardingPropertyValue( sal_Int32 )
+{
+ // not interested in
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL OPropertySetAggregationHelper::forwardedPropertyValue( sal_Int32, bool )
+{
+ // not interested in
+}
+
+//------------------------------------------------------------------------------
+bool OPropertySetAggregationHelper::isCurrentlyForwardingProperty( sal_Int32 _nHandle ) const
+{
+ return m_pForwarder->getCurrentlyForwardedProperty() == _nHandle;
+}
+
+//.........................................................................
+} // namespace comphelper
+//.........................................................................
+
diff --git a/comphelper/source/property/property.cxx b/comphelper/source/property/property.cxx
new file mode 100644
index 000000000000..6ab48aa1965b
--- /dev/null
+++ b/comphelper/source/property/property.cxx
@@ -0,0 +1,245 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+
+
+#include <comphelper/property.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/types.hxx>
+#include <osl/diagnose.h>
+
+#if OSL_DEBUG_LEVEL > 0
+ #include <rtl/strbuf.hxx>
+ #include <cppuhelper/exc_hlp.hxx>
+ #include <osl/thread.h>
+ #include <com/sun/star/lang/XServiceInfo.hpp>
+ #include <typeinfo>
+#endif
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/uno/genfunc.h>
+
+#include <algorithm>
+#include <boost/bind.hpp>
+
+//.........................................................................
+namespace comphelper
+{
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::beans::XPropertySetInfo;
+ using ::com::sun::star::beans::Property;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::uno::cpp_queryInterface;
+ using ::com::sun::star::uno::cpp_acquire;
+ using ::com::sun::star::uno::cpp_release;
+#if OSL_DEBUG_LEVEL > 0
+ using ::com::sun::star::lang::XServiceInfo;
+#endif
+ using ::com::sun::star::uno::UNO_QUERY;
+ /** === end UNO using === **/
+ namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
+
+//------------------------------------------------------------------
+void copyProperties(const Reference<XPropertySet>& _rxSource,
+ const Reference<XPropertySet>& _rxDest)
+{
+ if (!_rxSource.is() || !_rxDest.is())
+ {
+ OSL_ENSURE(sal_False, "copyProperties: invalid arguments !");
+ return;
+ }
+
+ Reference< XPropertySetInfo > xSourceProps = _rxSource->getPropertySetInfo();
+ Reference< XPropertySetInfo > xDestProps = _rxDest->getPropertySetInfo();
+
+ Sequence< Property > aSourceProps = xSourceProps->getProperties();
+ const Property* pSourceProps = aSourceProps.getConstArray();
+ Property aDestProp;
+ for (sal_Int32 i=0; i<aSourceProps.getLength(); ++i, ++pSourceProps)
+ {
+ if ( xDestProps->hasPropertyByName(pSourceProps->Name) )
+ {
+ try
+ {
+ aDestProp = xDestProps->getPropertyByName(pSourceProps->Name);
+ if (0 == (aDestProp.Attributes & PropertyAttribute::READONLY) )
+ {
+ const Any aSourceValue = _rxSource->getPropertyValue(pSourceProps->Name);
+ if ( 0 != (aDestProp.Attributes & PropertyAttribute::MAYBEVOID) || aSourceValue.hasValue() )
+ _rxDest->setPropertyValue(pSourceProps->Name, aSourceValue);
+ }
+ }
+ catch (Exception&)
+ {
+#if OSL_DEBUG_LEVEL > 0
+ ::rtl::OStringBuffer aBuffer;
+ aBuffer.append( "::comphelper::copyProperties: could not copy property '" );
+ aBuffer.append( ::rtl::OString( pSourceProps->Name.getStr(), pSourceProps->Name.getLength(), RTL_TEXTENCODING_ASCII_US ) );
+ aBuffer.append( "' to the destination set (a '" );
+
+ Reference< XServiceInfo > xSI( _rxDest, UNO_QUERY );
+ if ( xSI.is() )
+ {
+ aBuffer.append( ::rtl::OUStringToOString( xSI->getImplementationName(), osl_getThreadTextEncoding() ) );
+ }
+ else
+ {
+ aBuffer.append( typeid( *_rxDest.get() ).name() );
+ }
+ aBuffer.append( "' implementation).\n" );
+
+ Any aException( ::cppu::getCaughtException() );
+ aBuffer.append( "Caught an exception of type '" );
+ ::rtl::OUString sExceptionType( aException.getValueTypeName() );
+ aBuffer.append( ::rtl::OString( sExceptionType.getStr(), sExceptionType.getLength(), RTL_TEXTENCODING_ASCII_US ) );
+ aBuffer.append( "'" );
+
+ Exception aBaseException;
+ if ( ( aException >>= aBaseException ) && aBaseException.Message.getLength() )
+ {
+ aBuffer.append( ", saying '" );
+ aBuffer.append( ::rtl::OString( aBaseException.Message.getStr(), aBaseException.Message.getLength(), osl_getThreadTextEncoding() ) );
+ aBuffer.append( "'" );
+ }
+ aBuffer.append( "." );
+
+ OSL_ENSURE( sal_False, aBuffer.getStr() );
+#endif
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------
+sal_Bool hasProperty(const rtl::OUString& _rName, const Reference<XPropertySet>& _rxSet)
+{
+ if (_rxSet.is())
+ {
+ // XPropertySetInfoRef xInfo(rxSet->getPropertySetInfo());
+ return _rxSet->getPropertySetInfo()->hasPropertyByName(_rName);
+ }
+ return sal_False;
+}
+
+//------------------------------------------------------------------
+bool findProperty(Property& o_rProp,
+ Sequence<Property>& i_seqProps,
+ const ::rtl::OUString& i_rPropName)
+{
+ const Property* pAry(i_seqProps.getConstArray());
+ const sal_Int32 nLen(i_seqProps.getLength());
+ const Property* pRes(
+ std::find_if(pAry,pAry+nLen,
+ boost::bind(PropertyStringEqualFunctor(),
+ _1,
+ boost::cref(i_rPropName))));
+ if( pRes == pAry+nLen )
+ return false;
+
+ o_rProp = *pRes;
+ return true;
+}
+
+//------------------------------------------------------------------
+void RemoveProperty(Sequence<Property>& _rProps, const rtl::OUString& _rPropName)
+{
+ sal_Int32 nLen = _rProps.getLength();
+
+ // binaere Suche
+ const Property* pProperties = _rProps.getConstArray();
+ const Property* pResult = ::std::lower_bound(pProperties, pProperties + nLen, _rPropName,PropertyStringLessFunctor());
+
+ // gefunden ?
+ if ( pResult && (pResult != pProperties + nLen) && (pResult->Name == _rPropName) )
+ {
+ OSL_ENSURE(pResult->Name.equals(_rPropName), "::RemoveProperty Properties nicht sortiert");
+ removeElementAt(_rProps, pResult - pProperties);
+ }
+}
+
+//------------------------------------------------------------------
+void ModifyPropertyAttributes(Sequence<Property>& seqProps, const ::rtl::OUString& sPropName, sal_Int16 nAddAttrib, sal_Int16 nRemoveAttrib)
+{
+ sal_Int32 nLen = seqProps.getLength();
+
+ // binaere Suche
+ Property* pProperties = seqProps.getArray();
+ Property* pResult = ::std::lower_bound(pProperties, pProperties + nLen,sPropName, PropertyStringLessFunctor());
+
+ // gefunden ?
+ if ( pResult && (pResult != pProperties + nLen) && (pResult->Name == sPropName) )
+ {
+ pResult->Attributes |= nAddAttrib;
+ pResult->Attributes &= ~nRemoveAttrib;
+ }
+}
+
+//------------------------------------------------------------------
+sal_Bool tryPropertyValue(Any& _rConvertedValue, Any& _rOldValue, const Any& _rValueToSet, const Any& _rCurrentValue, const Type& _rExpectedType)
+{
+ sal_Bool bModified(sal_False);
+ if (_rCurrentValue.getValue() != _rValueToSet.getValue())
+ {
+ if ( _rValueToSet.hasValue() && ( !_rExpectedType.equals( _rValueToSet.getValueType() ) ) )
+ {
+ _rConvertedValue = Any( NULL, _rExpectedType.getTypeLibType() );
+
+ if ( !uno_type_assignData(
+ const_cast< void* >( _rConvertedValue.getValue() ), _rConvertedValue.getValueType().getTypeLibType(),
+ const_cast< void* >( _rValueToSet.getValue() ), _rValueToSet.getValueType().getTypeLibType(),
+ reinterpret_cast< uno_QueryInterfaceFunc >(
+ cpp_queryInterface),
+ reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
+ reinterpret_cast< uno_ReleaseFunc >(cpp_release)
+ )
+ )
+ throw starlang::IllegalArgumentException();
+ }
+ else
+ _rConvertedValue = _rValueToSet;
+
+ if ( _rCurrentValue != _rConvertedValue )
+ {
+ _rOldValue = _rCurrentValue;
+ bModified = sal_True;
+ }
+ }
+ return bModified;
+}
+
+//.........................................................................
+}
+//.........................................................................
+
diff --git a/comphelper/source/property/propertybag.cxx b/comphelper/source/property/propertybag.cxx
new file mode 100644
index 000000000000..88f925e20db7
--- /dev/null
+++ b/comphelper/source/property/propertybag.cxx
@@ -0,0 +1,221 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include "comphelper/propertybag.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/beans/IllegalTypeException.hpp>
+#include <com/sun/star/beans/PropertyExistException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/NotRemoveableException.hpp>
+/** === end UNO includes === **/
+
+#include <map>
+
+//........................................................................
+namespace comphelper
+{
+//........................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::uno::TypeClass_VOID;
+ using ::com::sun::star::beans::IllegalTypeException;
+ using ::com::sun::star::beans::PropertyExistException;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::beans::Property;
+ using ::com::sun::star::beans::NotRemoveableException;
+ using ::com::sun::star::beans::UnknownPropertyException;
+ /** === end UNO using === **/
+ namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
+
+ //====================================================================
+ //= PropertyBag_Impl
+ //====================================================================
+ typedef ::std::map< sal_Int32, Any > MapInt2Any;
+ struct PropertyBag_Impl
+ {
+ PropertyBag_Impl() : m_bAllowEmptyPropertyName(false) { }
+ MapInt2Any aDefaults;
+ bool m_bAllowEmptyPropertyName;
+ };
+
+ //====================================================================
+ //= PropertyBag
+ //====================================================================
+ //--------------------------------------------------------------------
+ PropertyBag::PropertyBag()
+ :m_pImpl( new PropertyBag_Impl )
+ {
+ }
+
+ PropertyBag::~PropertyBag()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void PropertyBag::setAllowEmptyPropertyName( bool i_isAllowed )
+ {
+ m_pImpl->m_bAllowEmptyPropertyName = i_isAllowed;
+ }
+
+ //--------------------------------------------------------------------
+ namespace
+ {
+ void lcl_checkForEmptyName( const bool _allowEmpty, const ::rtl::OUString& _name )
+ {
+ if ( !_allowEmpty && !_name.getLength() )
+ throw IllegalArgumentException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The property name must not be empty." ) ),
+ // TODO: resource
+ NULL,
+ 1
+ );
+ }
+
+ void lcl_checkNameAndHandle( const ::rtl::OUString& _name, const sal_Int32 _handle, const PropertyBag& _container )
+ {
+ if ( _container.hasPropertyByName( _name ) || _container.hasPropertyByHandle( _handle ) )
+ throw PropertyExistException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Property name or handle already used." ) ),
+ // TODO: resource
+ NULL );
+
+ }
+ }
+
+ //--------------------------------------------------------------------
+ void PropertyBag::addVoidProperty( const ::rtl::OUString& _rName, const Type& _rType, sal_Int32 _nHandle, sal_Int32 _nAttributes )
+ {
+ if ( _rType.getTypeClass() == TypeClass_VOID )
+ throw IllegalArgumentException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Illegal property type: VOID" ) ),
+ // TODO: resource
+ NULL,
+ 1
+ );
+
+ // check name/handle sanity
+ lcl_checkForEmptyName( m_pImpl->m_bAllowEmptyPropertyName, _rName );
+ lcl_checkNameAndHandle( _rName, _nHandle, *this );
+
+ // register the property
+ OSL_ENSURE( _nAttributes & PropertyAttribute::MAYBEVOID, "PropertyBag::addVoidProperty: this is for default-void properties only!" );
+ registerPropertyNoMember( _rName, _nHandle, _nAttributes | PropertyAttribute::MAYBEVOID, _rType, NULL );
+
+ // remember the default
+ m_pImpl->aDefaults.insert( MapInt2Any::value_type( _nHandle, Any() ) );
+ }
+
+ //--------------------------------------------------------------------
+ void PropertyBag::addProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, const Any& _rInitialValue )
+ {
+ // check type sanity
+ Type aPropertyType = _rInitialValue.getValueType();
+ if ( aPropertyType.getTypeClass() == TypeClass_VOID )
+ throw IllegalTypeException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The initial value must be non-NULL to determine the property type." ) ),
+ // TODO: resource
+ NULL );
+
+ // check name/handle sanity
+ lcl_checkForEmptyName( m_pImpl->m_bAllowEmptyPropertyName, _rName );
+ lcl_checkNameAndHandle( _rName, _nHandle, *this );
+
+ // register the property
+ registerPropertyNoMember( _rName, _nHandle, _nAttributes, aPropertyType,
+ _rInitialValue.hasValue() ? _rInitialValue.getValue() : NULL );
+
+ // remember the default
+ m_pImpl->aDefaults.insert( MapInt2Any::value_type( _nHandle, _rInitialValue ) );
+ }
+
+ //--------------------------------------------------------------------
+ void PropertyBag::removeProperty( const ::rtl::OUString& _rName )
+ {
+ const Property& rProp = getProperty( _rName );
+ // will throw an UnknownPropertyException if necessary
+ if ( ( rProp.Attributes & PropertyAttribute::REMOVEABLE ) == 0 )
+ throw NotRemoveableException( ::rtl::OUString(), NULL );
+ const sal_Int32 nHandle = rProp.Handle;
+
+ revokeProperty( nHandle );
+
+ m_pImpl->aDefaults.erase( nHandle );
+ }
+
+ //--------------------------------------------------------------------
+ void PropertyBag::getFastPropertyValue( sal_Int32 _nHandle, Any& _out_rValue ) const
+ {
+ if ( !hasPropertyByHandle( _nHandle ) )
+ throw UnknownPropertyException();
+
+ OPropertyContainerHelper::getFastPropertyValue( _out_rValue, _nHandle );
+ }
+
+ //--------------------------------------------------------------------
+ bool PropertyBag::convertFastPropertyValue( sal_Int32 _nHandle, const Any& _rNewValue, Any& _out_rConvertedValue, Any& _out_rCurrentValue ) const
+ {
+ if ( !hasPropertyByHandle( _nHandle ) )
+ throw UnknownPropertyException();
+
+ return const_cast< PropertyBag* >( this )->OPropertyContainerHelper::convertFastPropertyValue(
+ _out_rConvertedValue, _out_rCurrentValue, _nHandle, _rNewValue );
+ }
+
+ //--------------------------------------------------------------------
+ void PropertyBag::setFastPropertyValue( sal_Int32 _nHandle, const Any& _rValue )
+ {
+ if ( !hasPropertyByHandle( _nHandle ) )
+ throw UnknownPropertyException();
+
+ OPropertyContainerHelper::setFastPropertyValue( _nHandle, _rValue );
+ }
+
+ //--------------------------------------------------------------------
+ void PropertyBag::getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _out_rValue ) const
+ {
+ if ( !hasPropertyByHandle( _nHandle ) )
+ throw UnknownPropertyException();
+
+ MapInt2Any::const_iterator pos = m_pImpl->aDefaults.find( _nHandle );
+ OSL_ENSURE( pos != m_pImpl->aDefaults.end(), "PropertyBag::getPropertyDefaultByHandle: inconsistency!" );
+ if ( pos != m_pImpl->aDefaults.end() )
+ _out_rValue = pos->second;
+ else
+ _out_rValue.clear();
+ }
+
+
+//........................................................................
+} // namespace comphelper
+//........................................................................
+
diff --git a/comphelper/source/property/propertycontainer.cxx b/comphelper/source/property/propertycontainer.cxx
new file mode 100644
index 000000000000..c385107733fe
--- /dev/null
+++ b/comphelper/source/property/propertycontainer.cxx
@@ -0,0 +1,105 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include <comphelper/propertycontainer.hxx>
+#include <comphelper/property.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <osl/diagnose.h>
+#include <uno/data.h>
+#include <com/sun/star/uno/genfunc.h>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <rtl/ustrbuf.hxx>
+
+#include <algorithm>
+
+//.........................................................................
+namespace comphelper
+{
+//.........................................................................
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+
+//==========================================================================
+//= OPropertyContainer
+//==========================================================================
+//--------------------------------------------------------------------------
+OPropertyContainer::OPropertyContainer(::cppu::OBroadcastHelper& _rBHelper)
+ :OPropertyContainer_Base(_rBHelper)
+{
+}
+
+// -------------------------------------------------------------------------
+OPropertyContainer::~OPropertyContainer()
+{
+}
+
+//--------------------------------------------------------------------------
+Sequence< Type > SAL_CALL OPropertyContainer::getTypes() throw (RuntimeException)
+{
+ // just the types from our one and only base class
+ ::cppu::OTypeCollection aTypes(
+ ::getCppuType( static_cast< Reference< XPropertySet >* >(NULL)),
+ ::getCppuType( static_cast< Reference< XFastPropertySet >* >(NULL)),
+ ::getCppuType( static_cast< Reference< XMultiPropertySet >* >(NULL))
+ );
+ return aTypes.getTypes();
+}
+
+//--------------------------------------------------------------------------
+void SAL_CALL OPropertyContainer::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue ) throw ( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ OPropertyContainer_Base::setFastPropertyValue( nHandle, rValue );
+}
+
+//--------------------------------------------------------------------------
+sal_Bool OPropertyContainer::convertFastPropertyValue(
+ Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw (IllegalArgumentException)
+{
+ return OPropertyContainerHelper::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue );
+}
+
+//--------------------------------------------------------------------------
+void OPropertyContainer::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (Exception)
+{
+ OPropertyContainerHelper::setFastPropertyValue( _nHandle, _rValue );
+}
+
+//--------------------------------------------------------------------------
+void OPropertyContainer::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
+{
+ OPropertyContainerHelper::getFastPropertyValue( _rValue, _nHandle );
+}
+
+//.........................................................................
+} // namespace comphelper
+//.........................................................................
+
+
diff --git a/comphelper/source/property/propertycontainerhelper.cxx b/comphelper/source/property/propertycontainerhelper.cxx
new file mode 100644
index 000000000000..0b420a3eebd8
--- /dev/null
+++ b/comphelper/source/property/propertycontainerhelper.cxx
@@ -0,0 +1,552 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include <comphelper/propertycontainerhelper.hxx>
+#include <comphelper/property.hxx>
+#include <osl/diagnose.h>
+#include <uno/data.h>
+#include <com/sun/star/uno/genfunc.h>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <rtl/ustrbuf.hxx>
+
+#include <algorithm>
+
+//.........................................................................
+namespace comphelper
+{
+//.........................................................................
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+
+//--------------------------------------------------------------------------
+namespace
+{
+ // comparing two property descriptions
+ struct PropertyDescriptionCompareByHandle : public ::std::binary_function< PropertyDescription, PropertyDescription, bool >
+ {
+ bool operator() (const PropertyDescription& x, const PropertyDescription& y) const
+ {
+ return x.aProperty.Handle < y.aProperty.Handle;
+ }
+ };
+ // comparing two property descriptions
+ struct PropertyDescriptionHandleCompare : public ::std::binary_function< PropertyDescription, sal_Int32, bool >
+ {
+ bool operator() (const PropertyDescription& x, const sal_Int32& y) const
+ {
+ return x.aProperty.Handle < y;
+ }
+ bool operator() (const sal_Int32& x, const PropertyDescription& y) const
+ {
+ return x < y.aProperty.Handle;
+ }
+ };
+ // comparing two property descriptions (by name)
+ struct PropertyDescriptionNameMatch : public ::std::unary_function< PropertyDescription, bool >
+ {
+ ::rtl::OUString m_rCompare;
+ PropertyDescriptionNameMatch( const ::rtl::OUString& _rCompare ) : m_rCompare( _rCompare ) { }
+
+ bool operator() (const PropertyDescription& x ) const
+ {
+ return x.aProperty.Name.equals(m_rCompare);
+ }
+ };
+}
+
+//==========================================================================
+//= OPropertyContainerHelper
+//==========================================================================
+//--------------------------------------------------------------------------
+OPropertyContainerHelper::OPropertyContainerHelper()
+ :m_bUnused(sal_False)
+{
+}
+
+// -------------------------------------------------------------------------
+OPropertyContainerHelper::~OPropertyContainerHelper()
+{
+}
+
+//--------------------------------------------------------------------------
+void OPropertyContainerHelper::registerProperty(const ::rtl::OUString& _rName, sal_Int32 _nHandle,
+ sal_Int32 _nAttributes, void* _pPointerToMember, const Type& _rMemberType)
+{
+ OSL_ENSURE((_nAttributes & PropertyAttribute::MAYBEVOID) == 0,
+ "OPropertyContainerHelper::registerProperty: don't use this for properties which may be void ! There is a method called \"registerMayBeVoidProperty\" for this !");
+ OSL_ENSURE(!_rMemberType.equals(::getCppuType(static_cast< Any* >(NULL))),
+ "OPropertyContainerHelper::registerProperty: don't give my the type of an uno::Any ! Really can't handle this !");
+ OSL_ENSURE(_pPointerToMember,
+ "OPropertyContainerHelper::registerProperty: you gave me nonsense : the pointer must be non-NULL");
+
+ PropertyDescription aNewProp;
+ aNewProp.aProperty = Property( _rName, _nHandle, _rMemberType, (sal_Int16)_nAttributes );
+ aNewProp.eLocated = PropertyDescription::ltDerivedClassRealType;
+ aNewProp.aLocation.pDerivedClassMember = _pPointerToMember;
+
+ implPushBackProperty(aNewProp);
+}
+
+//--------------------------------------------------------------------------
+void OPropertyContainerHelper::revokeProperty( sal_Int32 _nHandle )
+{
+ PropertiesIterator aPos = searchHandle( _nHandle );
+ if ( aPos == m_aProperties.end() )
+ throw UnknownPropertyException();
+ m_aProperties.erase( aPos );
+}
+
+//--------------------------------------------------------------------------
+void OPropertyContainerHelper::registerMayBeVoidProperty(const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes,
+ Any* _pPointerToMember, const Type& _rExpectedType)
+{
+ OSL_ENSURE((_nAttributes & PropertyAttribute::MAYBEVOID) != 0,
+ "OPropertyContainerHelper::registerMayBeVoidProperty: why calling this when the attributes say nothing about may-be-void ?");
+ OSL_ENSURE(!_rExpectedType.equals(::getCppuType(static_cast< Any* >(NULL))),
+ "OPropertyContainerHelper::registerMayBeVoidProperty: don't give my the type of an uno::Any ! Really can't handle this !");
+ OSL_ENSURE(_pPointerToMember,
+ "OPropertyContainerHelper::registerMayBeVoidProperty: you gave me nonsense : the pointer must be non-NULL");
+
+ _nAttributes |= PropertyAttribute::MAYBEVOID;
+
+ PropertyDescription aNewProp;
+ aNewProp.aProperty = Property( _rName, _nHandle, _rExpectedType, (sal_Int16)_nAttributes );
+ aNewProp.eLocated = PropertyDescription::ltDerivedClassAnyType;
+ aNewProp.aLocation.pDerivedClassMember = _pPointerToMember;
+
+ implPushBackProperty(aNewProp);
+}
+
+
+//--------------------------------------------------------------------------
+void OPropertyContainerHelper::registerPropertyNoMember(const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes,
+ const Type& _rType, const void* _pInitialValue)
+{
+ OSL_ENSURE(!_rType.equals(::getCppuType(static_cast< Any* >(NULL))),
+ "OPropertyContainerHelper::registerPropertyNoMember : don't give my the type of an uno::Any ! Really can't handle this !");
+ OSL_ENSURE(_pInitialValue || ((_nAttributes & PropertyAttribute::MAYBEVOID) != 0),
+ "OPropertyContainerHelper::registerPropertyNoMember : you should not ommit the initial value if the property can't be void ! This will definitivly crash later !");
+
+ PropertyDescription aNewProp;
+ aNewProp.aProperty = Property( _rName, _nHandle, _rType, (sal_Int16)_nAttributes );
+ aNewProp.eLocated = PropertyDescription::ltHoldMyself;
+ aNewProp.aLocation.nOwnClassVectorIndex = m_aHoldProperties.size();
+ if (_pInitialValue)
+ m_aHoldProperties.push_back(Any(_pInitialValue, _rType));
+ else
+ m_aHoldProperties.push_back(Any());
+
+ implPushBackProperty(aNewProp);
+}
+
+//--------------------------------------------------------------------------
+sal_Bool OPropertyContainerHelper::isRegisteredProperty( sal_Int32 _nHandle ) const
+{
+ return const_cast< OPropertyContainerHelper* >( this )->searchHandle( _nHandle ) != m_aProperties.end();
+}
+
+//--------------------------------------------------------------------------
+sal_Bool OPropertyContainerHelper::isRegisteredProperty( const ::rtl::OUString& _rName ) const
+{
+ // TODO: the current structure is from a time where properties were
+ // static, not dynamic. Since we allow that properties are also dynamic,
+ // i.e. registered and revoked even though the XPropertySet has already been
+ // accessed, a vector is not really the best data structure anymore ...
+
+ ConstPropertiesIterator pos = ::std::find_if(
+ m_aProperties.begin(),
+ m_aProperties.end(),
+ PropertyDescriptionNameMatch( _rName )
+ );
+ return pos != m_aProperties.end();
+}
+
+//--------------------------------------------------------------------------
+namespace
+{
+ struct ComparePropertyWithHandle
+ {
+ bool operator()( const PropertyDescription& _rLHS, sal_Int32 _nRHS ) const
+ {
+ return _rLHS.aProperty.Handle < _nRHS;
+ }
+ bool operator()( sal_Int32 _nLHS, const PropertyDescription& _rRHS ) const
+ {
+ return _nLHS < _rRHS.aProperty.Handle;
+ }
+ };
+}
+
+//--------------------------------------------------------------------------
+void OPropertyContainerHelper::implPushBackProperty(const PropertyDescription& _rProp)
+{
+#ifdef DBG_UTIL
+ for ( PropertiesIterator checkConflicts = m_aProperties.begin();
+ checkConflicts != m_aProperties.end();
+ ++checkConflicts
+ )
+ {
+ OSL_ENSURE(checkConflicts->aProperty.Name != _rProp.aProperty.Name, "OPropertyContainerHelper::implPushBackProperty: name already exists!");
+ OSL_ENSURE(checkConflicts->aProperty.Handle != _rProp.aProperty.Handle, "OPropertyContainerHelper::implPushBackProperty: handle already exists!");
+ }
+#endif
+
+ PropertiesIterator pos = ::std::lower_bound(
+ m_aProperties.begin(), m_aProperties.end(),
+ _rProp.aProperty.Handle, ComparePropertyWithHandle() );
+
+ m_aProperties.insert( pos, _rProp );
+}
+
+//--------------------------------------------------------------------------
+namespace
+{
+ void lcl_throwIllegalPropertyValueTypeException( const PropertyDescription& _rProperty, const Any& _rValue )
+ {
+ ::rtl::OUStringBuffer aErrorMessage;
+ aErrorMessage.appendAscii( "The given value cannot be converted to the required property type." );
+ aErrorMessage.appendAscii( "\n(property name \"" );
+ aErrorMessage.append( _rProperty.aProperty.Name );
+ aErrorMessage.appendAscii( "\", found value type \"" );
+ aErrorMessage.append( _rValue.getValueType().getTypeName() );
+ aErrorMessage.appendAscii( "\", required property type \"" );
+ aErrorMessage.append( _rProperty.aProperty.Type.getTypeName() );
+ aErrorMessage.appendAscii( "\")" );
+ throw IllegalArgumentException( aErrorMessage.makeStringAndClear(), NULL, 4 );
+ }
+}
+
+//--------------------------------------------------------------------------
+sal_Bool OPropertyContainerHelper::convertFastPropertyValue(
+ Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) SAL_THROW( (IllegalArgumentException) )
+{
+ sal_Bool bModified = sal_False;
+
+ // get the property somebody is asking for
+ PropertiesIterator aPos = searchHandle(_nHandle);
+ if (aPos == m_aProperties.end())
+ {
+ OSL_ENSURE( false, "OPropertyContainerHelper::convertFastPropertyValue: unknown handle!" );
+ // should not happen if the derived class has built a correct property set info helper to be used by
+ // our base class OPropertySetHelper
+ return bModified;
+ }
+
+ switch (aPos->eLocated)
+ {
+ // similar handling for the two cases where the value is stored in an any
+ case PropertyDescription::ltHoldMyself:
+ case PropertyDescription::ltDerivedClassAnyType:
+ {
+ sal_Bool bMayBeVoid = ((aPos->aProperty.Attributes & PropertyAttribute::MAYBEVOID) != 0);
+
+
+ // non modifiable version of the value-to-be-set
+ Any aNewRequestedValue( _rValue );
+
+ // normalization
+ // (#102329# - 2002-08-14 - fs@openoffice.org)
+ // (#i29490# - 2004-06-16 - fs@openoffice.org)
+ if ( !aNewRequestedValue.getValueType().equals( aPos->aProperty.Type ) )
+ { // the actually given value is not of the same type as the one required
+ Any aProperlyTyped( NULL, aPos->aProperty.Type.getTypeLibType() );
+
+ if ( uno_type_assignData(
+ const_cast< void* >( aProperlyTyped.getValue() ), aProperlyTyped.getValueType().getTypeLibType(),
+ const_cast< void* >( aNewRequestedValue.getValue() ), aNewRequestedValue.getValueType().getTypeLibType(),
+ reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
+ reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
+ reinterpret_cast< uno_ReleaseFunc >( cpp_release )
+ )
+ )
+ {
+ // we were able to query the given XInterface-derivee for the interface
+ // which is required for this property
+ aNewRequestedValue = aProperlyTyped;
+ }
+ }
+
+ // argument check
+ if ( ! ( (bMayBeVoid && !aNewRequestedValue.hasValue()) // void is allowed if the attribute says so
+ || (aNewRequestedValue.getValueType().equals(aPos->aProperty.Type)) // else the types have to be equal
+ )
+ )
+ {
+ lcl_throwIllegalPropertyValueTypeException( *aPos, _rValue );
+ }
+
+ Any* pPropContainer = NULL;
+ // the pointer to the any which holds the property value, no matter if located in the derived clas
+ // or in out vector
+
+ if (PropertyDescription::ltHoldMyself == aPos->eLocated)
+ {
+ OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < (sal_Int32)m_aHoldProperties.size(),
+ "OPropertyContainerHelper::convertFastPropertyValue: invalid position !");
+ PropertyContainerIterator aIter = m_aHoldProperties.begin() + aPos->aLocation.nOwnClassVectorIndex;
+ pPropContainer = &(*aIter);
+ }
+ else
+ pPropContainer = reinterpret_cast<Any*>(aPos->aLocation.pDerivedClassMember);
+
+ // check if the new value differs from the current one
+ if (!pPropContainer->hasValue() || !aNewRequestedValue.hasValue())
+ bModified = pPropContainer->hasValue() != aNewRequestedValue.hasValue();
+ else
+ bModified = !uno_type_equalData(
+ const_cast< void* >( pPropContainer->getValue() ), aPos->aProperty.Type.getTypeLibType(),
+ const_cast< void* >( aNewRequestedValue.getValue() ), aPos->aProperty.Type.getTypeLibType(),
+ reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
+ reinterpret_cast< uno_ReleaseFunc >( cpp_release )
+ );
+
+ if (bModified)
+ {
+ _rOldValue = *pPropContainer;
+ _rConvertedValue = aNewRequestedValue;
+ }
+ }
+ break;
+ case PropertyDescription::ltDerivedClassRealType:
+ // let the UNO runtime library do any possible conversion
+ // this may include a change of the type - for instance, if a LONG is required,
+ // but a short is given, then this is valid, as it can be converted without any potential
+ // data loss
+
+ Any aProperlyTyped;
+ const Any* pNewValue = &_rValue;
+
+ if (!_rValue.getValueType().equals(aPos->aProperty.Type))
+ {
+ sal_Bool bConverted = sal_False;
+
+ // a temporary any of the correct (required) type
+ aProperlyTyped = Any( NULL, aPos->aProperty.Type.getTypeLibType() );
+ // (need this as we do not want to overwrite the derived class member here)
+
+ if ( uno_type_assignData(
+ const_cast<void*>(aProperlyTyped.getValue()), aProperlyTyped.getValueType().getTypeLibType(),
+ const_cast<void*>(_rValue.getValue()), _rValue.getValueType().getTypeLibType(),
+ reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
+ reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
+ reinterpret_cast< uno_ReleaseFunc >( cpp_release )
+ )
+ )
+ {
+ // could query for the requested interface
+ bConverted = sal_True;
+ pNewValue = &aProperlyTyped;
+ }
+
+ if ( !bConverted )
+ lcl_throwIllegalPropertyValueTypeException( *aPos, _rValue );
+ }
+
+ // from here on, we should have the proper type
+ OSL_ENSURE( pNewValue->getValueType() == aPos->aProperty.Type,
+ "OPropertyContainerHelper::convertFastPropertyValue: conversion failed!" );
+ bModified = !uno_type_equalData(
+ aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type.getTypeLibType(),
+ const_cast<void*>(pNewValue->getValue()), aPos->aProperty.Type.getTypeLibType(),
+ reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
+ reinterpret_cast< uno_ReleaseFunc >( cpp_release )
+ );
+
+ if (bModified)
+ {
+ _rOldValue.setValue(aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type);
+ _rConvertedValue = *pNewValue;
+ }
+ break;
+ }
+
+ return bModified;
+}
+
+//--------------------------------------------------------------------------
+void OPropertyContainerHelper::setFastPropertyValue(sal_Int32 _nHandle, const Any& _rValue) SAL_THROW( (Exception) )
+{
+ // get the property somebody is asking for
+ PropertiesIterator aPos = searchHandle(_nHandle);
+ if (aPos == m_aProperties.end())
+ {
+ OSL_ENSURE( false, "OPropertyContainerHelper::setFastPropertyValue: unknown handle!" );
+ // should not happen if the derived class has built a correct property set info helper to be used by
+ // our base class OPropertySetHelper
+ return;
+ }
+
+ switch (aPos->eLocated)
+ {
+ case PropertyDescription::ltHoldMyself:
+ m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex] = _rValue;
+ break;
+
+ case PropertyDescription::ltDerivedClassAnyType:
+ *reinterpret_cast< Any* >(aPos->aLocation.pDerivedClassMember) = _rValue;
+ break;
+
+ case PropertyDescription::ltDerivedClassRealType:
+#if OSL_DEBUG_LEVEL > 0
+ sal_Bool bSuccess =
+#endif
+ // copy the data from the to-be-set value
+ uno_type_assignData(
+ aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type.getTypeLibType(),
+ const_cast< void* >( _rValue.getValue() ), _rValue.getValueType().getTypeLibType(),
+ reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
+ reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
+ reinterpret_cast< uno_ReleaseFunc >( cpp_release ) );
+
+ OSL_ENSURE( bSuccess,
+ "OPropertyContainerHelper::setFastPropertyValue: ooops .... the value could not be assigned!");
+
+ break;
+ }
+}
+
+//--------------------------------------------------------------------------
+void OPropertyContainerHelper::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
+{
+ // get the property somebody is asking for
+ PropertiesIterator aPos = const_cast<OPropertyContainerHelper*>(this)->searchHandle(_nHandle);
+ if (aPos == m_aProperties.end())
+ {
+ OSL_ENSURE( false, "OPropertyContainerHelper::getFastPropertyValue: unknown handle!" );
+ // should not happen if the derived class has built a correct property set info helper to be used by
+ // our base class OPropertySetHelper
+ return;
+ }
+
+ switch (aPos->eLocated)
+ {
+ case PropertyDescription::ltHoldMyself:
+ OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < (sal_Int32)m_aHoldProperties.size(),
+ "OPropertyContainerHelper::convertFastPropertyValue: invalid position !");
+ _rValue = m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex];
+ break;
+ case PropertyDescription::ltDerivedClassAnyType:
+ _rValue = *reinterpret_cast<Any*>(aPos->aLocation.pDerivedClassMember);
+ break;
+ case PropertyDescription::ltDerivedClassRealType:
+ _rValue.setValue(aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type);
+ break;
+ }
+}
+
+//--------------------------------------------------------------------------
+OPropertyContainerHelper::PropertiesIterator OPropertyContainerHelper::searchHandle(sal_Int32 _nHandle)
+{
+ // search a lower bound
+ PropertiesIterator aLowerBound = ::std::lower_bound(
+ m_aProperties.begin(),
+ m_aProperties.end(),
+ _nHandle,
+ PropertyDescriptionHandleCompare());
+
+ // check for identity
+ if ((aLowerBound != m_aProperties.end()) && aLowerBound->aProperty.Handle != _nHandle)
+ aLowerBound = m_aProperties.end();
+
+ return aLowerBound;
+}
+
+//--------------------------------------------------------------------------
+const Property& OPropertyContainerHelper::getProperty( const ::rtl::OUString& _rName ) const
+{
+ ConstPropertiesIterator pos = ::std::find_if(
+ m_aProperties.begin(),
+ m_aProperties.end(),
+ PropertyDescriptionNameMatch( _rName )
+ );
+ if ( pos == m_aProperties.end() )
+ throw UnknownPropertyException( _rName, NULL );
+
+ return pos->aProperty;
+}
+
+//--------------------------------------------------------------------------
+void OPropertyContainerHelper::modifyAttributes(sal_Int32 _nHandle, sal_Int32 _nAddAttrib, sal_Int32 _nRemoveAttrib)
+{
+ // get the property somebody is asking for
+ PropertiesIterator aPos = searchHandle(_nHandle);
+ if (aPos == m_aProperties.end())
+ {
+ OSL_ENSURE( false, "OPropertyContainerHelper::modifyAttributes: unknown handle!" );
+ // should not happen if the derived class has built a correct property set info helper to be used by
+ // our base class OPropertySetHelper
+ return;
+ }
+ aPos->aProperty.Handle |= _nAddAttrib;
+ aPos->aProperty.Handle &= ~_nRemoveAttrib;
+}
+
+//--------------------------------------------------------------------------
+void OPropertyContainerHelper::describeProperties(Sequence< Property >& _rProps) const
+{
+ Sequence< Property > aOwnProps(m_aProperties.size());
+ Property* pOwnProps = aOwnProps.getArray();
+
+ for ( ConstPropertiesIterator aLoop = m_aProperties.begin();
+ aLoop != m_aProperties.end();
+ ++aLoop, ++pOwnProps
+ )
+ {
+ pOwnProps->Name = aLoop->aProperty.Name;
+ pOwnProps->Handle = aLoop->aProperty.Handle;
+ pOwnProps->Attributes = (sal_Int16)aLoop->aProperty.Attributes;
+ pOwnProps->Type = aLoop->aProperty.Type;
+ }
+
+ // as our property vector is sorted by handles, not by name, we have to sort aOwnProps
+ ::std::sort(aOwnProps.getArray(), aOwnProps.getArray() + aOwnProps.getLength(), PropertyCompareByName());
+
+ // unfortunally the STL merge function does not allow the output range to overlap one of the input ranges,
+ // so we need an extra sequence
+ Sequence< Property > aOutput;
+ aOutput.realloc(_rProps.getLength() + aOwnProps.getLength());
+ // do the merge
+ ::std::merge( _rProps.getConstArray(), _rProps.getConstArray() + _rProps.getLength(), // input 1
+ aOwnProps.getConstArray(), aOwnProps.getConstArray() + aOwnProps.getLength(), // input 2
+ aOutput.getArray(), // output
+ PropertyCompareByName() // compare operator
+ );
+
+ // copy the output
+ _rProps = aOutput;
+}
+
+//.........................................................................
+} // namespace comphelper
+//.........................................................................
+
+
diff --git a/comphelper/source/property/propertysethelper.cxx b/comphelper/source/property/propertysethelper.cxx
new file mode 100644
index 000000000000..9d2abf784c1b
--- /dev/null
+++ b/comphelper/source/property/propertysethelper.cxx
@@ -0,0 +1,328 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+
+#include "comphelper/propertysetinfo.hxx"
+#include "comphelper/propertysethelper.hxx"
+
+///////////////////////////////////////////////////////////////////////
+
+using namespace ::rtl;
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+
+namespace comphelper
+{
+class PropertySetHelperImpl
+{
+public:
+ PropertyMapEntry* find( const OUString& aName ) const throw();
+
+ PropertySetInfo* mpInfo;
+};
+}
+
+PropertyMapEntry* PropertySetHelperImpl::find( const OUString& aName ) const throw()
+{
+ PropertyMap::const_iterator aIter = mpInfo->getPropertyMap()->find( aName );
+
+ if( mpInfo->getPropertyMap()->end() != aIter )
+ {
+ return (*aIter).second;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////
+
+PropertySetHelper::PropertySetHelper( )
+{
+ mp = new PropertySetHelperImpl;
+ mp->mpInfo = new PropertySetInfo;
+ mp->mpInfo->acquire();
+}
+
+PropertySetHelper::PropertySetHelper( comphelper::PropertySetInfo* pInfo ) throw()
+{
+ mp = new PropertySetHelperImpl;
+ mp->mpInfo = pInfo;
+ pInfo->acquire();
+}
+
+PropertySetHelper::PropertySetHelper( comphelper::PropertySetInfo* pInfo, __sal_NoAcquire ) throw()
+{
+ mp = new PropertySetHelperImpl;
+ mp->mpInfo = pInfo;
+}
+
+PropertySetHelper::~PropertySetHelper() throw()
+{
+ mp->mpInfo->release();
+ delete mp;
+}
+
+void PropertySetHelper::setInfo( comphelper::PropertySetInfo* pInfo ) throw()
+{
+ OSL_ENSURE( pInfo != NULL, "need pInfo" );
+ OSL_ENSURE( mp->mpInfo != NULL, "where's the old pInfo?" );
+
+ mp->mpInfo->release();
+ mp->mpInfo = pInfo;
+ mp->mpInfo->acquire();
+}
+
+// XPropertySet
+Reference< XPropertySetInfo > SAL_CALL PropertySetHelper::getPropertySetInfo( ) throw(RuntimeException)
+{
+ return mp->mpInfo;
+}
+
+void SAL_CALL PropertySetHelper::setPropertyValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ PropertyMapEntry* aEntries[2];
+ aEntries[0] = mp->find( aPropertyName );
+
+ if( NULL == aEntries[0] )
+ throw UnknownPropertyException( aPropertyName, static_cast< XPropertySet* >( this ) );
+
+ aEntries[1] = NULL;
+
+ _setPropertyValues( (const PropertyMapEntry**)aEntries, &aValue );
+}
+
+Any SAL_CALL PropertySetHelper::getPropertyValue( const ::rtl::OUString& PropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ PropertyMapEntry* aEntries[2];
+ aEntries[0] = mp->find( PropertyName );
+
+ if( NULL == aEntries[0] )
+ throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) );
+
+ aEntries[1] = NULL;
+
+ Any aAny;
+ _getPropertyValues( (const PropertyMapEntry**)aEntries, &aAny );
+
+ return aAny;
+}
+
+void SAL_CALL PropertySetHelper::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL PropertySetHelper::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL PropertySetHelper::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL PropertySetHelper::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // todo
+}
+
+// XMultiPropertySet
+void SAL_CALL PropertySetHelper::setPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames, const Sequence< Any >& aValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ const sal_Int32 nCount = aPropertyNames.getLength();
+
+ if( nCount != aValues.getLength() )
+ throw IllegalArgumentException();
+
+ if( nCount )
+ {
+ PropertyMapEntry** pEntries = new PropertyMapEntry*[nCount+1];
+ pEntries[nCount] = NULL;
+ const OUString* pNames = aPropertyNames.getConstArray();
+
+ sal_Bool bUnknown = sal_False;
+ sal_Int32 n;
+ for( n = 0; !bUnknown && ( n < nCount ); n++, pNames++ )
+ {
+ pEntries[n] = mp->find( *pNames );
+ bUnknown = NULL == pEntries[n];
+ }
+
+ if( !bUnknown )
+ _setPropertyValues( (const PropertyMapEntry**)pEntries, aValues.getConstArray() );
+
+ delete[] pEntries;
+
+ if( bUnknown )
+ throw UnknownPropertyException( *pNames, static_cast< XPropertySet* >( this ) );
+ }
+}
+
+Sequence< Any > SAL_CALL PropertySetHelper::getPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames ) throw(RuntimeException)
+{
+ const sal_Int32 nCount = aPropertyNames.getLength();
+
+ Sequence< Any > aValues;
+ if( nCount )
+ {
+ PropertyMapEntry** pEntries = new PropertyMapEntry*[nCount+1];
+ pEntries[nCount] = NULL;
+ const OUString* pNames = aPropertyNames.getConstArray();
+
+ sal_Bool bUnknown = sal_False;
+ sal_Int32 n;
+ for( n = 0; !bUnknown && ( n < nCount ); n++, pNames++ )
+ {
+ pEntries[n] = mp->find( *pNames );
+ bUnknown = NULL == pEntries[n];
+ }
+
+ if( !bUnknown )
+ {
+ aValues.realloc(nCount);
+ _getPropertyValues( (const PropertyMapEntry**)pEntries, aValues.getArray() );
+ }
+
+ delete[] pEntries;
+
+ if( bUnknown )
+ throw UnknownPropertyException( *pNames, static_cast< XPropertySet* >( this ) );
+ }
+
+ return aValues;
+}
+
+void SAL_CALL PropertySetHelper::addPropertiesChangeListener( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& ) throw(RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL PropertySetHelper::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& ) throw(RuntimeException)
+{
+ // todo
+}
+
+void SAL_CALL PropertySetHelper::firePropertiesChangeEvent( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& ) throw(RuntimeException)
+{
+ // todo
+}
+
+// XPropertyState
+PropertyState SAL_CALL PropertySetHelper::getPropertyState( const ::rtl::OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException)
+{
+ PropertyMapEntry* aEntries[2];
+
+ aEntries[0] = mp->find( PropertyName );
+ if( aEntries[0] == NULL )
+ throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) );
+
+ aEntries[1] = NULL;
+
+ PropertyState aState;
+ _getPropertyStates( (const PropertyMapEntry**)aEntries, &aState );
+
+ return aState;
+}
+
+Sequence< PropertyState > SAL_CALL PropertySetHelper::getPropertyStates( const Sequence< ::rtl::OUString >& aPropertyName ) throw(UnknownPropertyException, RuntimeException)
+{
+ const sal_Int32 nCount = aPropertyName.getLength();
+
+ Sequence< PropertyState > aStates( nCount );
+
+ if( nCount )
+ {
+ const OUString* pNames = aPropertyName.getConstArray();
+
+ sal_Bool bUnknown = sal_False;
+
+ PropertyMapEntry** pEntries = new PropertyMapEntry*[nCount+1];
+
+ sal_Int32 n;
+ for( n = 0; !bUnknown && (n < nCount); n++, pNames++ )
+ {
+ pEntries[n] = mp->find( *pNames );
+ bUnknown = NULL == pEntries[n];
+ }
+
+ pEntries[nCount] = NULL;
+
+ if( !bUnknown )
+ _getPropertyStates( (const PropertyMapEntry**)pEntries, aStates.getArray() );
+
+ delete[] pEntries;
+
+ if( bUnknown )
+ throw UnknownPropertyException( *pNames, static_cast< XPropertySet* >( this ) );
+ }
+
+ return aStates;
+}
+
+void SAL_CALL PropertySetHelper::setPropertyToDefault( const ::rtl::OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException)
+{
+ PropertyMapEntry *pEntry = mp->find( PropertyName );
+ if( NULL == pEntry )
+ throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) );
+
+ _setPropertyToDefault( pEntry );
+}
+
+Any SAL_CALL PropertySetHelper::getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ PropertyMapEntry* pEntry = mp->find( aPropertyName );
+ if( NULL == pEntry )
+ throw UnknownPropertyException( aPropertyName, static_cast< XPropertySet* >( this ) );
+
+ return _getPropertyDefault( pEntry );
+}
+
+void PropertySetHelper::_getPropertyStates( const comphelper::PropertyMapEntry**, PropertyState* ) throw(UnknownPropertyException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+}
+
+void PropertySetHelper::_setPropertyToDefault( const comphelper::PropertyMapEntry* ) throw(UnknownPropertyException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+}
+
+Any PropertySetHelper::_getPropertyDefault( const comphelper::PropertyMapEntry* ) throw(UnknownPropertyException, WrappedTargetException )
+{
+ OSL_ENSURE( sal_False, "you have to implement this yourself!");
+
+ Any aAny;
+ return aAny;
+}
diff --git a/comphelper/source/property/propertysetinfo.cxx b/comphelper/source/property/propertysetinfo.cxx
new file mode 100644
index 000000000000..efdd495ac1bc
--- /dev/null
+++ b/comphelper/source/property/propertysetinfo.cxx
@@ -0,0 +1,214 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+
+#include "comphelper/propertysetinfo.hxx"
+
+using namespace ::rtl;
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+
+namespace comphelper
+{
+class PropertyMapImpl
+{
+public:
+ PropertyMapImpl() throw();
+ virtual ~PropertyMapImpl() throw();
+
+ void add( PropertyMapEntry* pMap, sal_Int32 nCount = -1 ) throw();
+ void remove( const OUString& aName ) throw();
+
+ Sequence< Property > getProperties() throw();
+
+ const PropertyMap* getPropertyMap() const throw();
+
+ Property getPropertyByName( const OUString& aName ) throw( UnknownPropertyException );
+ sal_Bool hasPropertyByName( const OUString& aName ) throw();
+
+private:
+ PropertyMap maPropertyMap;
+ Sequence< Property > maProperties;
+};
+}
+
+PropertyMapImpl::PropertyMapImpl() throw()
+{
+}
+
+PropertyMapImpl::~PropertyMapImpl() throw()
+{
+}
+
+void PropertyMapImpl::add( PropertyMapEntry* pMap, sal_Int32 nCount ) throw()
+{
+ // nCount < 0 => add all
+ // nCount == 0 => add nothing
+ // nCount > 0 => add at most nCount entries
+
+ while( pMap->mpName && ( ( nCount < 0) || ( nCount-- > 0 ) ) )
+ {
+ OUString aName( pMap->mpName, pMap->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+
+#ifdef DBG_UTIL
+ PropertyMap::iterator aIter = maPropertyMap.find( aName );
+ if( aIter != maPropertyMap.end() )
+ {
+ OSL_ENSURE( sal_False, "Warning: PropertyMapEntry added twice, possible error!");
+ }
+#endif
+ if( NULL == pMap->mpType )
+ {
+ OSL_ENSURE( sal_False, "No type in PropertyMapEntry!");
+ pMap->mpType = &::getCppuType((const sal_Int32*)0);
+ }
+
+ maPropertyMap[aName] = pMap;
+
+ if( maProperties.getLength() )
+ maProperties.realloc( 0 );
+
+ pMap = &pMap[1];
+ }
+}
+
+void PropertyMapImpl::remove( const OUString& aName ) throw()
+{
+ maPropertyMap.erase( aName );
+
+ if( maProperties.getLength() )
+ maProperties.realloc( 0 );
+}
+
+Sequence< Property > PropertyMapImpl::getProperties() throw()
+{
+ // maybe we have to generate the properties after
+ // a change in the property map or at first call
+ // to getProperties
+ if( maProperties.getLength() != (sal_Int32)maPropertyMap.size() )
+ {
+ maProperties = Sequence< Property >( maPropertyMap.size() );
+ Property* pProperties = maProperties.getArray();
+
+ PropertyMap::iterator aIter = maPropertyMap.begin();
+ const PropertyMap::iterator aEnd = maPropertyMap.end();
+ while( aIter != aEnd )
+ {
+ PropertyMapEntry* pEntry = (*aIter).second;
+
+ pProperties->Name = OUString( pEntry->mpName, pEntry->mnNameLen, RTL_TEXTENCODING_ASCII_US );
+ pProperties->Handle = pEntry->mnHandle;
+ pProperties->Type = *pEntry->mpType;
+ pProperties->Attributes = pEntry->mnAttributes;
+
+ pProperties++;
+ aIter++;
+ }
+ }
+
+ return maProperties;
+}
+
+const PropertyMap* PropertyMapImpl::getPropertyMap() const throw()
+{
+ return &maPropertyMap;
+}
+
+Property PropertyMapImpl::getPropertyByName( const OUString& aName ) throw( UnknownPropertyException )
+{
+ PropertyMap::iterator aIter = maPropertyMap.find( aName );
+
+ if( maPropertyMap.end() == aIter )
+ throw UnknownPropertyException( aName, NULL );
+
+ PropertyMapEntry* pEntry = (*aIter).second;
+
+ return Property( aName, pEntry->mnHandle, *pEntry->mpType, pEntry->mnAttributes );
+}
+
+sal_Bool PropertyMapImpl::hasPropertyByName( const OUString& aName ) throw()
+{
+ return maPropertyMap.find( aName ) != maPropertyMap.end();
+}
+
+///////////////////////////////////////////////////////////////////////
+
+PropertySetInfo::PropertySetInfo() throw()
+{
+ mpMap = new PropertyMapImpl();
+}
+
+PropertySetInfo::PropertySetInfo( PropertyMapEntry* pMap ) throw()
+{
+ mpMap = new PropertyMapImpl();
+ mpMap->add( pMap );
+}
+
+PropertySetInfo::~PropertySetInfo() throw()
+{
+ delete mpMap;
+}
+
+void PropertySetInfo::add( PropertyMapEntry* pMap ) throw()
+{
+ mpMap->add( pMap );
+}
+
+void PropertySetInfo::add( PropertyMapEntry* pMap, sal_Int32 nCount ) throw()
+{
+ mpMap->add( pMap, nCount );
+}
+
+void PropertySetInfo::remove( const rtl::OUString& aName ) throw()
+{
+ mpMap->remove( aName );
+}
+
+Sequence< ::com::sun::star::beans::Property > SAL_CALL PropertySetInfo::getProperties() throw(::com::sun::star::uno::RuntimeException)
+{
+ return mpMap->getProperties();
+}
+
+Property SAL_CALL PropertySetInfo::getPropertyByName( const ::rtl::OUString& aName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
+{
+ return mpMap->getPropertyByName( aName );
+}
+
+sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName( const ::rtl::OUString& Name ) throw(::com::sun::star::uno::RuntimeException)
+{
+ return mpMap->hasPropertyByName( Name );
+}
+
+const PropertyMap* PropertySetInfo::getPropertyMap() const throw()
+{
+ return mpMap->getPropertyMap();
+}
diff --git a/comphelper/source/property/propertystatecontainer.cxx b/comphelper/source/property/propertystatecontainer.cxx
new file mode 100644
index 000000000000..341dc1b43a78
--- /dev/null
+++ b/comphelper/source/property/propertystatecontainer.cxx
@@ -0,0 +1,339 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include "comphelper/propertystatecontainer.hxx"
+#include <rtl/ustrbuf.hxx>
+
+//.........................................................................
+namespace comphelper
+{
+//.........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::lang;
+
+ namespace
+ {
+ static ::rtl::OUString lcl_getUnknownPropertyErrorMessage( const ::rtl::OUString& _rPropertyName )
+ {
+ // TODO: perhaps it's time to think about resources in the comphelper module?
+ // Would be nice to have localized exception strings (a simply resource file containing
+ // strings only would suffice, and could be realized with an UNO service, so we do not
+ // need the dependency to the Tools project)
+ ::rtl::OUStringBuffer sMessage;
+ sMessage.appendAscii( "The property \"" );
+ sMessage.append( _rPropertyName );
+ sMessage.appendAscii( "\" is unknown." );
+ return sMessage.makeStringAndClear();
+ }
+ }
+
+ //=====================================================================
+ //= OPropertyStateContainer
+ //=====================================================================
+ //---------------------------------------------------------------------
+ OPropertyStateContainer::OPropertyStateContainer( ::cppu::OBroadcastHelper& _rBHelper )
+ :OPropertyContainer( _rBHelper )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ Any SAL_CALL OPropertyStateContainer::queryInterface( const Type& _rType ) throw (RuntimeException)
+ {
+ Any aReturn = OPropertyContainer::queryInterface( _rType );
+ if ( !aReturn.hasValue() )
+ aReturn = OPropertyStateContainer_TBase::queryInterface( _rType );
+ return aReturn;
+ }
+
+ //--------------------------------------------------------------------
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( OPropertyStateContainer, OPropertyContainer, OPropertyStateContainer_TBase )
+
+ //--------------------------------------------------------------------
+ sal_Int32 OPropertyStateContainer::getHandleForName( const ::rtl::OUString& _rPropertyName ) SAL_THROW( ( UnknownPropertyException ) )
+ {
+ // look up the handle for the name
+ ::cppu::IPropertyArrayHelper& rPH = getInfoHelper();
+ sal_Int32 nHandle = rPH.getHandleByName( _rPropertyName );
+
+ if ( -1 == nHandle )
+ throw UnknownPropertyException( lcl_getUnknownPropertyErrorMessage( _rPropertyName ), static_cast< XPropertyState* >( this ) );
+
+ return nHandle;
+ }
+
+ //--------------------------------------------------------------------
+ PropertyState SAL_CALL OPropertyStateContainer::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
+ {
+ return getPropertyStateByHandle( getHandleForName( _rPropertyName ) );
+ }
+
+ //--------------------------------------------------------------------
+ Sequence< PropertyState > SAL_CALL OPropertyStateContainer::getPropertyStates( const Sequence< ::rtl::OUString >& _rPropertyNames ) throw (UnknownPropertyException, RuntimeException)
+ {
+ sal_Int32 nProperties = _rPropertyNames.getLength();
+ Sequence< PropertyState> aStates( nProperties );
+ if ( !nProperties )
+ return aStates;
+
+#ifdef _DEBUG
+ // precondition: property sequence is sorted (the algorythm below relies on this)
+ {
+ const ::rtl::OUString* pNames = _rPropertyNames.getConstArray();
+ const ::rtl::OUString* pNamesCompare = pNames + 1;
+ const ::rtl::OUString* pNamesEnd = _rPropertyNames.getConstArray() + _rPropertyNames.getLength();
+ for ( ; pNamesCompare != pNamesEnd; ++pNames, ++pNamesCompare )
+ OSL_PRECOND( pNames->compareTo( *pNamesCompare ) < 0,
+ "OPropertyStateContainer::getPropertyStates: property sequence not sorted!" );
+ }
+#endif
+
+ const ::rtl::OUString* pLookup = _rPropertyNames.getConstArray();
+ const ::rtl::OUString* pLookupEnd = pLookup + nProperties;
+ PropertyState* pStates = aStates.getArray();
+
+ cppu::IPropertyArrayHelper& rHelper = getInfoHelper();
+ Sequence< Property> aAllProperties = rHelper.getProperties();
+ sal_Int32 nAllProperties = aAllProperties.getLength();
+ const Property* pAllProperties = aAllProperties.getConstArray();
+ const Property* pAllPropertiesEnd = pAllProperties + nAllProperties;
+
+ osl::MutexGuard aGuard( rBHelper.rMutex );
+ for ( ; ( pAllProperties != pAllPropertiesEnd ) && ( pLookup != pLookupEnd ); ++pAllProperties )
+ {
+#ifdef _DEBUG
+ if ( pAllProperties < pAllPropertiesEnd - 1 )
+ OSL_ENSURE( pAllProperties->Name.compareTo( (pAllProperties + 1)->Name ) < 0,
+ "OPropertyStateContainer::getPropertyStates: all-properties not sorted!" );
+#endif
+ if ( pAllProperties->Name.equals( *pLookup ) )
+ {
+ *pStates++ = getPropertyState( *pLookup );
+ ++pLookup;
+ }
+ }
+
+ if ( pLookup != pLookupEnd )
+ // we run out of properties from the IPropertyArrayHelper, but still have properties to lookup
+ // -> we were asked for a nonexistent property
+ throw UnknownPropertyException( lcl_getUnknownPropertyErrorMessage( *pLookup ), static_cast< XPropertyState* >( this ) );
+
+ return aStates;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OPropertyStateContainer::setPropertyToDefault( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
+ {
+ setPropertyToDefaultByHandle( getHandleForName( _rPropertyName ) );
+ }
+
+ //--------------------------------------------------------------------
+ Any SAL_CALL OPropertyStateContainer::getPropertyDefault( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ Any aDefault;
+ getPropertyDefaultByHandle( getHandleForName( _rPropertyName ), aDefault );
+ return aDefault;
+ }
+
+ //--------------------------------------------------------------------
+ PropertyState OPropertyStateContainer::getPropertyStateByHandle( sal_Int32 _nHandle )
+ {
+ // simply compare the current and the default value
+ Any aCurrentValue; getFastPropertyValue( aCurrentValue, _nHandle );
+ Any aDefaultValue; getPropertyDefaultByHandle( _nHandle, aDefaultValue );
+
+ sal_Bool bEqual = uno_type_equalData(
+ const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(),
+ const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(),
+ reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
+ reinterpret_cast< uno_ReleaseFunc >(cpp_release)
+ );
+ if ( bEqual )
+ return PropertyState_DEFAULT_VALUE;
+ else
+ return PropertyState_DIRECT_VALUE;
+ }
+
+ //--------------------------------------------------------------------
+ void OPropertyStateContainer::setPropertyToDefaultByHandle( sal_Int32 _nHandle )
+ {
+ Any aDefault;
+ getPropertyDefaultByHandle( _nHandle, aDefault );
+ setFastPropertyValue( _nHandle, aDefault );
+ }
+
+//.........................................................................
+} // namespace comphelper
+//.........................................................................
+
+#ifdef FS_PRIV_DEBUG
+#define STATECONTAINER_TEST
+#endif
+
+#ifdef STATECONTAINER_TEST
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/broadcasthelper.hxx>
+
+//.........................................................................
+namespace comphelper
+{
+//.........................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+
+ //=====================================================================
+ //= Test - compiler test
+ //=====================================================================
+ typedef ::cppu::OWeakAggObject Test_RefCountBase;
+ class Test :public OMutexAndBroadcastHelper
+ ,public OPropertyStateContainer
+ ,public OPropertyArrayUsageHelper< Test >
+ ,public Test_RefCountBase
+ {
+ private:
+ ::rtl::OUString m_sStringProperty;
+ Reference< XInterface > m_xInterfaceProperty;
+ Any m_aMayBeVoidProperty;
+
+ protected:
+ Test( );
+
+ DECLARE_XINTERFACE( )
+
+ public:
+ static Test* Create( );
+
+ protected:
+ virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(RuntimeException);
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const;
+
+ protected:
+ // OPropertyStateContainer overridables
+ virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const;
+ };
+
+ //---------------------------------------------------------------------
+ Test::Test( )
+ :OPropertyStateContainer( GetBroadcastHelper() )
+ {
+ registerProperty(
+ ::rtl::OUString::createFromAscii( "StringProperty" ),
+ 1,
+ PropertyAttribute::BOUND,
+ &m_sStringProperty,
+ ::getCppuType( &m_sStringProperty )
+ );
+
+ registerProperty(
+ ::rtl::OUString::createFromAscii( "InterfaceProperty" ),
+ 2,
+ PropertyAttribute::BOUND,
+ &m_xInterfaceProperty,
+ ::getCppuType( &m_xInterfaceProperty )
+ );
+
+ registerMayBeVoidProperty(
+ ::rtl::OUString::createFromAscii( "IntProperty" ),
+ 3,
+ PropertyAttribute::BOUND,
+ &m_aMayBeVoidProperty,
+ ::getCppuType( static_cast< sal_Int32* >( NULL ) )
+ );
+
+ registerPropertyNoMember(
+ ::rtl::OUString::createFromAscii( "OtherInterfaceProperty" ),
+ 4,
+ PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID,
+ ::getCppuType( static_cast< Reference< XInterface >* >( NULL ) ),
+ NULL
+ );
+ }
+
+ //---------------------------------------------------------------------
+ IMPLEMENT_FORWARD_XINTERFACE2( Test, Test_RefCountBase, OPropertyStateContainer )
+
+ //---------------------------------------------------------------------
+ void Test::getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const
+ {
+ switch ( _nHandle )
+ {
+ case 1:
+ _rDefault = makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StringPropertyDefault" ) ) );
+ break;
+ case 2:
+ _rDefault = makeAny( Reference< XInterface >( ) );
+ break;
+ case 3:
+ // void
+ break;
+ case 4:
+ _rDefault = makeAny( Reference< XInterface >( ) );
+ break;
+ default:
+ OSL_ENSURE( sal_False, "Test::getPropertyDefaultByHandle: invalid handle!" );
+ }
+ }
+
+ //---------------------------------------------------------------------
+ Reference< XPropertySetInfo > SAL_CALL Test::getPropertySetInfo( ) throw(RuntimeException)
+ {
+ return createPropertySetInfo( getInfoHelper() );
+ }
+
+ //---------------------------------------------------------------------
+ ::cppu::IPropertyArrayHelper& SAL_CALL Test::getInfoHelper()
+ {
+ return *getArrayHelper();
+ }
+
+ //---------------------------------------------------------------------
+ ::cppu::IPropertyArrayHelper* Test::createArrayHelper( ) const
+ {
+ Sequence< Property > aProps;
+ describeProperties( aProps );
+ return new ::cppu::OPropertyArrayHelper( aProps );
+ }
+
+ //---------------------------------------------------------------------
+ Test* Test::Create( )
+ {
+ Test* pInstance = new Test;
+ return pInstance;
+ }
+
+//.........................................................................
+} // namespace comphelper
+//.........................................................................
+
+#endif
+
diff --git a/comphelper/source/property/propmultiplex.cxx b/comphelper/source/property/propmultiplex.cxx
new file mode 100644
index 000000000000..db0b35650d32
--- /dev/null
+++ b/comphelper/source/property/propmultiplex.cxx
@@ -0,0 +1,182 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include <comphelper/propmultiplex.hxx>
+#include <osl/diagnose.h>
+
+//.........................................................................
+namespace comphelper
+{
+//.........................................................................
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+
+//========================================================================
+//= OPropertyChangeListener
+//========================================================================
+//------------------------------------------------------------------------
+OPropertyChangeListener::~OPropertyChangeListener()
+{
+ if (m_pAdapter)
+ m_pAdapter->dispose();
+}
+
+//------------------------------------------------------------------
+void OPropertyChangeListener::_disposing(const EventObject&) throw( RuntimeException)
+{
+ // nothing to do here
+}
+
+//------------------------------------------------------------------
+void OPropertyChangeListener::disposeAdapter()
+{
+ if ( m_pAdapter )
+ m_pAdapter->dispose();
+
+ // will automatically set a new adapter
+ OSL_ENSURE( !m_pAdapter, "OPropertyChangeListener::disposeAdapter: what did dispose do?" );
+}
+
+//------------------------------------------------------------------
+void OPropertyChangeListener::setAdapter(OPropertyChangeMultiplexer* pAdapter)
+{
+ if (m_pAdapter)
+ {
+ ::osl::MutexGuard aGuard(m_rMutex);
+ m_pAdapter->release();
+ m_pAdapter = NULL;
+ }
+
+ if (pAdapter)
+ {
+ ::osl::MutexGuard aGuard(m_rMutex);
+ m_pAdapter = pAdapter;
+ m_pAdapter->acquire();
+ }
+}
+
+//========================================================================
+//= OPropertyChangeMultiplexer
+//========================================================================
+//------------------------------------------------------------------
+OPropertyChangeMultiplexer::OPropertyChangeMultiplexer(OPropertyChangeListener* _pListener, const Reference< XPropertySet>& _rxSet, sal_Bool _bAutoReleaseSet)
+ :m_xSet(_rxSet)
+ ,m_pListener(_pListener)
+ ,m_nLockCount(0)
+ ,m_bListening(sal_False)
+ ,m_bAutoSetRelease(_bAutoReleaseSet)
+{
+ m_pListener->setAdapter(this);
+}
+
+//------------------------------------------------------------------
+OPropertyChangeMultiplexer::~OPropertyChangeMultiplexer()
+{
+}
+
+//------------------------------------------------------------------
+void OPropertyChangeMultiplexer::lock()
+{
+ ++m_nLockCount;
+}
+
+//------------------------------------------------------------------
+void OPropertyChangeMultiplexer::unlock()
+{
+ --m_nLockCount;
+}
+
+//------------------------------------------------------------------
+void OPropertyChangeMultiplexer::dispose()
+{
+ if (m_bListening)
+ {
+ Reference< XPropertyChangeListener> xPreventDelete(this);
+
+ const ::rtl::OUString* pProperties = m_aProperties.getConstArray();
+ for (sal_Int32 i = 0; i < m_aProperties.getLength(); ++i, ++pProperties)
+ m_xSet->removePropertyChangeListener(*pProperties, static_cast< XPropertyChangeListener*>(this));
+
+ m_pListener->setAdapter(NULL);
+
+ m_pListener = NULL;
+ m_bListening = sal_False;
+
+ if (m_bAutoSetRelease)
+ m_xSet = NULL;
+ }
+}
+
+// XEventListener
+//------------------------------------------------------------------
+void SAL_CALL OPropertyChangeMultiplexer::disposing( const EventObject& _rSource) throw( RuntimeException)
+{
+ if (m_pListener)
+ {
+ // tell the listener
+ if (!locked())
+ m_pListener->_disposing(_rSource);
+ // disconnect the listener
+ if (m_pListener) // may have been reset whilest calling into _disposing
+ m_pListener->setAdapter(NULL);
+ }
+
+ m_pListener = NULL;
+ m_bListening = sal_False;
+
+ if (m_bAutoSetRelease)
+ m_xSet = NULL;
+}
+
+// XPropertyChangeListener
+//------------------------------------------------------------------
+void SAL_CALL OPropertyChangeMultiplexer::propertyChange( const PropertyChangeEvent& _rEvent ) throw( RuntimeException)
+{
+ if (m_pListener && !locked())
+ m_pListener->_propertyChanged(_rEvent);
+}
+
+//------------------------------------------------------------------
+void OPropertyChangeMultiplexer::addProperty(const ::rtl::OUString& _sPropertyName)
+{
+ if (m_xSet.is())
+ {
+ m_xSet->addPropertyChangeListener(_sPropertyName, static_cast< XPropertyChangeListener*>(this));
+ m_aProperties.realloc(m_aProperties.getLength() + 1);
+ m_aProperties.getArray()[m_aProperties.getLength()-1] = _sPropertyName;
+ m_bListening = sal_True;
+ }
+}
+
+//.........................................................................
+}
+//.........................................................................
+
diff --git a/comphelper/source/property/propstate.cxx b/comphelper/source/property/propstate.cxx
new file mode 100644
index 000000000000..214bccb3f40f
--- /dev/null
+++ b/comphelper/source/property/propstate.cxx
@@ -0,0 +1,261 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_comphelper.hxx"
+#include <comphelper/propstate.hxx>
+#include <com/sun/star/uno/genfunc.h>
+#include <cppuhelper/queryinterface.hxx>
+#include <comphelper/sequence.hxx>
+
+//.........................................................................
+namespace comphelper
+{
+//.........................................................................
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::lang::XTypeProvider;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::cpp_queryInterface;
+ using ::com::sun::star::uno::cpp_release;
+ using ::com::sun::star::beans::PropertyState_DEFAULT_VALUE;
+ using ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
+
+ //=====================================================================
+ // OPropertyStateHelper
+ //=====================================================================
+
+ //---------------------------------------------------------------------
+ ::com::sun::star::uno::Any SAL_CALL OPropertyStateHelper::queryInterface(const ::com::sun::star::uno::Type& _rType) throw( ::com::sun::star::uno::RuntimeException)
+ {
+ ::com::sun::star::uno::Any aReturn = OPropertySetHelper::queryInterface(_rType);
+ // our own ifaces
+ if ( !aReturn.hasValue() )
+ aReturn = ::cppu::queryInterface(_rType, static_cast< ::com::sun::star::beans::XPropertyState*>(this));
+
+ return aReturn;
+ }
+
+ //---------------------------------------------------------------------
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> OPropertyStateHelper::getTypes() throw( ::com::sun::star::uno::RuntimeException)
+ {
+ static ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> aTypes;
+ if (!aTypes.getLength())
+ {
+ aTypes.realloc(4);
+ ::com::sun::star::uno::Type* pTypes = aTypes.getArray();
+ // base class types
+ pTypes[0] = getCppuType(( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>*)NULL);
+ pTypes[1] = getCppuType(( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XMultiPropertySet>*)NULL);
+ pTypes[2] = getCppuType(( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XFastPropertySet>*)NULL);
+ // my own type
+ pTypes[3] = getCppuType(( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState>*)NULL);
+ }
+ return aTypes;
+ }
+
+ OPropertyStateHelper::OPropertyStateHelper(
+ ::cppu::OBroadcastHelper& rBHlp,
+ ::cppu::IEventNotificationHook *i_pFireEvents)
+ : ::cppu::OPropertySetHelper(rBHlp, i_pFireEvents) { }
+
+ OPropertyStateHelper::~OPropertyStateHelper() {}
+
+ //---------------------------------------------------------------------
+ void OPropertyStateHelper::firePropertyChange(sal_Int32 nHandle, const ::com::sun::star::uno::Any& aNewValue, const ::com::sun::star::uno::Any& aOldValue)
+ {
+ fire(&nHandle, &aNewValue, &aOldValue, 1, sal_False);
+ }
+
+ // XPropertyState
+ //---------------------------------------------------------------------
+ ::com::sun::star::beans::PropertyState SAL_CALL OPropertyStateHelper::getPropertyState(const ::rtl::OUString& _rsName) throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
+ {
+ cppu::IPropertyArrayHelper& rPH = getInfoHelper();
+ sal_Int32 nHandle = rPH.getHandleByName(_rsName);
+
+ if (nHandle == -1)
+ throw ::com::sun::star::beans::UnknownPropertyException();
+
+ return getPropertyStateByHandle(nHandle);
+ }
+
+ //---------------------------------------------------------------------
+ void SAL_CALL OPropertyStateHelper::setPropertyToDefault(const ::rtl::OUString& _rsName) throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
+ {
+ cppu::IPropertyArrayHelper& rPH = getInfoHelper();
+ sal_Int32 nHandle = rPH.getHandleByName(_rsName);
+
+ if (nHandle == -1)
+ throw ::com::sun::star::beans::UnknownPropertyException();
+
+ setPropertyToDefaultByHandle(nHandle);
+ }
+
+ //---------------------------------------------------------------------
+ ::com::sun::star::uno::Any SAL_CALL OPropertyStateHelper::getPropertyDefault(const ::rtl::OUString& _rsName) throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
+ {
+ cppu::IPropertyArrayHelper& rPH = getInfoHelper();
+ sal_Int32 nHandle = rPH.getHandleByName(_rsName);
+
+ if (nHandle == -1)
+ throw ::com::sun::star::beans::UnknownPropertyException();
+
+ return getPropertyDefaultByHandle(nHandle);
+ }
+
+ //---------------------------------------------------------------------
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyState> SAL_CALL OPropertyStateHelper::getPropertyStates(const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rPropertyNames) throw( ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
+ {
+ sal_Int32 nLen = _rPropertyNames.getLength();
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyState> aRet(nLen);
+ ::com::sun::star::beans::PropertyState* pValues = aRet.getArray();
+ const ::rtl::OUString* pNames = _rPropertyNames.getConstArray();
+
+ cppu::IPropertyArrayHelper& rHelper = getInfoHelper();
+
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property> aProps = rHelper.getProperties();
+ const ::com::sun::star::beans::Property* pProps = aProps.getConstArray();
+ sal_Int32 nPropCount = aProps.getLength();
+
+ osl::MutexGuard aGuard(rBHelper.rMutex);
+ for (sal_Int32 i=0, j=0; i<nPropCount && j<nLen; ++i, ++pProps)
+ {
+ // get the values only for valid properties
+ if (pProps->Name.equals(*pNames))
+ {
+ *pValues = getPropertyState(*pNames);
+ ++pValues;
+ ++pNames;
+ ++j;
+ }
+ }
+
+ return aRet;
+ }
+
+ //---------------------------------------------------------------------
+ ::com::sun::star::beans::PropertyState OPropertyStateHelper::getPropertyStateByHandle( sal_Int32 _nHandle )
+ {
+ // simply compare the current and the default value
+ Any aCurrentValue = getPropertyDefaultByHandle( _nHandle );
+ Any aDefaultValue; getFastPropertyValue( aDefaultValue, _nHandle );
+
+ sal_Bool bEqual = uno_type_equalData(
+ const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(),
+ const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(),
+ reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
+ reinterpret_cast< uno_ReleaseFunc >(cpp_release)
+ );
+ return bEqual ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
+ }
+
+ //---------------------------------------------------------------------
+ void OPropertyStateHelper::setPropertyToDefaultByHandle( sal_Int32 _nHandle )
+ {
+ setFastPropertyValue( _nHandle, getPropertyDefaultByHandle( _nHandle ) );
+ }
+
+ //---------------------------------------------------------------------
+ ::com::sun::star::uno::Any OPropertyStateHelper::getPropertyDefaultByHandle( sal_Int32 ) const
+ {
+ return ::com::sun::star::uno::Any();
+ }
+
+ //=====================================================================
+ // OStatefulPropertySet
+ //=====================================================================
+ //---------------------------------------------------------------------
+ OStatefulPropertySet::OStatefulPropertySet()
+ :OPropertyStateHelper( GetBroadcastHelper() )
+ {
+ }
+
+ //---------------------------------------------------------------------
+ OStatefulPropertySet::~OStatefulPropertySet()
+ {
+ }
+
+ //---------------------------------------------------------------------
+ Sequence< Type > SAL_CALL OStatefulPropertySet::getTypes() throw(RuntimeException)
+ {
+ Sequence< Type > aOwnTypes( 2 );
+ aOwnTypes[0] = XWeak::static_type();
+ aOwnTypes[1] = XTypeProvider::static_type();
+
+ return concatSequences(
+ aOwnTypes,
+ OPropertyStateHelper::getTypes()
+ );
+ }
+
+ //---------------------------------------------------------------------
+ Sequence< sal_Int8 > SAL_CALL OStatefulPropertySet::getImplementationId() throw(RuntimeException)
+ {
+ static ::cppu::OImplementationId * pId = NULL;
+ if ( !pId )
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if ( !pId )
+ {
+ static ::cppu::OImplementationId aId;
+ pId = &aId;
+ }
+ }
+ return pId->getImplementationId();
+ }
+
+ //---------------------------------------------------------------------
+ Any SAL_CALL OStatefulPropertySet::queryInterface( const Type& _rType ) throw(RuntimeException)
+ {
+ Any aReturn = OWeakObject::queryInterface( _rType );
+ if ( !aReturn.hasValue() )
+ aReturn = ::cppu::queryInterface( _rType, static_cast< XTypeProvider* >( this ) );
+ if ( !aReturn.hasValue() )
+ aReturn = OPropertyStateHelper::queryInterface( _rType );
+ return aReturn;
+ }
+
+ //---------------------------------------------------------------------
+ void SAL_CALL OStatefulPropertySet::acquire() throw()
+ {
+ ::cppu::OWeakObject::acquire();
+ }
+
+ //---------------------------------------------------------------------
+ void SAL_CALL OStatefulPropertySet::release() throw()
+ {
+ ::cppu::OWeakObject::release();
+ }
+
+//.........................................................................
+}
+//.........................................................................
+