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