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