merge the formfield patch from ooo-build
[ooovba.git] / connectivity / source / drivers / mozab / mozillasrc / MQueryHelper.cxx
blob08830ee3a1f7310c5226b7b7788cd75a6bbe2e94
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: MQueryHelper.cxx,v $
10 * $Revision: 1.17 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
34 #include "MQueryHelper.hxx"
35 #include "MTypeConverter.hxx"
36 #include "MConnection.hxx"
37 #include "MNSDeclares.hxx"
38 #include "MLdapAttributeMap.hxx"
40 #include <connectivity/dbexception.hxx>
42 #include "resource/mozab_res.hrc"
44 using namespace connectivity::mozab;
47 NS_IMPL_THREADSAFE_ISUPPORTS1(connectivity::mozab::MQueryHelper,nsIAbDirectoryQueryResultListener)
50 // class MQueryHelperResultEntry
54 MQueryHelperResultEntry::MQueryHelperResultEntry()
56 m_Card = NULL;
57 m_RowStates = 0;
60 MQueryHelperResultEntry::~MQueryHelperResultEntry()
62 OSL_TRACE("IN MQueryHelperResultEntry::~MQueryHelperResultEntry()\n");
63 OSL_TRACE("OUT MQueryHelperResultEntry::~MQueryHelperResultEntry()\n");
66 void
67 MQueryHelperResultEntry::setCard(nsIAbCard *card)
69 m_Card = card;
71 nsIAbCard *
72 MQueryHelperResultEntry::getCard()
74 return m_Card;
76 void MQueryHelperResultEntry::insert( const rtl::OString &key, rtl::OUString &value )
78 m_Fields[ key ] = value;
81 rtl::OUString MQueryHelperResultEntry::getValue( const rtl::OString &key ) const
83 FieldMap::const_iterator iter = m_Fields.find( key );
84 if ( iter == m_Fields.end() )
86 return rtl::OUString();
88 else
90 return iter->second;
94 void MQueryHelperResultEntry::setValue( const rtl::OString &key, const rtl::OUString & rValue)
96 m_Fields[ key ] = rValue;
99 // class MQueryHelper
101 MQueryHelper::MQueryHelper()
102 :m_nIndex( 0 )
103 ,m_bHasMore( sal_True )
104 ,m_bAtEnd( sal_False )
105 ,m_bErrorCondition( sal_False )
106 ,m_bQueryComplete( sal_False )
107 ,mRefCnt( 0 ) // NSISUPPORTS - Initialize RefCnt to 0
109 m_aResults.clear();
110 #if OSL_DEBUG_LEVEL > 0
111 m_oThreadID = osl_getThreadIdentifier(NULL);
112 #endif
115 MQueryHelper::~MQueryHelper()
117 OSL_TRACE("IN MQueryHelper::~MQueryHelper()\n");
118 clear_results();
119 OSL_TRACE("OUT MQueryHelper::~MQueryHelper()\n");
122 void
123 MQueryHelper::append(MQueryHelperResultEntry* resEnt )
125 if ( resEnt != NULL ) {
126 m_aResults.push_back( resEnt );
127 m_bAtEnd = sal_False;
131 void
132 MQueryHelper::clear_results()
134 resultsArray::iterator iter = m_aResults.begin();
135 while ( iter != m_aResults.end() ) {
136 delete (*iter);
137 ++iter;
139 m_aResults.clear();
142 void
143 MQueryHelper::rewind()
145 m_nIndex = 0;
148 void
149 MQueryHelper::reset()
151 m_nIndex = 0;
152 m_bHasMore = sal_True;
153 m_bQueryComplete = sal_False;
154 m_bAtEnd = sal_False;
155 m_bErrorCondition = sal_False;
156 clear_results();
159 void
160 MQueryHelper::clearResultOrComplete()
162 // Don't use a Mutex, it should be called by a method already holding it.
163 OSL_TRACE("In/Out : clearResultOrComplete()");
164 m_aCondition.reset();
167 void
168 MQueryHelper::notifyResultOrComplete()
170 OSL_TRACE("In/Out : notifyResultOrComplete()");
171 m_aCondition.set();
174 sal_Bool
175 MQueryHelper::waitForResultOrComplete( )
177 TimeValue timeValue = { 1, 0 }; // 20 Seconds 0 NanoSecond timeout
178 sal_Int32 times=0;
179 osl::Condition::Result rv = ::osl::Condition::result_ok;
181 OSL_TRACE("In : waitForResultOrComplete()");
182 // Can't hold mutex or condition would never get set...
183 while( (m_aCondition.check() == sal_False || rv == ::osl::Condition::result_error) && times < 20) {
184 rv = m_aCondition.wait( &timeValue );
185 times ++;
187 if (times >= 20 && rv == ::osl::Condition::result_timeout ) {
188 OSL_TRACE("waitForResultOrComplete() : Timeout!");
189 m_aError.setResId( STR_TIMEOUT_WAITING );
190 return sal_False;
193 if ( isError() ) {
194 OSL_TRACE("waitForResultOrComplete() : Error returned!");
195 m_aError.setResId( STR_ERR_EXECUTING_QUERY );
196 return sal_False;
198 m_aError.reset();
199 OSL_TRACE(" Out : waitForResultOrComplete()");
200 return sal_True;
204 MQueryHelperResultEntry*
205 MQueryHelper::next( )
207 MQueryHelperResultEntry* result;
208 sal_Int32 index;
210 m_aMutex.acquire();
211 index = m_nIndex;
212 m_aMutex.release();
214 result = getByIndex( m_nIndex + 1) ; // Add 1 as Row is numbered from 1 to N
216 if ( result ) {
217 m_aMutex.acquire();
218 m_nIndex++;
219 m_aMutex.release();
222 return( result );
225 MQueryHelperResultEntry*
226 MQueryHelper::getByIndex( sal_uInt32 nRow )
228 // Row numbers are from 1 to N, need to ensure this, and then
229 // substract 1
230 if ( nRow < 1 ) {
231 return( NULL );
234 do {
235 // Obtain the Mutex - don't use a guard as we want to be able to release
236 // and acquire again...
237 m_aMutex.acquire();
238 if ( nRow > m_aResults.size() )
240 if ( m_bQueryComplete )
242 m_bAtEnd = sal_True;
243 m_aMutex.release();
244 return( NULL );
246 else
248 clearResultOrComplete();
249 m_aMutex.release();
250 if ( !waitForResultOrComplete( ) )
251 return( NULL );
254 else
256 m_aMutex.release();
257 return( m_aResults[ nRow -1 ] );
259 } while ( sal_True );
262 sal_Bool
263 MQueryHelper::hasMore() const
265 return m_bHasMore;
268 sal_Bool
269 MQueryHelper::atEnd() const
271 return m_bAtEnd;
274 sal_Bool
275 MQueryHelper::isError() const
277 return m_bErrorCondition;
280 sal_Bool
281 MQueryHelper::queryComplete() const
283 return m_bQueryComplete;
286 sal_Bool
287 MQueryHelper::waitForQueryComplete( )
289 m_aMutex.acquire();
291 OSL_TRACE("In : waitForQueryComplete()");
292 if ( ! m_bQueryComplete ) {
295 m_aMutex.release();
296 clearResultOrComplete();
297 if ( !waitForResultOrComplete( ) )
298 return( sal_False );
299 m_aMutex.acquire();
301 while ( !m_bQueryComplete );
304 m_aMutex.release();
305 OSL_TRACE("Out : waitForQueryComplete()");
306 return( sal_True );
309 sal_Bool
310 MQueryHelper::waitForRow( sal_Int32 rowNum )
312 m_aMutex.acquire();
315 m_aMutex.release();
316 clearResultOrComplete();
317 if ( !waitForResultOrComplete() )
318 return( sal_False );
319 m_aMutex.acquire();
321 while ( !m_bQueryComplete && m_aResults.size() < (size_t)rowNum );
323 m_aMutex.release();
324 return( sal_True );
327 // -------------------------------------------------------------------------
329 sal_Int32
330 MQueryHelper::getResultCount() const
332 OSL_TRACE( "IN MQueryHelper::getResultCount()" );
333 if ( !m_bQueryComplete )
335 OSL_TRACE( "\tOUT MQueryHelper::getResultCount() = -1\n");
336 return -1;
338 else
340 OSL_TRACE( "\tOUT MQueryHelper::getResultCount() = %d\n", m_aResults.size() );
341 return static_cast<sal_Int32>(m_aResults.size());
345 // -------------------------------------------------------------------------
347 sal_uInt32
348 MQueryHelper::getRealCount() const
350 OSL_TRACE( "IN/OUT MQueryHelper::getRealCount() = %d\n", m_aResults.size() );
351 return static_cast<sal_Int32>(m_aResults.size());
354 // -------------------------------------------------------------------------
355 NS_IMETHODIMP MQueryHelper::OnQueryItem(nsIAbDirectoryQueryResult *result)
357 ::osl::MutexGuard aGuard( m_aMutex );
358 #if OSL_DEBUG_LEVEL > 0
359 OSL_TRACE( "IN MQueryHelper::OnQueryItem() Caller thread: %4d \n",m_oThreadID );
360 #endif
361 nsresult rv;
362 PRInt32 resultType;
364 if ( result == NULL ) {
365 OSL_TRACE("\tresult ptr is NULL\n");
366 return NS_OK;
369 // Get return status of executeQuery() call.
370 rv = result -> GetType(&resultType);
371 NS_ENSURE_SUCCESS(rv, rv);
373 // Check for errors of the executeQuery() call.
374 switch ( resultType ) {
375 case nsIAbDirectoryQueryResult::queryResultError:
376 OSL_TRACE("\tresultType == nsIAbDirectoryQueryResult::queryResultError\n");
377 m_bQueryComplete = sal_True;
378 m_bErrorCondition = sal_True;
379 notifyResultOrComplete();
380 return NS_OK;
381 case nsIAbDirectoryQueryResult::queryResultStopped:
382 OSL_TRACE("\tresultType == nsIAbDirectoryQueryResult::queryResultStopped\n");
383 m_bQueryComplete = sal_True;
384 notifyResultOrComplete();
385 return NS_OK;
386 case nsIAbDirectoryQueryResult::queryResultComplete:
387 OSL_TRACE("\tresultType == nsIAbDirectoryQueryResult::queryResultComplete\n");
388 m_bQueryComplete = sal_True;
389 notifyResultOrComplete();
390 return NS_OK;
391 case nsIAbDirectoryQueryResult::queryResultMatch:
392 OSL_TRACE("IN MQueryHelper::OnQueryItem --> queryResultMatch\n");
393 // Don't return, continues onto rest of method.
394 break;
395 default:
396 OSL_TRACE("\t******** Unexpected : resultType\n");
397 m_bQueryComplete = sal_True;
398 return NS_OK;
401 // Initialise an array that holds the resultset of the query.
402 nsCOMPtr<nsISupportsArray> properties;
403 rv = result -> GetResult(getter_AddRefs (properties));
404 NS_ENSURE_SUCCESS(rv, rv);
407 nsCOMPtr<nsISupports> item;
408 rv = properties -> GetElementAt(0, getter_AddRefs(item));
409 NS_ENSURE_SUCCESS(rv, rv);
411 nsCOMPtr<nsIAbDirectoryQueryPropertyValue> property(do_QueryInterface(item, &rv));
412 NS_ENSURE_SUCCESS(rv, rv);
414 char *name;
415 rv = property -> GetName(&name);
416 NS_ENSURE_SUCCESS(rv, rv);
417 if ( !strcmp(name,"card:nsIAbCard") )
419 nsCOMPtr<nsISupports> cardSupports;
420 property->GetValueISupports (getter_AddRefs (cardSupports));
421 nsCOMPtr<nsIAbCard> card(do_QueryInterface(cardSupports, &rv));
422 NS_ENSURE_SUCCESS(rv, rv);
424 getCardValues(card);
426 nsMemory::Free(name);
428 OSL_TRACE( "\tOUT MQueryHelper::OnQueryItem()\n" );
430 notifyResultOrComplete();
432 return(NS_OK);
435 // -----------------------------------------------------------------------------
436 void MQueryHelper::notifyQueryError()
438 m_bQueryComplete = sal_True ;
439 notifyResultOrComplete() ;
442 const char * getAddrURI(const nsIAbDirectory* directory)
444 nsresult retCode;
445 nsCOMPtr<nsIRDFResource> rdfResource = do_QueryInterface((nsISupports *)directory, &retCode) ;
446 if (NS_FAILED(retCode)) { return NULL; }
447 const char * uri;
448 retCode=rdfResource->GetValueConst(&uri);
449 if (NS_FAILED(retCode)) { return NULL; }
450 return uri;
453 #define ENSURE_GETUPDATECARD(x) \
454 if (NS_FAILED(retCode)) \
456 OSL_TRACE( x ); \
457 return card; \
459 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
461 //Some address book does not support query uri on card
462 //In this case, we can't resync the cards, we just return the old cards
463 nsIAbCard * getUpdatedCard( nsIAbCard* card)
465 OSL_ENSURE(card != NULL, "getUpdatedCard for NULL");
466 nsresult retCode;
467 nsCOMPtr<nsIRDFResource> rdfResource = do_QueryInterface((nsISupports *)card, &retCode) ;
468 ENSURE_GETUPDATECARD( "IN getUpdatedCard: Card does not support nsIRDFResource\n" );
470 const char * uri;
471 retCode=rdfResource->GetValueConst(&uri);
472 ENSURE_GETUPDATECARD( "IN getUpdatedCard: Card does not has a uri\n" );
474 nsCOMPtr<nsIRDFService> rdfService (do_GetService(kRDFServiceCID, &retCode)) ;
475 ENSURE_GETUPDATECARD( "IN getUpdatedCard: Card does not has a uri\n" );
477 nsCOMPtr<nsIRDFResource> rdfCard;
479 retCode = rdfService->GetResource(nsDependentCString(uri), getter_AddRefs(rdfCard)) ;
480 ENSURE_GETUPDATECARD( "IN getUpdatedCard: Can not get the updated card\n" );
482 nsCOMPtr<nsIAbCard> aNewCard=do_QueryInterface((nsISupports *)rdfCard, &retCode);
483 ENSURE_GETUPDATECARD( "IN getUpdatedCard: Error in get new card\n" );
485 return aNewCard;
488 #define ENSURE_MOZAB_PROFILE_NOT_LOOKED(directory) \
489 if (getDirectoryType(directory) == SDBCAddress::Mozilla && isProfileLocked(NULL)) \
491 m_aError.setResId( STR_MOZILLA_IS_RUNNIG_NO_CHANGES ); \
492 return sal_False; \
495 sal_Int32 MQueryHelper::commitCard(const sal_Int32 rowIndex,nsIAbDirectory * directory)
497 ENSURE_MOZAB_PROFILE_NOT_LOOKED(directory);
499 MQueryHelperResultEntry *resEntry = getByIndex(rowIndex);
500 if (!resEntry)
502 return sal_False;
504 nsIAbCard *card=resEntry->getCard();
505 if (!card)
507 return sal_False;
509 nsresult rv;
510 PRBool hasCard;
511 rv = directory->HasCard(card,&hasCard);
512 if (setCardValues(rowIndex) != sal_True)
513 return sal_False;
515 if (!NS_FAILED(rv) && hasCard)
517 rv = card->EditCardToDatabase(getAddrURI(directory));
519 else
521 nsIAbCard *addedCard=NULL;
522 rv = directory->AddCard(card,&addedCard);
523 if (!NS_FAILED(rv))
524 resEntry->setCard(addedCard);
526 //We return NS_ERROR_FILE_ACCESS_DENIED in the case the mozillaAB has been changed out side of our process
527 if (rv == NS_ERROR_FILE_ACCESS_DENIED )
528 m_aError.setResId( STR_FOREIGN_PROCESS_CHANGED_AB );
530 return !(NS_FAILED(rv));
533 sal_Int32 MQueryHelper::deleteCard(const sal_Int32 rowIndex,nsIAbDirectory * directory)
535 ENSURE_MOZAB_PROFILE_NOT_LOOKED(directory);
536 MQueryHelperResultEntry *resEntry = getByIndex(rowIndex);
537 if (!resEntry)
539 return sal_False;
541 nsIAbCard *card=resEntry->getCard();
542 if (!card)
544 return sal_False;
546 nsresult rv;
547 PRBool hasCard;
548 if (resEntry->getRowStates() == RowStates_Inserted)
550 rv = 0;
551 hasCard = sal_True;
553 else
554 rv = directory->HasCard(card,&hasCard);
556 if (!NS_FAILED(rv) && hasCard)
558 nsCOMPtr <nsISupportsArray> cardsToDelete;
559 rv = NS_NewISupportsArray(getter_AddRefs(cardsToDelete));
560 if (NS_SUCCEEDED(rv))
562 nsCOMPtr<nsISupports> supports = do_QueryInterface(card, &rv);
563 if (NS_SUCCEEDED(rv))
565 rv = cardsToDelete->AppendElement(supports);
566 if (NS_SUCCEEDED(rv))
567 rv = directory->DeleteCards(cardsToDelete);
572 if (NS_SUCCEEDED(rv))
573 resEntry->setRowStates(RowStates_Deleted);
574 //We return NS_ERROR_FILE_ACCESS_DENIED in the case the mozillaAB has been changed out side of our process
575 if (rv == NS_ERROR_FILE_ACCESS_DENIED )
576 m_aError.setResId( STR_FOREIGN_PROCESS_CHANGED_AB );
577 return !(NS_FAILED(rv));
580 sal_Bool MQueryHelper::setCardValues(const sal_Int32 rowIndex)
582 MQueryHelperResultEntry *resEntry = getByIndex(rowIndex);
583 if (!resEntry)
585 m_aError.setResId( STR_CANT_FIND_ROW );
586 return sal_False;
588 nsIAbCard *card=resEntry->getCard();
589 if (!card)
591 m_aError.setResId( STR_CANT_FIND_CARD_FOR_ROW );
592 return sal_False;
595 MLdapAttributeMap::fillCardFromResult( *card, *resEntry );
596 return sal_True;
599 void MQueryHelper::getCardValues(nsIAbCard *card,sal_Int32 rowIndex)
601 MQueryHelperResultEntry *resEntry;
602 if (rowIndex>0)
604 resEntry = getByIndex(rowIndex);
606 else
607 resEntry = new MQueryHelperResultEntry();
609 MLdapAttributeMap::fillResultFromCard( *resEntry, *card );
610 resEntry->setCard(card);
611 if (!rowIndex)
612 append( resEntry );
614 sal_Bool MQueryHelper::resyncRow(sal_Int32 rowIndex)
617 MQueryHelperResultEntry *resEntry = getByIndex(rowIndex);
618 if (!resEntry)
620 m_aError.setResId( STR_CANT_FIND_ROW );
621 return sal_False;
623 nsIAbCard *card=resEntry->getCard();
624 card = getUpdatedCard(card);
625 getCardValues(card,rowIndex);
626 return sal_True;
628 // -------------------------------------------------------------------------
629 sal_Int32 MQueryHelper::createNewCard()
631 ::osl::MutexGuard aGuard( m_aMutex );
632 nsresult rv;
633 nsCOMPtr <nsIAbCard> card = do_CreateInstance(NS_ABCARDPROPERTY_CONTRACTID, &rv);
634 //set default values
635 getCardValues(card);
636 return static_cast<sal_Int32>(m_aResults.size());