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