xref: /trunk/main/dbaccess/source/core/dataaccess/ContentHelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 #ifndef DBA_CONTENTHELPER_HXX
31 #include "ContentHelper.hxx"
32 #endif
33 #ifndef _UCBHELPER_CANCELCOMMANDEXECUTION_HXX_
34 #include <ucbhelper/cancelcommandexecution.hxx>
35 #endif
36 #ifndef _COMPHELPER_PROPERTY_HXX_
37 #include <comphelper/property.hxx>
38 #endif
39 #ifndef _COM_SUN_STAR_UCB_UNSUPPORTEDCOMMANDEXCEPTION_HPP_
40 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
41 #endif
42 #ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_
43 #include <com/sun/star/lang/IllegalArgumentException.hpp>
44 #endif
45 #ifndef _COM_SUN_STAR_LANG_ILLEGALACCESSEXCEPTION_HPP_
46 #include <com/sun/star/lang/IllegalAccessException.hpp>
47 #endif
48 #ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
49 #include <com/sun/star/io/XOutputStream.hpp>
50 #endif
51 #ifndef _COM_SUN_STAR_IO_XACTIVEDATASINK_HPP_
52 #include <com/sun/star/io/XActiveDataSink.hpp>
53 #endif
54 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
55 #include <com/sun/star/beans/PropertyAttribute.hpp>
56 #endif
57 #ifndef _UCBHELPER_PROPERTYVALUESET_HXX
58 #include <ucbhelper/propertyvalueset.hxx>
59 #endif
60 #ifndef _UCBHELPER_CONTENTIDENTIFIER_HXX
61 #include <ucbhelper/contentidentifier.hxx>
62 #endif
63 #ifndef DBA_UCPRESULTSET_HXX
64 #include "myucp_resultset.hxx"
65 #endif
66 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
67 #include <com/sun/star/container/XNameContainer.hpp>
68 #endif
69 #ifndef DBACORE_SDBCORETOOLS_HXX
70 #include "sdbcoretools.hxx"
71 #endif
72 #ifndef DBACCESS_SHARED_DBASTRINGS_HRC
73 #include "dbastrings.hrc"
74 #endif
75 #ifndef _TOOLS_DEBUG_HXX
76 #include <tools/debug.hxx>
77 #endif
78 
79 
80 namespace dbaccess
81 {
82 using namespace ::com::sun::star::uno;
83 using namespace ::com::sun::star::ucb;
84 using namespace ::com::sun::star::beans;
85 using namespace ::com::sun::star::lang;
86 using namespace ::com::sun::star::sdbc;
87 using namespace ::com::sun::star::io;
88 using namespace ::com::sun::star::util;
89 using namespace ::com::sun::star::embed;
90 using namespace ::com::sun::star::container;
91 using namespace ::comphelper;
92 using namespace ::cppu;
93 
94 // -----------------------------------------------------------------------------
95 DBG_NAME(OContentHelper_Impl)
96 OContentHelper_Impl::OContentHelper_Impl()
97 {
98     DBG_CTOR(OContentHelper_Impl,NULL);
99 }
100 // -----------------------------------------------------------------------------
101 OContentHelper_Impl::~OContentHelper_Impl()
102 {
103     DBG_DTOR(OContentHelper_Impl,NULL);
104 }
105 // -----------------------------------------------------------------------------
106 
107 OContentHelper::OContentHelper(const Reference< XMultiServiceFactory >& _xORB
108                                ,const Reference< XInterface >&  _xParentContainer
109                                ,const TContentPtr& _pImpl)
110     : OContentHelper_COMPBASE(m_aMutex)
111     ,m_aContentListeners(m_aMutex)
112     ,m_aPropertyChangeListeners(m_aMutex)
113     ,m_xParentContainer(_xParentContainer)
114     ,m_aContext( _xORB )
115     ,m_aErrorHelper( m_aContext )
116     ,m_pImpl(_pImpl)
117     ,m_nCommandId(0)
118 {
119 }
120 //--------------------------------------------------------------------------
121 void SAL_CALL OContentHelper::disposing()
122 {
123     ::osl::MutexGuard aGuard(m_aMutex);
124 
125     // say our listeners goobye
126     EventObject aEvt(*this);
127     m_aContentListeners.disposeAndClear(aEvt);
128 
129     m_xParentContainer = NULL;
130 }
131 // -----------------------------------------------------------------------------
132 IMPLEMENT_SERVICE_INFO1(OContentHelper,"com.sun.star.comp.sdb.Content","com.sun.star.ucb.Content");
133 IMPLEMENT_IMPLEMENTATION_ID(OContentHelper)
134 // -----------------------------------------------------------------------------
135 // XContent
136 Reference< XContentIdentifier > SAL_CALL OContentHelper::getIdentifier(  ) throw (RuntimeException)
137 {
138     ::osl::MutexGuard aGuard(m_aMutex);
139     ::rtl::OUStringBuffer aIdentifier;
140     aIdentifier.appendAscii( "private:" );
141     aIdentifier.append( impl_getHierarchicalName( true ) );
142     return new ::ucbhelper::ContentIdentifier( m_aContext.getLegacyServiceFactory(), aIdentifier.makeStringAndClear() );
143 }
144 // -----------------------------------------------------------------------------
145 ::rtl::OUString OContentHelper::impl_getHierarchicalName( bool _includingRootContainer ) const
146 {
147     ::rtl::OUStringBuffer aHierarchicalName( m_pImpl->m_aProps.aTitle );
148     Reference< XInterface > xParent = m_xParentContainer;
149     while( xParent.is() )
150     {
151         Reference<XPropertySet> xProp( xParent, UNO_QUERY );
152         Reference< XChild > xChild( xParent, UNO_QUERY );
153         xParent.set( xChild.is() ? xChild->getParent() : Reference< XInterface >(), UNO_QUERY );
154         if ( xProp.is() && xParent.is() )
155         {
156             ::rtl::OUString sName;
157             xProp->getPropertyValue( PROPERTY_NAME ) >>= sName;
158 
159             ::rtl::OUString sPrevious = aHierarchicalName.makeStringAndClear();
160             aHierarchicalName.append( sName );
161             aHierarchicalName.append( sal_Unicode( '/' ) );
162             aHierarchicalName.append( sPrevious );
163         }
164     }
165     ::rtl::OUString sHierarchicalName( aHierarchicalName.makeStringAndClear() );
166     if ( !_includingRootContainer )
167         sHierarchicalName = sHierarchicalName.copy( sHierarchicalName.indexOf( '/' ) + 1 );
168     return sHierarchicalName;
169 }
170 
171 // -----------------------------------------------------------------------------
172 ::rtl::OUString SAL_CALL OContentHelper::getContentType() throw (RuntimeException)
173 {
174     ::osl::MutexGuard aGuard(m_aMutex);
175 
176     if ( !m_pImpl->m_aProps.aContentType )
177     {   // content type not yet retrieved
178         m_pImpl->m_aProps.aContentType.reset( determineContentType() );
179     }
180 
181     return *m_pImpl->m_aProps.aContentType;
182 }
183 // -----------------------------------------------------------------------------
184 void SAL_CALL OContentHelper::addContentEventListener( const Reference< XContentEventListener >& _rxListener ) throw (RuntimeException)
185 {
186     ::osl::MutexGuard aGuard(m_aMutex);
187     if ( _rxListener.is() )
188         m_aContentListeners.addInterface(_rxListener);
189 }
190 // -----------------------------------------------------------------------------
191 void SAL_CALL OContentHelper::removeContentEventListener( const Reference< XContentEventListener >& _rxListener ) throw (RuntimeException)
192 {
193     ::osl::MutexGuard aGuard(m_aMutex);
194     if (_rxListener.is())
195         m_aContentListeners.removeInterface(_rxListener);
196 }
197 // -----------------------------------------------------------------------------
198 
199 // XCommandProcessor
200 sal_Int32 SAL_CALL OContentHelper::createCommandIdentifier(  ) throw (RuntimeException)
201 {
202     ::osl::MutexGuard aGuard(m_aMutex);
203     // Just increase counter on every call to generate an identifier.
204     return ++m_nCommandId;
205 }
206 // -----------------------------------------------------------------------------
207 Any SAL_CALL OContentHelper::execute( const Command& aCommand, sal_Int32 /*CommandId*/, const Reference< XCommandEnvironment >& Environment ) throw (Exception, CommandAbortedException, RuntimeException)
208 {
209     Any aRet;
210     if ( aCommand.Name.compareToAscii( "getPropertyValues" ) == 0 )
211     {
212         //////////////////////////////////////////////////////////////////
213         // getPropertyValues
214         //////////////////////////////////////////////////////////////////
215 
216         Sequence< Property > Properties;
217         if ( !( aCommand.Argument >>= Properties ) )
218         {
219             OSL_ENSURE( sal_False, "Wrong argument type!" );
220             ucbhelper::cancelCommandExecution(
221                 makeAny( IllegalArgumentException(
222                                     rtl::OUString(),
223                                     static_cast< cppu::OWeakObject * >( this ),
224                                     -1 ) ),
225                 Environment );
226             // Unreachable
227         }
228         aRet <<= getPropertyValues( Properties);
229     }
230     else if ( aCommand.Name.compareToAscii( "setPropertyValues" ) == 0 )
231     {
232         //////////////////////////////////////////////////////////////////
233         // setPropertyValues
234         //////////////////////////////////////////////////////////////////
235 
236         Sequence< PropertyValue > aProperties;
237         if ( !( aCommand.Argument >>= aProperties ) )
238         {
239             OSL_ENSURE( sal_False, "Wrong argument type!" );
240             ucbhelper::cancelCommandExecution(
241                 makeAny( IllegalArgumentException(
242                                     rtl::OUString(),
243                                     static_cast< cppu::OWeakObject * >( this ),
244                                     -1 ) ),
245                 Environment );
246             // Unreachable
247         }
248 
249         if ( !aProperties.getLength() )
250         {
251             OSL_ENSURE( sal_False, "No properties!" );
252             ucbhelper::cancelCommandExecution(
253                 makeAny( IllegalArgumentException(
254                                     rtl::OUString(),
255                                     static_cast< cppu::OWeakObject * >( this ),
256                                     -1 ) ),
257                 Environment );
258             // Unreachable
259         }
260 
261         aRet <<= setPropertyValues( aProperties, Environment );
262     }
263     else if ( aCommand.Name.compareToAscii( "getPropertySetInfo" ) == 0 )
264     {
265         //////////////////////////////////////////////////////////////////
266         // getPropertySetInfo
267         //////////////////////////////////////////////////////////////////
268 
269         Reference<XPropertySet> xProp(*this,UNO_QUERY);
270         if ( xProp.is() )
271             aRet <<= xProp->getPropertySetInfo();
272         //  aRet <<= getPropertySetInfo(); // TODO
273     }
274     else
275     {
276         //////////////////////////////////////////////////////////////////
277         // Unsupported command
278         //////////////////////////////////////////////////////////////////
279 
280         OSL_ENSURE( sal_False, "Content::execute - unsupported command!" );
281 
282         ucbhelper::cancelCommandExecution(
283             makeAny( UnsupportedCommandException(
284                             rtl::OUString(),
285                             static_cast< cppu::OWeakObject * >( this ) ) ),
286             Environment );
287         // Unreachable
288     }
289 
290     return aRet;
291 }
292 // -----------------------------------------------------------------------------
293 void SAL_CALL OContentHelper::abort( sal_Int32 /*CommandId*/ ) throw (RuntimeException)
294 {
295 }
296 // -----------------------------------------------------------------------------
297 
298 // XPropertiesChangeNotifier
299 void SAL_CALL OContentHelper::addPropertiesChangeListener( const Sequence< ::rtl::OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener ) throw (RuntimeException)
300 {
301     ::osl::MutexGuard aGuard(m_aMutex);
302     sal_Int32 nCount = PropertyNames.getLength();
303     if ( !nCount )
304     {
305         // Note: An empty sequence means a listener for "all" properties.
306         m_aPropertyChangeListeners.addInterface(::rtl::OUString(), Listener );
307     }
308     else
309     {
310         const ::rtl::OUString* pSeq = PropertyNames.getConstArray();
311 
312         for ( sal_Int32 n = 0; n < nCount; ++n )
313         {
314             const ::rtl::OUString& rName = pSeq[ n ];
315             if ( rName.getLength() )
316                 m_aPropertyChangeListeners.addInterface(rName, Listener );
317         }
318     }
319 }
320 // -----------------------------------------------------------------------------
321 void SAL_CALL OContentHelper::removePropertiesChangeListener( const Sequence< ::rtl::OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener ) throw (RuntimeException)
322 {
323     ::osl::MutexGuard aGuard(m_aMutex);
324     sal_Int32 nCount = PropertyNames.getLength();
325     if ( !nCount )
326     {
327         // Note: An empty sequence means a listener for "all" properties.
328         m_aPropertyChangeListeners.removeInterface( ::rtl::OUString(), Listener );
329     }
330     else
331     {
332         const ::rtl::OUString* pSeq = PropertyNames.getConstArray();
333 
334         for ( sal_Int32 n = 0; n < nCount; ++n )
335         {
336             const ::rtl::OUString& rName = pSeq[ n ];
337             if ( rName.getLength() )
338                 m_aPropertyChangeListeners.removeInterface( rName, Listener );
339         }
340     }
341 }
342 // -----------------------------------------------------------------------------
343 
344 // XPropertyContainer
345 void SAL_CALL OContentHelper::addProperty( const ::rtl::OUString& /*Name*/, sal_Int16 /*Attributes*/, const Any& /*DefaultValue*/ ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException)
346 {
347     DBG_ERROR( "OContentHelper::addProperty: not implemented!" );
348 }
349 // -----------------------------------------------------------------------------
350 void SAL_CALL OContentHelper::removeProperty( const ::rtl::OUString& /*Name*/ ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException)
351 {
352     DBG_ERROR( "OContentHelper::removeProperty: not implemented!" );
353 }
354 // -----------------------------------------------------------------------------
355 // XInitialization
356 void SAL_CALL OContentHelper::initialize( const Sequence< Any >& _aArguments ) throw(Exception, RuntimeException)
357 {
358     const Any* pBegin = _aArguments.getConstArray();
359     const Any* pEnd = pBegin + _aArguments.getLength();
360     PropertyValue aValue;;
361     for(;pBegin != pEnd;++pBegin)
362     {
363         *pBegin >>= aValue;
364         if ( aValue.Name.equalsAscii("Parent") )
365         {
366             m_xParentContainer.set(aValue.Value,UNO_QUERY);
367         }
368         else if ( aValue.Name.equalsAscii(PROPERTY_NAME) )
369         {
370             aValue.Value >>= m_pImpl->m_aProps.aTitle;
371         }
372         else if ( aValue.Name.equalsAscii(PROPERTY_PERSISTENT_NAME) )
373         {
374             aValue.Value >>= m_pImpl->m_aProps.sPersistentName;
375         }
376     }
377 }
378 // -----------------------------------------------------------------------------
379 Sequence< Any > OContentHelper::setPropertyValues(const Sequence< PropertyValue >& rValues,const Reference< XCommandEnvironment >& /*xEnv*/ )
380 {
381     osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
382 
383     Sequence< Any > aRet( rValues.getLength() );
384     Sequence< PropertyChangeEvent > aChanges( rValues.getLength() );
385     sal_Int32 nChanged = 0;
386 
387     PropertyChangeEvent aEvent;
388     aEvent.Source         = static_cast< cppu::OWeakObject * >( this );
389     aEvent.Further        = sal_False;
390     aEvent.PropertyHandle = -1;
391 
392     const PropertyValue* pValues = rValues.getConstArray();
393     sal_Int32 nCount = rValues.getLength();
394 
395     for ( sal_Int32 n = 0; n < nCount; ++n )
396     {
397         const PropertyValue& rValue = pValues[ n ];
398 
399         if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
400         {
401             // Read-only property!
402             aRet[ n ] <<= IllegalAccessException(
403                             rtl::OUString::createFromAscii(
404                                 "Property is read-only!" ),
405                             static_cast< cppu::OWeakObject * >( this ) );
406         }
407         else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
408         {
409             // Read-only property!
410             aRet[ n ] <<= IllegalAccessException(
411                             rtl::OUString::createFromAscii(
412                                 "Property is read-only!" ),
413                             static_cast< cppu::OWeakObject * >( this ) );
414         }
415         else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
416         {
417             // Read-only property!
418             aRet[ n ] <<= IllegalAccessException(
419                             rtl::OUString::createFromAscii(
420                                 "Property is read-only!" ),
421                             static_cast< cppu::OWeakObject * >( this ) );
422         }
423         else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
424         {
425             rtl::OUString aNewValue;
426             if ( rValue.Value >>= aNewValue )
427             {
428                 if ( aNewValue != m_pImpl->m_aProps.aTitle )
429                 {
430                     aEvent.PropertyName = rValue.Name;
431                     aEvent.OldValue     = makeAny( m_pImpl->m_aProps.aTitle );
432 
433                     try
434                     {
435                         impl_rename_throw( aNewValue ,false);
436                         OSL_ENSURE( m_pImpl->m_aProps.aTitle == aNewValue, "OContentHelper::setPropertyValues('Title'): rename did not work!" );
437 
438                         aEvent.NewValue     = makeAny( aNewValue );
439                         aChanges.getArray()[ nChanged ] = aEvent;
440                         nChanged++;
441                     }
442                     catch( const Exception& )
443                     {
444                         OSL_ENSURE( sal_False, "OContentHelper::setPropertyValues('Title'): caught an exception while renaming!" );
445                     }
446                 }
447                 else
448                 {
449                     // Old value equals new value. No error!
450                 }
451             }
452             else
453             {
454                 aRet[ n ] <<= IllegalTypeException(
455                                 rtl::OUString::createFromAscii(
456                                     "Property value has wrong type!" ),
457                                 static_cast< cppu::OWeakObject * >( this ) );
458             }
459         }
460 
461         // @@@ Process other properties supported directly.
462 #if 0
463         else if ( rValue.Name.equalsAsciiL(
464                         RTL_CONSTASCII_STRINGPARAM( "xxxxxx" ) ) )
465         {
466         }
467 #endif
468         else
469         {
470             aRet[ n ] <<= Exception(
471                             rtl::OUString::createFromAscii(
472                                 "No property set for storing the value!" ),
473                             static_cast< cppu::OWeakObject * >( this ) );
474         }
475     }
476 
477     if ( nChanged > 0 )
478     {
479         // @@@ Save changes.
480 //      storeData();
481 
482         notifyDataSourceModified();
483         aGuard.clear();
484         aChanges.realloc( nChanged );
485         notifyPropertiesChange( aChanges );
486     }
487 
488     return aRet;
489 }
490 // -----------------------------------------------------------------------------
491 //=========================================================================
492 // static
493 Reference< XRow > OContentHelper::getPropertyValues( const Sequence< Property >& rProperties)
494 {
495     // Note: Empty sequence means "get values of all supported properties".
496 
497     rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( m_aContext.getLegacyServiceFactory() );
498 
499     sal_Int32 nCount = rProperties.getLength();
500     if ( nCount )
501     {
502         const Property* pProps = rProperties.getConstArray();
503         for ( sal_Int32 n = 0; n < nCount; ++n )
504         {
505             const Property& rProp = pProps[ n ];
506 
507             // Process Core properties.
508 
509             if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
510             {
511                 xRow->appendString ( rProp, getContentType() );
512             }
513             else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
514             {
515                 xRow->appendString ( rProp, m_pImpl->m_aProps.aTitle );
516             }
517             else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
518             {
519                 xRow->appendBoolean( rProp, m_pImpl->m_aProps.bIsDocument );
520             }
521             else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
522             {
523                 xRow->appendBoolean( rProp, m_pImpl->m_aProps.bIsFolder );
524             }
525             else
526                 xRow->appendVoid(rProp);
527 
528             // @@@ Process other properties supported directly.
529 #if 0
530             else if ( rProp.Name.equalsAsciiL(
531                     RTL_CONSTASCII_STRINGPARAM( "xxxxxx" ) ) )
532             {
533             }
534 #endif
535         }
536     }
537     else
538     {
539         // Append all Core Properties.
540         xRow->appendString (
541             Property( rtl::OUString::createFromAscii( "ContentType" ),
542                       -1,
543                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
544                       PropertyAttribute::BOUND
545                         | PropertyAttribute::READONLY ),
546             getContentType() );
547         xRow->appendString (
548             Property( rtl::OUString::createFromAscii( "Title" ),
549                       -1,
550                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
551                       PropertyAttribute::BOUND ),
552             m_pImpl->m_aProps.aTitle );
553         xRow->appendBoolean(
554             Property( rtl::OUString::createFromAscii( "IsDocument" ),
555                       -1,
556                       getCppuBooleanType(),
557                       PropertyAttribute::BOUND
558                         | PropertyAttribute::READONLY ),
559             m_pImpl->m_aProps.bIsDocument );
560         xRow->appendBoolean(
561             Property( rtl::OUString::createFromAscii( "IsFolder" ),
562                       -1,
563                       getCppuBooleanType(),
564                       PropertyAttribute::BOUND
565                         | PropertyAttribute::READONLY ),
566             m_pImpl->m_aProps.bIsFolder );
567 
568         // @@@ Append other properties supported directly.
569     }
570 
571     return Reference< XRow >( xRow.get() );
572 }
573 // -----------------------------------------------------------------------------
574 // -----------------------------------------------------------------------------
575 void OContentHelper::notifyPropertiesChange( const Sequence< PropertyChangeEvent >& evt ) const
576 {
577 
578     sal_Int32 nCount = evt.getLength();
579     if ( nCount )
580     {
581         // First, notify listeners interested in changes of every property.
582         OInterfaceContainerHelper* pAllPropsContainer = m_aPropertyChangeListeners.getContainer( ::rtl::OUString() );
583         if ( pAllPropsContainer )
584         {
585             OInterfaceIteratorHelper aIter( *pAllPropsContainer );
586             while ( aIter.hasMoreElements() )
587             {
588                 // Propagate event.
589                 Reference< XPropertiesChangeListener > xListener( aIter.next(), UNO_QUERY );
590                 if ( xListener.is() )
591                     xListener->propertiesChange( evt );
592             }
593         }
594 
595         typedef Sequence< PropertyChangeEvent > PropertyEventSequence;
596         typedef ::std::map< XPropertiesChangeListener*, PropertyEventSequence* > PropertiesEventListenerMap;
597         PropertiesEventListenerMap aListeners;
598 
599 
600         const PropertyChangeEvent* propertyChangeEvent = evt.getConstArray();
601 
602         for ( sal_Int32 n = 0; n < nCount; ++n, ++propertyChangeEvent )
603         {
604             const PropertyChangeEvent& rEvent = *propertyChangeEvent;
605             const ::rtl::OUString& rName = rEvent.PropertyName;
606 
607             OInterfaceContainerHelper* pPropsContainer = m_aPropertyChangeListeners.getContainer( rName );
608             if ( pPropsContainer )
609             {
610                 OInterfaceIteratorHelper aIter( *pPropsContainer );
611                 while ( aIter.hasMoreElements() )
612                 {
613                     PropertyEventSequence* propertyEvents = NULL;
614 
615                     XPropertiesChangeListener* pListener = static_cast< XPropertiesChangeListener * >( aIter.next() );
616                     PropertiesEventListenerMap::iterator it = aListeners.find( pListener );
617                     if ( it == aListeners.end() )
618                     {
619                         // Not in map - create and insert new entry.
620                         propertyEvents = new PropertyEventSequence( nCount );
621                         aListeners[ pListener ] = propertyEvents;
622                     }
623                     else
624                         propertyEvents = (*it).second;
625 
626                     if ( propertyEvents )
627                         (*propertyEvents)[n] = rEvent;
628                 }
629             }
630         }
631 
632         // Notify listeners.
633         PropertiesEventListenerMap::iterator it = aListeners.begin();
634         while ( !aListeners.empty() )
635         {
636             XPropertiesChangeListener* pListener =
637                     static_cast< XPropertiesChangeListener * >( (*it).first );
638             PropertyEventSequence* pSeq = (*it).second;
639 
640             // Remove current element.
641             aListeners.erase( it );
642 
643             // Propagate event.
644             pListener->propertiesChange( *pSeq );
645 
646             delete pSeq;
647 
648             it = aListeners.begin();
649         }
650     }
651 }
652 // -----------------------------------------------------------------------------
653 // com::sun::star::lang::XUnoTunnel
654 //------------------------------------------------------------------
655 sal_Int64 OContentHelper::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
656 {
657     if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
658         return reinterpret_cast<sal_Int64>(this);
659 
660     return 0;
661 }
662 
663 // -----------------------------------------------------------------------------
664 OContentHelper* OContentHelper::getImplementation( const Reference< XInterface >& _rxComponent )
665 {
666     OContentHelper* pContent( NULL );
667 
668     Reference< XUnoTunnel > xUnoTunnel( _rxComponent, UNO_QUERY );
669     if ( xUnoTunnel.is() )
670         pContent = reinterpret_cast< OContentHelper* >( xUnoTunnel->getSomething( getUnoTunnelImplementationId() ) );
671 
672     return pContent;
673 }
674 
675 // -----------------------------------------------------------------------------
676 Reference< XInterface > SAL_CALL OContentHelper::getParent(  ) throw (RuntimeException)
677 {
678     ::osl::MutexGuard aGuard(m_aMutex);
679     return m_xParentContainer;
680 }
681 // -----------------------------------------------------------------------------
682 void SAL_CALL OContentHelper::setParent( const Reference< XInterface >& _xParent ) throw (NoSupportException, RuntimeException)
683 {
684     ::osl::MutexGuard aGuard(m_aMutex);
685     m_xParentContainer = _xParent;
686 }
687 
688 // -----------------------------------------------------------------------------
689 void OContentHelper::impl_rename_throw(const ::rtl::OUString& _sNewName,bool _bNotify )
690 {
691     osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
692     if ( _sNewName.equals( m_pImpl->m_aProps.aTitle ) )
693         return;
694     try
695     {
696         Sequence< PropertyChangeEvent > aChanges( 1 );
697 
698         aChanges[0].Source          = static_cast< cppu::OWeakObject * >( this );
699         aChanges[0].Further         = sal_False;
700         aChanges[0].PropertyName    = PROPERTY_NAME;
701         aChanges[0].PropertyHandle  = PROPERTY_ID_NAME;
702         aChanges[0].OldValue        <<= m_pImpl->m_aProps.aTitle;
703         aChanges[0].NewValue        <<= _sNewName;
704 
705         aGuard.clear();
706 
707         m_pImpl->m_aProps.aTitle = _sNewName;
708         if ( _bNotify )
709             notifyPropertiesChange( aChanges );
710         notifyDataSourceModified();
711     }
712     catch(const PropertyVetoException&)
713     {
714         throw ElementExistException(_sNewName,*this);
715     }
716 }
717 // -----------------------------------------------------------------------------
718 void SAL_CALL OContentHelper::rename( const ::rtl::OUString& newName ) throw (SQLException, ElementExistException, RuntimeException)
719 {
720 
721     impl_rename_throw(newName);
722     //Reference<XNameContainer> xNameCont(m_xParentContainer,UNO_QUERY);
723     //if ( xNameCont.is() )
724     //{
725     //  if ( xNameCont->hasByName(newName) )
726     //      throw ElementExistException(newName,*this);
727 
728     //  try
729     //  {
730     //      if ( xNameCont->hasByName(m_pImpl->m_aProps.aTitle) )
731     //          xNameCont->removeByName(m_pImpl->m_aProps.aTitle);
732 
733     //      m_pImpl->m_aProps.aTitle = newName;
734     //      xNameCont->insertByName(m_pImpl->m_aProps.aTitle,makeAny(Reference<XContent>(*this,UNO_QUERY)));
735     //      notifyDataSourceModified();
736     //  }
737     //  catch(IllegalArgumentException)
738     //  {
739     //      throw SQLException();
740     //  }
741     //  catch(NoSuchElementException)
742     //  {
743     //      throw SQLException();
744     //  }
745     //  catch(WrappedTargetException)
746     //  {
747     //      throw SQLException();
748     //  }
749     //}
750     //else
751     //  m_pImpl->m_aProps.aTitle = newName;
752 
753 }
754 // -----------------------------------------------------------------------------
755 void OContentHelper::notifyDataSourceModified()
756 {
757     ::dbaccess::notifyDataSourceModified(m_xParentContainer,sal_True);
758 }
759 //........................................................................
760 }   // namespace dbaccess
761 //........................................................................
762 
763