blob: 8fa742a80bafd93e418da20d244c9018c712f386 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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