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_ucb.hxx" 26 27 /************************************************************************** 28 TODO 29 ************************************************************************** 30 31 *************************************************************************/ 32 33 #include <vector> 34 #include <ucbhelper/contentidentifier.hxx> 35 #include "hierarchydatasupplier.hxx" 36 #include "hierarchyprovider.hxx" 37 #include "hierarchycontent.hxx" 38 39 using namespace com::sun::star; 40 using namespace hierarchy_ucp; 41 42 namespace hierarchy_ucp 43 { 44 45 //========================================================================= 46 // 47 // struct ResultListEntry. 48 // 49 //========================================================================= 50 51 struct ResultListEntry 52 { 53 rtl::OUString aId; 54 uno::Reference< ucb::XContentIdentifier > xId; 55 uno::Reference< ucb::XContent > xContent; 56 uno::Reference< sdbc::XRow > xRow; 57 HierarchyEntryData aData; 58 59 ResultListEntry( const HierarchyEntryData& rEntry ) : aData( rEntry ) {} 60 }; 61 62 //========================================================================= 63 // 64 // ResultList. 65 // 66 //========================================================================= 67 68 typedef std::vector< ResultListEntry* > ResultList; 69 70 //========================================================================= 71 // 72 // struct DataSupplier_Impl. 73 // 74 //========================================================================= 75 76 struct DataSupplier_Impl 77 { 78 osl::Mutex m_aMutex; 79 ResultList m_aResults; 80 rtl::Reference< HierarchyContent > m_xContent; 81 uno::Reference< lang::XMultiServiceFactory > m_xSMgr; 82 HierarchyEntry m_aFolder; 83 HierarchyEntry::iterator m_aIterator; 84 sal_Int32 m_nOpenMode; 85 sal_Bool m_bCountFinal; 86 87 DataSupplier_Impl( 88 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 89 const rtl::Reference< HierarchyContent >& rContent, 90 sal_Int32 nOpenMode ) 91 : m_xContent( rContent ), m_xSMgr( rxSMgr ), 92 m_aFolder( rxSMgr, 93 static_cast< HierarchyContentProvider * >( 94 rContent->getProvider().get() ), 95 rContent->getIdentifier()->getContentIdentifier() ), 96 m_nOpenMode( nOpenMode ), m_bCountFinal( sal_False ) {} 97 ~DataSupplier_Impl(); 98 }; 99 100 //========================================================================= 101 DataSupplier_Impl::~DataSupplier_Impl() 102 { 103 ResultList::const_iterator it = m_aResults.begin(); 104 ResultList::const_iterator end = m_aResults.end(); 105 106 while ( it != end ) 107 { 108 delete (*it); 109 it++; 110 } 111 } 112 113 } 114 115 //========================================================================= 116 //========================================================================= 117 // 118 // HierarchyResultSetDataSupplier Implementation. 119 // 120 //========================================================================= 121 //========================================================================= 122 123 HierarchyResultSetDataSupplier::HierarchyResultSetDataSupplier( 124 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 125 const rtl::Reference< HierarchyContent >& rContent, 126 sal_Int32 nOpenMode ) 127 : m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) ) 128 { 129 } 130 131 //========================================================================= 132 // virtual 133 HierarchyResultSetDataSupplier::~HierarchyResultSetDataSupplier() 134 { 135 delete m_pImpl; 136 } 137 138 //========================================================================= 139 // virtual 140 rtl::OUString HierarchyResultSetDataSupplier::queryContentIdentifierString( 141 sal_uInt32 nIndex ) 142 { 143 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 144 145 if ( nIndex < m_pImpl->m_aResults.size() ) 146 { 147 rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId; 148 if ( aId.getLength() ) 149 { 150 // Already cached. 151 return aId; 152 } 153 } 154 155 if ( getResult( nIndex ) ) 156 { 157 rtl::OUString aId 158 = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(); 159 160 if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() ) 161 aId += rtl::OUString::createFromAscii( "/" ); 162 163 aId += m_pImpl->m_aResults[ nIndex ]->aData.getName(); 164 165 m_pImpl->m_aResults[ nIndex ]->aId = aId; 166 return aId; 167 } 168 return rtl::OUString(); 169 } 170 171 //========================================================================= 172 // virtual 173 uno::Reference< ucb::XContentIdentifier > 174 HierarchyResultSetDataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) 175 { 176 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 177 178 if ( nIndex < m_pImpl->m_aResults.size() ) 179 { 180 uno::Reference< ucb::XContentIdentifier > xId 181 = m_pImpl->m_aResults[ nIndex ]->xId; 182 if ( xId.is() ) 183 { 184 // Already cached. 185 return xId; 186 } 187 } 188 189 rtl::OUString aId = queryContentIdentifierString( nIndex ); 190 if ( aId.getLength() ) 191 { 192 uno::Reference< ucb::XContentIdentifier > xId 193 = new ::ucbhelper::ContentIdentifier( aId ); 194 m_pImpl->m_aResults[ nIndex ]->xId = xId; 195 return xId; 196 } 197 return uno::Reference< ucb::XContentIdentifier >(); 198 } 199 200 //========================================================================= 201 // virtual 202 uno::Reference< ucb::XContent > 203 HierarchyResultSetDataSupplier::queryContent( sal_uInt32 nIndex ) 204 { 205 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 206 207 if ( nIndex < m_pImpl->m_aResults.size() ) 208 { 209 uno::Reference< ucb::XContent > xContent 210 = m_pImpl->m_aResults[ nIndex ]->xContent; 211 if ( xContent.is() ) 212 { 213 // Already cached. 214 return xContent; 215 } 216 } 217 218 uno::Reference< ucb::XContentIdentifier > xId 219 = queryContentIdentifier( nIndex ); 220 if ( xId.is() ) 221 { 222 try 223 { 224 uno::Reference< ucb::XContent > xContent 225 = m_pImpl->m_xContent->getProvider()->queryContent( xId ); 226 m_pImpl->m_aResults[ nIndex ]->xContent = xContent; 227 return xContent; 228 229 } 230 catch ( ucb::IllegalIdentifierException const & ) 231 { 232 } 233 } 234 return uno::Reference< ucb::XContent >(); 235 } 236 237 //========================================================================= 238 // virtual 239 sal_Bool HierarchyResultSetDataSupplier::getResult( sal_uInt32 nIndex ) 240 { 241 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 242 243 if ( m_pImpl->m_aResults.size() > nIndex ) 244 { 245 // Result already present. 246 return sal_True; 247 } 248 249 // Result not (yet) present. 250 251 if ( m_pImpl->m_bCountFinal ) 252 return sal_False; 253 254 // Try to obtain result... 255 256 sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); 257 sal_Bool bFound = sal_False; 258 sal_uInt32 nPos = nOldCount; 259 260 while ( m_pImpl->m_aFolder.next( m_pImpl->m_aIterator ) ) 261 { 262 const HierarchyEntryData& rResult = *m_pImpl->m_aIterator; 263 if ( checkResult( rResult ) ) 264 { 265 m_pImpl->m_aResults.push_back( new ResultListEntry( rResult ) ); 266 267 if ( nPos == nIndex ) 268 { 269 // Result obtained. 270 bFound = sal_True; 271 break; 272 } 273 } 274 nPos++; 275 } 276 277 if ( !bFound ) 278 m_pImpl->m_bCountFinal = sal_True; 279 280 rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); 281 if ( xResultSet.is() ) 282 { 283 // Callbacks follow! 284 aGuard.clear(); 285 286 if ( nOldCount < m_pImpl->m_aResults.size() ) 287 xResultSet->rowCountChanged( 288 nOldCount, m_pImpl->m_aResults.size() ); 289 290 if ( m_pImpl->m_bCountFinal ) 291 xResultSet->rowCountFinal(); 292 } 293 294 return bFound; 295 } 296 297 //========================================================================= 298 // virtual 299 sal_uInt32 HierarchyResultSetDataSupplier::totalCount() 300 { 301 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 302 303 if ( m_pImpl->m_bCountFinal ) 304 return m_pImpl->m_aResults.size(); 305 306 sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); 307 308 while ( m_pImpl->m_aFolder.next( m_pImpl->m_aIterator ) ) 309 { 310 const HierarchyEntryData& rResult = *m_pImpl->m_aIterator; 311 if ( checkResult( rResult ) ) 312 m_pImpl->m_aResults.push_back( new ResultListEntry( rResult ) ); 313 } 314 315 m_pImpl->m_bCountFinal = sal_True; 316 317 rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); 318 if ( xResultSet.is() ) 319 { 320 // Callbacks follow! 321 aGuard.clear(); 322 323 if ( nOldCount < m_pImpl->m_aResults.size() ) 324 xResultSet->rowCountChanged( 325 nOldCount, m_pImpl->m_aResults.size() ); 326 327 xResultSet->rowCountFinal(); 328 } 329 330 return m_pImpl->m_aResults.size(); 331 } 332 333 //========================================================================= 334 // virtual 335 sal_uInt32 HierarchyResultSetDataSupplier::currentCount() 336 { 337 return m_pImpl->m_aResults.size(); 338 } 339 340 //========================================================================= 341 // virtual 342 sal_Bool HierarchyResultSetDataSupplier::isCountFinal() 343 { 344 return m_pImpl->m_bCountFinal; 345 } 346 347 //========================================================================= 348 // virtual 349 uno::Reference< sdbc::XRow > 350 HierarchyResultSetDataSupplier::queryPropertyValues( sal_uInt32 nIndex ) 351 { 352 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 353 354 if ( nIndex < m_pImpl->m_aResults.size() ) 355 { 356 uno::Reference< sdbc::XRow > xRow 357 = m_pImpl->m_aResults[ nIndex ]->xRow; 358 if ( xRow.is() ) 359 { 360 // Already cached. 361 return xRow; 362 } 363 } 364 365 if ( getResult( nIndex ) ) 366 { 367 static rtl::OUString aFolderType( 368 rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) ); 369 static rtl::OUString aLinkType( 370 rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ) ); 371 372 HierarchyContentProperties aData( 373 m_pImpl->m_aResults[ nIndex ]->aData ); 374 375 uno::Reference< sdbc::XRow > xRow 376 = HierarchyContent::getPropertyValues( 377 m_pImpl->m_xSMgr, 378 getResultSet()->getProperties(), 379 aData, 380 static_cast< HierarchyContentProvider * >( 381 m_pImpl->m_xContent->getProvider().get() ), 382 queryContentIdentifierString( nIndex ) ); 383 m_pImpl->m_aResults[ nIndex ]->xRow = xRow; 384 return xRow; 385 } 386 387 return uno::Reference< sdbc::XRow >(); 388 } 389 390 //========================================================================= 391 // virtual 392 void HierarchyResultSetDataSupplier::releasePropertyValues( sal_uInt32 nIndex ) 393 { 394 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); 395 396 if ( nIndex < m_pImpl->m_aResults.size() ) 397 m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >(); 398 } 399 400 //========================================================================= 401 // virtual 402 void HierarchyResultSetDataSupplier::close() 403 { 404 } 405 406 //========================================================================= 407 // virtual 408 void HierarchyResultSetDataSupplier::validate() 409 throw( ucb::ResultSetException ) 410 { 411 } 412 413 //========================================================================= 414 sal_Bool HierarchyResultSetDataSupplier::checkResult( 415 const HierarchyEntryData& rResult ) 416 { 417 switch ( m_pImpl->m_nOpenMode ) 418 { 419 case ucb::OpenMode::FOLDERS: 420 if ( rResult.getType() == HierarchyEntryData::LINK ) 421 { 422 // Entry is a link. 423 return sal_False; 424 } 425 break; 426 427 case ucb::OpenMode::DOCUMENTS: 428 if ( rResult.getType() == HierarchyEntryData::FOLDER ) 429 { 430 // Entry is a folder. 431 return sal_False; 432 } 433 break; 434 435 case ucb::OpenMode::ALL: 436 default: 437 break; 438 } 439 440 return sal_True; 441 } 442 443