1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_dbaccess.hxx" 26 27 #include "documentevents.hxx" 28 29 /** === begin UNO includes === **/ 30 #include <com/sun/star/beans/PropertyValue.hpp> 31 /** === end UNO includes === **/ 32 33 #include <comphelper/namedvaluecollection.hxx> 34 35 #include <algorithm> 36 #include <functional> 37 38 //........................................................................ 39 namespace dbaccess 40 { 41 //........................................................................ 42 43 /** === begin UNO using === **/ 44 using ::com::sun::star::uno::Reference; 45 using ::com::sun::star::uno::XInterface; 46 using ::com::sun::star::uno::UNO_QUERY; 47 using ::com::sun::star::uno::UNO_QUERY_THROW; 48 using ::com::sun::star::uno::UNO_SET_THROW; 49 using ::com::sun::star::uno::Exception; 50 using ::com::sun::star::uno::RuntimeException; 51 using ::com::sun::star::uno::Any; 52 using ::com::sun::star::uno::makeAny; 53 using ::com::sun::star::beans::PropertyValue; 54 using ::com::sun::star::container::NoSuchElementException; 55 using ::com::sun::star::lang::WrappedTargetException; 56 using ::com::sun::star::lang::IllegalArgumentException; 57 using ::com::sun::star::uno::Sequence; 58 using ::com::sun::star::uno::Type; 59 /** === end UNO using === **/ 60 61 //==================================================================== 62 //= DocumentEvents_Data 63 //==================================================================== 64 struct DocumentEvents_Data : public ::boost::noncopyable 65 { 66 ::cppu::OWeakObject& rParent; 67 ::osl::Mutex& rMutex; 68 DocumentEventsData& rEventsData; 69 DocumentEvents_Datadbaccess::DocumentEvents_Data70 DocumentEvents_Data( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, DocumentEventsData& _rEventsData ) 71 :rParent( _rParent ) 72 ,rMutex( _rMutex ) 73 ,rEventsData( _rEventsData ) 74 { 75 } 76 }; 77 78 //==================================================================== 79 //= helper 80 //==================================================================== 81 struct DocumentEventData 82 { 83 const sal_Char* pAsciiEventName; 84 bool bNeedsSyncNotify; 85 }; 86 87 //-------------------------------------------------------------------- 88 namespace 89 { lcl_getDocumentEventData()90 static const DocumentEventData* lcl_getDocumentEventData() 91 { 92 static const DocumentEventData s_aData[] = { 93 { "OnCreate", true }, 94 { "OnLoadFinished", true }, 95 { "OnNew", false }, // compatibility, see http://www.openoffice.org/issues/show_bug.cgi?id=46484 96 { "OnLoad", false }, // compatibility, see http://www.openoffice.org/issues/show_bug.cgi?id=46484 97 { "OnSaveAs", true }, 98 { "OnSaveAsDone", false }, 99 { "OnSaveAsFailed", false }, 100 { "OnSave", true }, 101 { "OnSaveDone", false }, 102 { "OnSaveFailed", false }, 103 { "OnSaveTo", true }, 104 { "OnSaveToDone", false }, 105 { "OnSaveToFailed", false }, 106 { "OnPrepareUnload", true }, 107 { "OnUnload", true }, 108 { "OnFocus", false }, 109 { "OnUnfocus", false }, 110 { "OnModifyChanged", false }, 111 { "OnViewCreated", false }, 112 { "OnPrepareViewClosing", true }, 113 { "OnViewClosed", false }, 114 { "OnTitleChanged", false }, 115 { "OnSubComponentOpened", false }, 116 { "OnSubComponentClosed", false }, 117 { NULL, false } 118 }; 119 return s_aData; 120 } 121 } 122 123 //==================================================================== 124 //= DocumentEvents 125 //==================================================================== 126 //-------------------------------------------------------------------- DocumentEvents(::cppu::OWeakObject & _rParent,::osl::Mutex & _rMutex,DocumentEventsData & _rEventsData)127 DocumentEvents::DocumentEvents( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, DocumentEventsData& _rEventsData ) 128 :m_pData( new DocumentEvents_Data( _rParent, _rMutex, _rEventsData ) ) 129 { 130 const DocumentEventData* pEventData = lcl_getDocumentEventData(); 131 while ( pEventData->pAsciiEventName ) 132 { 133 ::rtl::OUString sEventName = ::rtl::OUString::createFromAscii( pEventData->pAsciiEventName ); 134 DocumentEventsData::iterator existingPos = m_pData->rEventsData.find( sEventName ); 135 if ( existingPos == m_pData->rEventsData.end() ) 136 m_pData->rEventsData[ sEventName ] = Sequence< PropertyValue >(); 137 ++pEventData; 138 } 139 } 140 141 //-------------------------------------------------------------------- ~DocumentEvents()142 DocumentEvents::~DocumentEvents() 143 { 144 } 145 146 //-------------------------------------------------------------------- acquire()147 void SAL_CALL DocumentEvents::acquire() throw() 148 { 149 m_pData->rParent.acquire(); 150 } 151 152 //-------------------------------------------------------------------- release()153 void SAL_CALL DocumentEvents::release() throw() 154 { 155 m_pData->rParent.release(); 156 } 157 158 //-------------------------------------------------------------------- needsSynchronousNotification(const::rtl::OUString & _rEventName)159 bool DocumentEvents::needsSynchronousNotification( const ::rtl::OUString& _rEventName ) 160 { 161 const DocumentEventData* pEventData = lcl_getDocumentEventData(); 162 while ( pEventData->pAsciiEventName ) 163 { 164 if ( _rEventName.compareToAscii( pEventData->pAsciiEventName ) == 0 ) 165 return pEventData->bNeedsSyncNotify; 166 ++pEventData; 167 } 168 169 // this is an unknown event ... assume async notification 170 return false; 171 } 172 173 //-------------------------------------------------------------------- replaceByName(const::rtl::OUString & _Name,const Any & _Element)174 void SAL_CALL DocumentEvents::replaceByName( const ::rtl::OUString& _Name, const Any& _Element ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) 175 { 176 ::osl::MutexGuard aGuard( m_pData->rMutex ); 177 178 DocumentEventsData::iterator elementPos = m_pData->rEventsData.find( _Name ); 179 if ( elementPos == m_pData->rEventsData.end() ) 180 throw NoSuchElementException( _Name, *this ); 181 182 Sequence< PropertyValue > aEventDescriptor; 183 if ( _Element.hasValue() && !( _Element >>= aEventDescriptor ) ) 184 throw IllegalArgumentException( _Element.getValueTypeName(), *this, 2 ); 185 186 // Weird enough, the event assignment UI has (well: had) the idea of using an empty "EventType"/"Script" 187 // to indicate the event descriptor should be reset, instead of just passing an empty event descriptor. 188 ::comphelper::NamedValueCollection aCheck( aEventDescriptor ); 189 if ( aCheck.has( "EventType" ) ) 190 { 191 ::rtl::OUString sEventType = aCheck.getOrDefault( "EventType", ::rtl::OUString() ); 192 OSL_ENSURE( sEventType.getLength(), "DocumentEvents::replaceByName: doing a reset via an empty EventType is weird!" ); 193 if ( !sEventType.getLength() ) 194 aEventDescriptor.realloc( 0 ); 195 } 196 if ( aCheck.has( "Script" ) ) 197 { 198 ::rtl::OUString sScript = aCheck.getOrDefault( "Script", ::rtl::OUString() ); 199 OSL_ENSURE( sScript.getLength(), "DocumentEvents::replaceByName: doing a reset via an empty Script is weird!" ); 200 if ( !sScript.getLength() ) 201 aEventDescriptor.realloc( 0 ); 202 } 203 204 elementPos->second = aEventDescriptor; 205 } 206 207 //-------------------------------------------------------------------- getByName(const::rtl::OUString & _Name)208 Any SAL_CALL DocumentEvents::getByName( const ::rtl::OUString& _Name ) throw (NoSuchElementException, WrappedTargetException, RuntimeException) 209 { 210 ::osl::MutexGuard aGuard( m_pData->rMutex ); 211 212 DocumentEventsData::const_iterator elementPos = m_pData->rEventsData.find( _Name ); 213 if ( elementPos == m_pData->rEventsData.end() ) 214 throw NoSuchElementException( _Name, *this ); 215 216 Any aReturn; 217 const Sequence< PropertyValue >& rEventDesc( elementPos->second ); 218 if ( rEventDesc.getLength() > 0 ) 219 aReturn <<= rEventDesc; 220 return aReturn; 221 } 222 223 //-------------------------------------------------------------------- getElementNames()224 Sequence< ::rtl::OUString > SAL_CALL DocumentEvents::getElementNames( ) throw (RuntimeException) 225 { 226 ::osl::MutexGuard aGuard( m_pData->rMutex ); 227 228 Sequence< ::rtl::OUString > aNames( m_pData->rEventsData.size() ); 229 ::std::transform( 230 m_pData->rEventsData.begin(), 231 m_pData->rEventsData.end(), 232 aNames.getArray(), 233 ::std::select1st< DocumentEventsData::value_type >() 234 ); 235 return aNames; 236 } 237 238 //-------------------------------------------------------------------- hasByName(const::rtl::OUString & _Name)239 ::sal_Bool SAL_CALL DocumentEvents::hasByName( const ::rtl::OUString& _Name ) throw (RuntimeException) 240 { 241 ::osl::MutexGuard aGuard( m_pData->rMutex ); 242 243 return m_pData->rEventsData.find( _Name ) != m_pData->rEventsData.end(); 244 } 245 246 //-------------------------------------------------------------------- getElementType()247 Type SAL_CALL DocumentEvents::getElementType( ) throw (RuntimeException) 248 { 249 return ::cppu::UnoType< Sequence< PropertyValue > >::get(); 250 } 251 252 //-------------------------------------------------------------------- hasElements()253 ::sal_Bool SAL_CALL DocumentEvents::hasElements( ) throw (RuntimeException) 254 { 255 ::osl::MutexGuard aGuard( m_pData->rMutex ); 256 return !m_pData->rEventsData.empty(); 257 } 258 259 260 //........................................................................ 261 } // namespace dbaccess 262 //........................................................................ 263