#103388# introduced ElementDescription to cache some information (interfaces) about to-be-inserted objects / in disposing(EventObject), normalize the interfaces to be compared - sacves a _lot_ of queryInterfaces

This commit is contained in:
Frank Schönheit
2002-10-04 07:09:11 +00:00
parent ab21ea3329
commit 95c0977c33

View File

@@ -2,9 +2,9 @@
* *
* $RCSfile: InterfaceContainer.cxx,v $ * $RCSfile: InterfaceContainer.cxx,v $
* *
* $Revision: 1.14 $ * $Revision: 1.15 $
* *
* last change: $Author: fs $ $Date: 2002-01-18 15:28:51 $ * last change: $Author: fs $ $Date: 2002-10-04 08:09:11 $
* *
* The Contents of this file are made available subject to the terms of * The Contents of this file are made available subject to the terms of
* either of the following licenses * either of the following licenses
@@ -116,6 +116,11 @@
#endif #endif
#include <algorithm> #include <algorithm>
#include <memory>
#ifndef _RTL_LOGFILE_HXX_
#include <rtl/logfile.hxx>
#endif
//......................................................................... //.........................................................................
namespace frm namespace frm
@@ -141,6 +146,22 @@ using namespace ::com::sun::star::form;
throw IllegalArgumentException(); throw IllegalArgumentException();
} }
//==================================================================
//= ElementDescription
//==================================================================
//------------------------------------------------------------------
ElementDescription::ElementDescription( )
{
}
//------------------------------------------------------------------
ElementDescription::~ElementDescription()
{
}
//==================================================================
//= OInterfaceContainer
//==================================================================
//------------------------------------------------------------------ //------------------------------------------------------------------
OInterfaceContainer::OInterfaceContainer( OInterfaceContainer::OInterfaceContainer(
const Reference<XMultiServiceFactory>& _rxFactory, const Reference<XMultiServiceFactory>& _rxFactory,
@@ -502,13 +523,13 @@ void SAL_CALL OInterfaceContainer::read( const Reference< XObjectInputStream >&
Any aElement = xObj->queryInterface(m_aElementType); Any aElement = xObj->queryInterface(m_aElementType);
if (aElement.hasValue()) if (aElement.hasValue())
{ {
Reference< XInterface > xElement; Reference< XPropertySet > xElement;
aElement >>= xElement; aElement >>= xElement;
implInsert( implInsert(
m_aItems.size(), // position m_aItems.size(), // position
xElement, // element to insert xElement, // element to insert
sal_False, // no event attacher manager handling sal_False, // no event attacher manager handling
sal_True, // approve the element NULL, // not yet approved - let implInsert do it
sal_True // fire the event sal_True // fire the event
); );
} }
@@ -542,12 +563,34 @@ void SAL_CALL OInterfaceContainer::disposing(const EventObject& _rSource) throw(
{ {
::osl::MutexGuard aGuard( m_rMutex ); ::osl::MutexGuard aGuard( m_rMutex );
OInterfaceArray::iterator j = find(m_aItems.begin(), m_aItems.end(), _rSource.Source); Reference< XInterface > xSource( _rSource.Source, UNO_QUERY );
if (j != m_aItems.end()) // normalized source
OInterfaceArray::iterator j;
for ( j = m_aItems.begin(); j != m_aItems.end(); ++j )
{
DBG_ASSERT( j->get() == Reference< XInterface >( *j, UNO_QUERY ).get(),
"OInterfaceContainer::disposing: vector element not normalized!" );
if ( xSource.get() == j->get() )
// found the element
break;
}
if ( m_aItems.end() != j )
{ {
OInterfaceMap::iterator i = m_aMap.begin(); OInterfaceMap::iterator i = m_aMap.begin();
while (i != m_aMap.end() && i->second != _rSource.Source) while ( i != m_aMap.end() )
{
DBG_ASSERT( i->second.get() == Reference< XInterface >( i->second, UNO_QUERY ).get(),
"OInterfaceContainer::disposing: map element not normalized!" );
if ( i->second.get() == _rSource.Source.get() )
// found it
break;
++i; ++i;
}
m_aMap.erase(i); m_aMap.erase(i);
m_aItems.erase(j); m_aItems.erase(j);
@@ -644,80 +687,96 @@ Any OInterfaceContainer::getByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsEx
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
InterfaceRef OInterfaceContainer::approveNewElement( const Any& _rObject ) void OInterfaceContainer::approveNewElement( const Reference< XPropertySet >& _rxObject, ElementDescription* _pElement )
{
Reference< XInterface > xObject;
_rObject >>= xObject;
return approveNewElement( xObject );
}
//------------------------------------------------------------------------------
InterfaceRef OInterfaceContainer::approveNewElement( const InterfaceRef& _rxObject )
{ {
// it has to be non-NULL
if ( !_rxObject.is() ) if ( !_rxObject.is() )
throw IllegalArgumentException(FRM_RES_STRING(RID_STR_NEED_NON_NULL_OBJECT), static_cast<XContainer*>(this), 1); throw IllegalArgumentException(FRM_RES_STRING(RID_STR_NEED_NON_NULL_OBJECT), static_cast<XContainer*>(this), 1);
// it has to support our element type interface
Any aCorrectType = _rxObject->queryInterface( m_aElementType ); Any aCorrectType = _rxObject->queryInterface( m_aElementType );
if ( !aCorrectType.hasValue() ) if ( !aCorrectType.hasValue() )
lcl_throwIllegalArgumentException(); lcl_throwIllegalArgumentException();
Reference< XPropertySet > xSet( _rxObject, UNO_QUERY ); // it has to have a "Name" property
if ( !xSet.is() || !hasProperty( PROPERTY_NAME, xSet ) ) if ( !hasProperty( PROPERTY_NAME, _rxObject ) )
lcl_throwIllegalArgumentException(); lcl_throwIllegalArgumentException();
// it has to be a child, and it must not have a parent already
Reference< XChild > xChild( _rxObject, UNO_QUERY ); Reference< XChild > xChild( _rxObject, UNO_QUERY );
if ( !xChild.is() || xChild->getParent().is() ) if ( !xChild.is() || xChild->getParent().is() )
lcl_throwIllegalArgumentException(); lcl_throwIllegalArgumentException();
return _rxObject; // passed all tests. cache the information we have so far
DBG_ASSERT( _pElement, "OInterfaceContainer::approveNewElement: invalid event descriptor!" );
if ( _pElement )
{
_pElement->xPropertySet = _rxObject;
_pElement->xChild = xChild;
_pElement->aElementTypeInterface = aCorrectType;
_pElement->xInterface = Reference< XInterface >( _rxObject, UNO_QUERY ); // normalized XInterface
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void OInterfaceContainer::implInsert(sal_Int32 _nIndex, const InterfaceRef& _rxElement, void OInterfaceContainer::implInsert(sal_Int32 _nIndex, const Reference< XPropertySet >& _rxElement,
sal_Bool _bEvents, sal_Bool _bApprove, sal_Bool _bFire ) throw( IllegalArgumentException ) sal_Bool _bEvents, ElementDescription* _pApprovalResult, sal_Bool _bFire ) throw( IllegalArgumentException )
{ {
RTL_LOGFILE_CONTEXT( aLogger, "forms::OInterfaceContainer::implInsert" );
::osl::ClearableMutexGuard aGuard( m_rMutex ); ::osl::ClearableMutexGuard aGuard( m_rMutex );
// will throw an exception if necessary ::std::auto_ptr< ElementDescription > aAutoDeleteMetaData;
if ( _bApprove ) ElementDescription* pElementMetaData = _pApprovalResult;
approveNewElement( _rxElement ); if ( !pElementMetaData )
{ // not yet approved by the caller -> do ourself
pElementMetaData = createElementMetaData();
DBG_ASSERT( aElementMetaData.get(), "OInterfaceContainer::implInsert: createElementMetaData returned nonsense!" );
// das richtige Interface besorgen // ensure that the meta data structure will be deleted later on
InterfaceRef xCorrectType; aAutoDeleteMetaData = ::std::auto_ptr< ElementDescription >( pElementMetaData );
Any aCorrectedType = _rxElement->queryInterface( m_aElementType );
aCorrectedType >>= xCorrectType;
Reference<XPropertySet> xSet( _rxElement, UNO_QUERY );
// approveNewElement has ensured that both xCorrectType and xSet are not NULL // will throw an exception if necessary
approveNewElement( _rxElement, pElementMetaData );
}
// approveNewElement (no matter if called here or outside) has ensure that all relevant interfaces
// exist
// set the name, and add as change listener for the name
::rtl::OUString sName; ::rtl::OUString sName;
xSet->getPropertyValue(PROPERTY_NAME) >>= sName; _rxElement->getPropertyValue(PROPERTY_NAME) >>= sName;
xSet->addPropertyChangeListener(PROPERTY_NAME, this); _rxElement->addPropertyChangeListener(PROPERTY_NAME, this);
// insert the object into our internal structures
if (_nIndex > (sal_Int32)m_aItems.size()) // ermitteln des tatsaechlichen Indexs if (_nIndex > (sal_Int32)m_aItems.size()) // ermitteln des tatsaechlichen Indexs
{ {
_nIndex = m_aItems.size(); _nIndex = m_aItems.size();
m_aItems.push_back(xCorrectType); m_aItems.push_back( pElementMetaData->xInterface );
} }
else else
m_aItems.insert(m_aItems.begin() + _nIndex, xCorrectType); m_aItems.insert( m_aItems.begin() + _nIndex, pElementMetaData->xInterface );
m_aMap.insert(pair<const ::rtl::OUString, InterfaceRef >(sName,xCorrectType)); m_aMap.insert( pair< const ::rtl::OUString, InterfaceRef >( sName, pElementMetaData->xInterface ) );
Reference<XChild> xChild(_rxElement, UNO_QUERY); // announce ourself as parent to the new element
if (xChild.is()) {
xChild->setParent(static_cast<XContainer*>(this)); RTL_LOGFILE_CONTEXT( aLogger, "forms::OInterfaceContainer::implInsert::settingParent" );
pElementMetaData->xChild->setParent(static_cast<XContainer*>(this));
}
// handle the events
if (_bEvents) if (_bEvents)
{ {
m_xEventAttacher->insertEntry(_nIndex); m_xEventAttacher->insertEntry(_nIndex);
Reference< XInterface > xAsIFace(_rxElement, UNO_QUERY); // important to normalize this .... m_xEventAttacher->attach( _nIndex, pElementMetaData->xInterface, makeAny( _rxElement ) );
m_xEventAttacher->attach( _nIndex, xAsIFace, makeAny( xSet ) );
} }
// notify derived classes // notify derived classes
implInserted(xCorrectType); implInserted( pElementMetaData );
// fire the notification about the change
if ( _bFire ) if ( _bFire )
{ {
aGuard.clear(); aGuard.clear();
@@ -726,7 +785,7 @@ void OInterfaceContainer::implInsert(sal_Int32 _nIndex, const InterfaceRef& _rxE
ContainerEvent aEvt; ContainerEvent aEvt;
aEvt.Source = static_cast<XContainer*>(this); aEvt.Source = static_cast<XContainer*>(this);
aEvt.Accessor <<= _nIndex; aEvt.Accessor <<= _nIndex;
aEvt.Element = aCorrectedType; aEvt.Element = pElementMetaData->aElementTypeInterface;
NOTIFY_LISTENERS(m_aContainerListeners, XContainerListener, elementInserted, aEvt); NOTIFY_LISTENERS(m_aContainerListeners, XContainerListener, elementInserted, aEvt);
} }
} }
@@ -756,9 +815,9 @@ void OInterfaceContainer::removeElementsNoEvents(sal_Int32 nIndex)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void SAL_CALL OInterfaceContainer::insertByIndex( sal_Int32 _nIndex, const Any& _rElement ) throw(IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException) void SAL_CALL OInterfaceContainer::insertByIndex( sal_Int32 _nIndex, const Any& _rElement ) throw(IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
{ {
Reference< XInterface > xElement; Reference< XPropertySet > xElement;
_rElement >>= xElement; _rElement >>= xElement;
implInsert( _nIndex, xElement ); implInsert( _nIndex, xElement, sal_True /* event handling */ , NULL /* not yet approved */ , sal_True /* notification */ );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -769,58 +828,67 @@ void SAL_CALL OInterfaceContainer::replaceByIndex(sal_Int32 _nIndex, const Any&
::osl::ClearableMutexGuard aGuard( m_rMutex ); ::osl::ClearableMutexGuard aGuard( m_rMutex );
InterfaceRef xNewElement = approveNewElement( Element ); // approve the new object
::std::auto_ptr< ElementDescription > aElementMetaData( createElementMetaData() );
InterfaceRef xOldElement(m_aItems[_nIndex]); DBG_ASSERT( aElementMetaData.get(), "OInterfaceContainer::replaceByIndex: createElementMetaData returned nonsense!" );
{
Reference< XPropertySet > xElementProps;
Element >>= xElementProps;
approveNewElement( xElementProps, aElementMetaData.get() );
}
// get the old element
InterfaceRef xOldElement( m_aItems[ _nIndex ] );
DBG_ASSERT( xOldElement.get() == Reference< XInterface >( xOldElement, UNO_QUERY ).get(),
"OInterfaceContainer::replaceByIndex: elements should be held normalized!" );
// locate the old element in the map
OInterfaceMap::iterator j = m_aMap.begin(); OInterfaceMap::iterator j = m_aMap.begin();
while (j != m_aMap.end() && (*j).second != xOldElement) ++j; while ( ( j != m_aMap.end() ) && ( j->second.get() != xOldElement.get() ) )
++j;
// Eventverkn<EFBFBD>pfungen aufheben // remove event knittings
InterfaceRef xIfc(xOldElement, UNO_QUERY);// wichtig InterfaceRef xIfc(xOldElement, UNO_QUERY);// wichtig
m_xEventAttacher->detach(_nIndex, xIfc); m_xEventAttacher->detach(_nIndex, xIfc);
m_xEventAttacher->removeEntry(_nIndex); m_xEventAttacher->removeEntry(_nIndex);
Reference<XPropertySet> xSet(xOldElement, UNO_QUERY); // don't listen for property changes anymore
Reference<XPropertySet> xSet( xOldElement, UNO_QUERY );
if (xSet.is()) if (xSet.is())
xSet->removePropertyChangeListener(PROPERTY_NAME, this); xSet->removePropertyChangeListener(PROPERTY_NAME, this);
// give the old element a new (void) parent
Reference<XChild> xChild(xOldElement, UNO_QUERY); Reference<XChild> xChild(xOldElement, UNO_QUERY);
if (xChild.is()) if (xChild.is())
xChild->setParent(InterfaceRef ()); xChild->setParent(InterfaceRef ());
// neue einfuegen
::rtl::OUString sName;
xSet = xSet.query( xNewElement );
DBG_ASSERT( xSet.is(), "OInterfaceContainer::replaceByIndex: what did approveNewElement do?" );
xSet->getPropertyValue(PROPERTY_NAME) >>= sName;
xSet->addPropertyChangeListener(PROPERTY_NAME, this);
// remove the old one // remove the old one
m_aMap.erase(j); m_aMap.erase(j);
// insert the new one // examine the new element
m_aMap.insert(pair<const ::rtl::OUString, InterfaceRef >(sName,xNewElement)); ::rtl::OUString sName;
m_aItems[_nIndex] = xNewElement; DBG_ASSERT( aElementMetaData.get()->xPropertySet.is(), "OInterfaceContainer::replaceByIndex: what did approveNewElement do?" );
xChild = Reference<XChild> (xNewElement, UNO_QUERY); aElementMetaData.get()->xPropertySet->getPropertyValue(PROPERTY_NAME) >>= sName;
if (xChild.is()) aElementMetaData.get()->xPropertySet->addPropertyChangeListener(PROPERTY_NAME, this);
xChild->setParent(static_cast<XContainer*>(this));
// insert the new one
m_aMap.insert( pair<const ::rtl::OUString, InterfaceRef >( sName, aElementMetaData.get()->xInterface ) );
m_aItems[ _nIndex ] = aElementMetaData.get()->xInterface;
aElementMetaData.get()->xChild->setParent(static_cast<XContainer*>(this));
m_xEventAttacher->insertEntry(_nIndex); m_xEventAttacher->insertEntry(_nIndex);
xIfc = InterfaceRef ( xNewElement, UNO_QUERY );// wichtig m_xEventAttacher->attach( _nIndex, aElementMetaData.get()->xInterface, makeAny( aElementMetaData.get()->xPropertySet ) );
m_xEventAttacher->attach( _nIndex, xIfc, makeAny( xSet ) );
implReplaced(xOldElement, xNewElement); implReplaced( xOldElement, aElementMetaData.get() );
// benachrichtigen // benachrichtigen
aGuard.clear(); aGuard.clear();
ContainerEvent aEvt; ContainerEvent aEvt;
aEvt.Source = static_cast<XContainer*>(this); aEvt.Source = static_cast<XContainer*>(this);
aEvt.Accessor <<= _nIndex; aEvt.Accessor <<= _nIndex;
aEvt.Element = xNewElement->queryInterface( m_aElementType ); aEvt.Element = aElementMetaData.get()->aElementTypeInterface;
aEvt.ReplacedElement = xOldElement->queryInterface( m_aElementType ); aEvt.ReplacedElement = xOldElement->queryInterface( m_aElementType );
NOTIFY_LISTENERS(m_aContainerListeners, XContainerListener, elementReplaced, aEvt); NOTIFY_LISTENERS(m_aContainerListeners, XContainerListener, elementReplaced, aEvt);
} }
@@ -865,15 +933,30 @@ void SAL_CALL OInterfaceContainer::removeByIndex(sal_Int32 _nIndex) throw( Index
NOTIFY_LISTENERS(m_aContainerListeners, XContainerListener, elementRemoved, aEvt); NOTIFY_LISTENERS(m_aContainerListeners, XContainerListener, elementRemoved, aEvt);
} }
//------------------------------------------------------------------------
ElementDescription* OInterfaceContainer::createElementMetaData( )
{
return new ElementDescription;
}
//------------------------------------------------------------------------ //------------------------------------------------------------------------
void SAL_CALL OInterfaceContainer::insertByName(const ::rtl::OUString& _rName, const Any& _rElement) throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException ) void SAL_CALL OInterfaceContainer::insertByName(const ::rtl::OUString& _rName, const Any& _rElement) throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException )
{ {
Reference< XPropertySet > xElementProps; Reference< XPropertySet > xElementProps;
::std::auto_ptr< ElementDescription > aElementMetaData( createElementMetaData() );
DBG_ASSERT( aElementMetaData.get(), "OInterfaceContainer::insertByName: createElementMetaData returned nonsense!" );
if ( getCount() == 2969 )
{
sal_Int32 nDummy = 0;
}
// ensure the correct name of the element // ensure the correct name of the element
try try
{ {
_rElement >>= xElementProps; _rElement >>= xElementProps;
approveNewElement( xElementProps ); approveNewElement( xElementProps, aElementMetaData.get() );
xElementProps->setPropertyValue( PROPERTY_NAME, makeAny( _rName ) ); xElementProps->setPropertyValue( PROPERTY_NAME, makeAny( _rName ) );
} }
@@ -889,8 +972,7 @@ void SAL_CALL OInterfaceContainer::insertByName(const ::rtl::OUString& _rName, c
{ {
DBG_ERROR( "OInterfaceContainer::insertByName: caught an exception!" ); DBG_ERROR( "OInterfaceContainer::insertByName: caught an exception!" );
} }
implInsert( m_aItems.size(), xElementProps, sal_True, sal_False, sal_True ); implInsert( m_aItems.size(), xElementProps, sal_True, aElementMetaData.get(), sal_True );
// do not approve - we already did this
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------