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 <ucbhelper/providerhelper.hxx>
40 #include "odma_datasupplier.hxx"
41 #include "odma_content.hxx"
42 #include "odma_contentprops.hxx"
43 #include "odma_provider.hxx"
44 #include "odma_lib.hxx"
45 
46 using namespace com::sun::star::beans;
47 using namespace com::sun::star::lang;
48 using namespace com::sun::star::ucb;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::sdbc;
51 
52 using namespace odma;
53 
54 namespace odma
55 {
56 
57 //=========================================================================
58 //
59 // struct ResultListEntry.
60 //
61 //=========================================================================
62 
63 struct ResultListEntry
64 {
65 	::rtl::OUString					    aId;
66 	Reference< XContentIdentifier >     xId;
67 	Reference< XContent > 			    xContent;
68 	Reference< XRow > 				    xRow;
69 	::rtl::Reference<ContentProperties>	rData;
70 
71 	ResultListEntry( const ::rtl::Reference<ContentProperties>& rEntry ) : rData( rEntry ) {}
72 };
73 
74 //=========================================================================
75 //
76 // ResultList.
77 //
78 //=========================================================================
79 
80 typedef std::vector< ResultListEntry* > ResultList;
81 
82 //=========================================================================
83 //
84 // struct DataSupplier_Impl.
85 //
86 //=========================================================================
87 
88 struct DataSupplier_Impl
89 {
90 	osl::Mutex					      m_aMutex;
91 	ResultList					      m_aResults;
92 	rtl::Reference< Content >     	  m_xContent;
93 	Reference< XMultiServiceFactory > m_xSMgr;
94 // @@@ The data source and an iterator for it
95 //	Entry 		 	      	  		  m_aFolder;
96 //	Entry::iterator 		  		  m_aIterator;
97   	sal_Int32					      m_nOpenMode;
98   	sal_Bool					      m_bCountFinal;
99 
100 	DataSupplier_Impl( const Reference< XMultiServiceFactory >& rxSMgr,
101 	                   const rtl::Reference< Content >& rContent,
102 					   sal_Int32 nOpenMode )
103 	: m_xContent( rContent ), m_xSMgr( rxSMgr ),
104 //	  m_aFolder( rxSMgr, rContent->getIdentifier()->getContentIdentifier() ),
105 	  m_nOpenMode( nOpenMode ), m_bCountFinal( sal_False ) {}
106 	~DataSupplier_Impl();
107 };
108 
109 //=========================================================================
110 DataSupplier_Impl::~DataSupplier_Impl()
111 {
112 	ResultList::const_iterator it  = m_aResults.begin();
113 	ResultList::const_iterator end = m_aResults.end();
114 
115 	while ( it != end )
116 	{
117 		delete (*it);
118 		it++;
119 	}
120 }
121 
122 }
123 
124 //=========================================================================
125 //=========================================================================
126 //
127 // DataSupplier Implementation.
128 //
129 //=========================================================================
130 //=========================================================================
131 
132 DataSupplier::DataSupplier( const Reference<XMultiServiceFactory >& rxSMgr,
133 						   const rtl::Reference< ::odma::Content >& rContent,
134 							sal_Int32 nOpenMode )
135 : m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) )
136 {
137 }
138 
139 //=========================================================================
140 // virtual
141 DataSupplier::~DataSupplier()
142 {
143 	delete m_pImpl;
144 }
145 
146 //=========================================================================
147 // virtual
148 ::rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
149 {
150 	osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
151 
152 	if ( nIndex < m_pImpl->m_aResults.size() )
153 	{
154 		::rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId;
155 		if ( aId.getLength() )
156 		{
157 			// Already cached.
158 			return aId;
159 		}
160 	}
161 
162 	if ( getResult( nIndex ) )
163 	{
164 		::rtl::OUString aId
165 			= m_pImpl->m_xContent->getIdentifier()->getContentIdentifier();
166 
167 		aId += m_pImpl->m_aResults[ nIndex ]->rData->m_sTitle;
168 
169 		m_pImpl->m_aResults[ nIndex ]->aId = aId;
170 		return aId;
171 	}
172 	return ::rtl::OUString();
173 }
174 
175 //=========================================================================
176 // virtual
177 Reference< XContentIdentifier > DataSupplier::queryContentIdentifier(
178 														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 		Reference< 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 		Reference< XContentIdentifier > xId
197             = new ucbhelper::ContentIdentifier( aId );
198 		m_pImpl->m_aResults[ nIndex ]->xId = xId;
199 		return xId;
200 	}
201 	return Reference< XContentIdentifier >();
202 }
203 
204 //=========================================================================
205 // virtual
206 Reference< XContent > DataSupplier::queryContent( sal_uInt32 nIndex )
207 {
208 	osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
209 
210 	if ( nIndex < m_pImpl->m_aResults.size() )
211 	{
212 		Reference< XContent > xContent
213 								= m_pImpl->m_aResults[ nIndex ]->xContent;
214 		if ( xContent.is() )
215 		{
216 			// Already cached.
217 			return xContent;
218 		}
219 	}
220 
221 	Reference< XContentIdentifier > xId = queryContentIdentifier( nIndex );
222 	if ( xId.is() )
223 	{
224 		try
225 		{
226 			Reference< XContent > xContent
227 				= m_pImpl->m_xContent->getProvider()->queryContent( xId );
228 			m_pImpl->m_aResults[ nIndex ]->xContent = xContent;
229 			return xContent;
230 
231 		}
232 		catch ( IllegalIdentifierException& )
233 		{
234 		}
235 	}
236 	return Reference< XContent >();
237 }
238 
239 //=========================================================================
240 // virtual
241 sal_Bool DataSupplier::getResult( sal_uInt32 nIndex )
242 {
243 	osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
244 
245 	if ( m_pImpl->m_aResults.size() > nIndex )
246 	{
247 		// Result already present.
248 		return sal_True;
249 	}
250 
251 	// Result not (yet) present.
252 
253 	if ( m_pImpl->m_bCountFinal )
254 		return sal_False;
255 
256 	// Try to obtain result...
257 
258 	sal_uInt32 nOldCount = m_pImpl->m_aResults.size();
259 	sal_Bool bFound = sal_False;
260 //	sal_uInt32 nPos = nOldCount;
261 
262 	// @@@ Obtain data and put it into result list...
263 /*
264 	while ( m_pImpl->m_aFolder.next( m_pImpl->m_aIterator ) )
265 	{
266 		m_pImpl->m_aResults.push_back(
267 						new ResultListEntry( *m_pImpl->m_aIterator ) );
268 
269 		if ( nPos == nIndex )
270 		{
271 			// Result obtained.
272 			bFound = sal_True;
273 			break;
274 		}
275 
276 		nPos++;
277 	}
278 */
279 	// now query for all documents in the DMS
280 	OSL_ENSURE(ContentProvider::getHandle(),"No Handle!");
281 	sal_Char* pQueryId		= new sal_Char[ODM_QUERYID_MAX];
282 	sal_Char* lpszDMSList	= new sal_Char[ODM_DMSID_MAX];
283 
284 	ODMSTATUS odm = NODMGetDMS(ODMA_ODMA_REGNAME, lpszDMSList);
285 	lpszDMSList[strlen(lpszDMSList)+1] = '\0';
286 
287 	::rtl::OString sQuery("SELECT ODM_DOCID, ODM_NAME");
288 
289 	DWORD dwFlags = ODM_SPECIFIC;
290 	odm = NODMQueryExecute(ContentProvider::getHandle(), sQuery,dwFlags, lpszDMSList, pQueryId );
291 	if(odm != ODM_SUCCESS)
292 		return sal_False;
293 
294 	sal_uInt16 nCount		= 10;
295 	sal_uInt16 nMaxCount	= 10;
296 	sal_Char* lpszDocId		= new sal_Char[ODM_DOCID_MAX * nMaxCount];
297 	sal_Char* lpszDocName	= new sal_Char[ODM_NAME_MAX * nMaxCount];
298 
299 
300 	::rtl::OUString sContentType(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE));
301 	sal_uInt32 nCurrentCount = 0;
302 	do
303 	{
304 		if(nCount >= nMaxCount)
305 		{
306 			nCount = nMaxCount;
307 			odm = NODMQueryGetResults(ContentProvider::getHandle(), pQueryId,lpszDocId, lpszDocName, ODM_NAME_MAX, (WORD*)&nCount);
308 			nCurrentCount += nCount;
309 		}
310 		if(odm == ODM_SUCCESS && nIndex < nCurrentCount)
311 		{
312 			bFound = sal_True;
313 			for(sal_uInt16 i = 0; i < nCount; ++i)
314 			{
315 				::rtl::Reference<ContentProperties> rProps = new ContentProperties();
316 				rProps->m_sDocumentId	= ::rtl::OString(&lpszDocId[ODM_DOCID_MAX*i]);
317 				rProps->m_sContentType	= sContentType;
318 				m_pImpl->m_xContent->getContentProvider()->append(rProps);
319 				m_pImpl->m_aResults.push_back( new ResultListEntry(rProps));
320 			}
321 		}
322 	}
323 	while(nCount > nMaxCount);
324 
325 
326 	// now close the query
327 	odm = NODMQueryClose(ContentProvider::getHandle(), pQueryId);
328 
329 	delete [] lpszDMSList;
330 	delete [] pQueryId;
331 	delete [] lpszDocId;
332 	delete [] lpszDocName;
333 
334 	if ( !bFound )
335 		m_pImpl->m_bCountFinal = sal_True;
336 
337 	rtl::Reference< ucbhelper::ResultSet > xResultSet = getResultSet();
338 	if ( xResultSet.is() )
339 	{
340 		// Callbacks follow!
341 		aGuard.clear();
342 
343 		if ( nOldCount < m_pImpl->m_aResults.size() )
344 			xResultSet->rowCountChanged(
345 									nOldCount, m_pImpl->m_aResults.size() );
346 
347 		if ( m_pImpl->m_bCountFinal )
348 			xResultSet->rowCountFinal();
349 	}
350 
351 	return bFound;
352 }
353 
354 //=========================================================================
355 // virtual
356 sal_uInt32 DataSupplier::totalCount()
357 {
358 	osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
359 
360 	if ( m_pImpl->m_bCountFinal )
361 		return m_pImpl->m_aResults.size();
362 
363 	sal_uInt32 nOldCount = m_pImpl->m_aResults.size();
364 
365 	// @@@ Obtain data and put it into result list...
366 /*
367 	while ( m_pImpl->m_aFolder.next( m_pImpl->m_aIterator ) )
368 		m_pImpl->m_aResults.push_back(
369 						new ResultListEntry( *m_pImpl->m_aIterator ) );
370 */
371 	m_pImpl->m_bCountFinal = sal_True;
372 
373 	rtl::Reference< ucbhelper::ResultSet > xResultSet = getResultSet();
374 	if ( xResultSet.is() )
375 	{
376 		// Callbacks follow!
377 		aGuard.clear();
378 
379 		if ( nOldCount < m_pImpl->m_aResults.size() )
380 			xResultSet->rowCountChanged(
381 									nOldCount, m_pImpl->m_aResults.size() );
382 
383 		xResultSet->rowCountFinal();
384 	}
385 
386 	return m_pImpl->m_aResults.size();
387 }
388 
389 //=========================================================================
390 // virtual
391 sal_uInt32 DataSupplier::currentCount()
392 {
393 	return m_pImpl->m_aResults.size();
394 }
395 
396 //=========================================================================
397 // virtual
398 sal_Bool DataSupplier::isCountFinal()
399 {
400 	return m_pImpl->m_bCountFinal;
401 }
402 
403 //=========================================================================
404 // virtual
405 Reference< XRow > DataSupplier::queryPropertyValues( sal_uInt32 nIndex  )
406 {
407 	osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
408 
409 	if ( nIndex < m_pImpl->m_aResults.size() )
410 	{
411 		Reference< XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
412 		if ( xRow.is() )
413 		{
414 			// Already cached.
415 			return xRow;
416 		}
417 	}
418 
419 	if ( getResult( nIndex ) )
420 	{
421 		Reference< XRow > xRow = Content::getPropertyValues(
422 									m_pImpl->m_xSMgr,
423 									getResultSet()->getProperties(),
424 									m_pImpl->m_aResults[ nIndex ]->rData,
425 									m_pImpl->m_xContent->getProvider(),
426 									queryContentIdentifierString( nIndex ) );
427 		m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
428 		return xRow;
429 	}
430 
431 	return Reference< XRow >();
432 }
433 
434 //=========================================================================
435 // virtual
436 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
437 {
438 	osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
439 
440 	if ( nIndex < m_pImpl->m_aResults.size() )
441 		m_pImpl->m_aResults[ nIndex ]->xRow = Reference< XRow >();
442 }
443 
444 //=========================================================================
445 // virtual
446 void DataSupplier::close()
447 {
448 }
449 
450 //=========================================================================
451 // virtual
452 void DataSupplier::validate()
453 	throw( ResultSetException )
454 {
455 }
456