metadataengine/client/src/mdequery.cpp
changeset 0 c53acadfccc6
child 6 646a02f170b9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metadataengine/client/src/mdequery.cpp	Mon Jan 18 20:34:07 2010 +0200
@@ -0,0 +1,591 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Query base class
+*
+*/
+
+
+#include "mdequery.h"
+
+#include "mdeorderrule.h"
+#include "mdeinstanceitem.h"
+#include "mdelogiccondition.h"
+#include "mdenamespacedef.h"
+#include "mdepanic.h"
+
+
+CMdEQuery::CMdEQuery(TQueryType aType, CMdESession& aSession, CMdENamespaceDef& aNamespaceDef)
+        : iQueryId( 0 ), iSession(aSession), iNamespaceDef(aNamespaceDef), iType(aType), 
+          iResultMode(EQueryResultModeItem), iState(EStateNew), iError(KErrNone), 
+          iObjectResult(NULL), iCountResult(0), iDistinctResults(NULL)
+    {
+    }
+
+
+void CMdEQuery::QueryConstructL()
+    {
+    iConditions = CMdELogicCondition::NewL(ELogicConditionOperatorAnd);
+    }
+
+
+CMdEQuery::~CMdEQuery()
+	{
+	Cancel();
+  
+    // This will destroy the entire conditions tree.
+   	delete iConditions;
+
+   	const TInt count = iResults.Count();
+   	
+    // Destroy all result items this query instance owns.
+    for(TInt i = 0; i < count; ++i)
+        {
+        if(iResults[i].iOwned)
+            {
+            delete iResults[i].iItem;
+            }
+        }
+
+    // Destroy object result item this query instance owns  
+    if(iObjectResult.iItem)
+        {
+        if(iObjectResult.iOwned)
+        	{
+        	delete iObjectResult.iItem;
+        	iObjectResult.iItem = NULL;
+        	}
+        }
+
+	iCountResult = 0;
+
+	iResults.Reset();
+	iResults.Close();
+	iIdResults.Reset();
+	iIdResults.Close();
+
+    iOrderRules.Close();
+    iObservers.Close();
+
+   	delete iDistinctResults;
+	}
+
+
+EXPORT_C TQueryType CMdEQuery::Type() const
+    {
+    return iType;
+    }
+
+EXPORT_C CMdENamespaceDef& CMdEQuery::NamespaceDef() const
+	{
+	return iNamespaceDef;
+	}
+    
+EXPORT_C CMdESession& CMdEQuery::Session() const
+    {
+    return iSession;
+    }
+
+
+EXPORT_C CMdELogicCondition& CMdEQuery::Conditions() const
+    {
+    __ASSERT_DEBUG(iConditions , 
+                    TMdEPanic::Panic(TMdEPanic::EInternal));
+    return *iConditions;
+    }
+    
+    
+EXPORT_C void CMdEQuery::AppendOrderRuleL(const TMdEOrderRule& aRule)
+    {
+    AssertInState(EStateNew);
+    iOrderRules.AppendL( aRule );
+    }
+
+
+EXPORT_C void CMdEQuery::InsertOrderRuleL(const TMdEOrderRule& aRule, TInt aPos)
+    {
+    AssertInState(EStateNew);
+    User::LeaveIfError( iOrderRules.Insert(aRule, aPos) );   
+    }
+
+
+EXPORT_C TInt CMdEQuery::OrderRuleCount() const
+    {
+    return iOrderRules.Count();    
+    }
+
+
+EXPORT_C void CMdEQuery::RemoveOrderRule(TInt aIndex)
+    {
+    AssertInState(EStateNew);
+    iOrderRules.Remove(aIndex);
+    }
+
+
+EXPORT_C TMdEOrderRule CMdEQuery::OrderRule(TInt aIndex) const
+    {
+    return iOrderRules[aIndex];        
+    }
+    
+
+EXPORT_C void CMdEQuery::FindL(TUint aMaxCount, TUint aNotifyCount)
+    {
+    AssertNotInState(EStateError);
+
+	// leave if query already running    
+    if(iState == EStateSearching)
+        {
+        User::Leave(KErrNotReady);
+        }
+    
+    const TInt count = iResults.Count();
+    
+	// clear old results
+	// Destroy all result items this query instance owns.
+    for(TInt i = 0; i < count; ++i)
+        {
+        if(iResults[i].iOwned)
+            {
+            delete iResults[i].iItem;
+            }
+        }
+	iResults.Reset();
+
+    // Destroy object result item this query instance owns  
+    if( iObjectResult.iItem )
+        {
+        if( iObjectResult.iOwned )
+        	{
+        	delete iObjectResult.iItem;
+        	iObjectResult.iItem = NULL;
+        	}
+        }
+
+	iIdResults.Reset();
+
+    if( iDistinctResults )
+    	{    	
+    	delete iDistinctResults;
+    	iDistinctResults = NULL;
+    	}
+
+	iCountResult = 0;
+	// end of clearing
+
+    DoFindL(aMaxCount, aNotifyCount);
+    }
+
+
+EXPORT_C void CMdEQuery::Cancel()
+    {
+    // is query incomplete before canceling
+    TBool incomplete = !IsComplete();
+    
+    if( incomplete )
+    	{
+    	DoCancel();
+    	}
+
+	if( iConditions )
+		{		
+    	iConditions->SetLocked( EFalse );
+		}
+    
+    if( incomplete || IsComplete() == EFalse )
+    	{
+    	iState = EStateError;
+    	NotifyCompleted( KErrCancel );
+    	}
+    }
+
+
+EXPORT_C TBool CMdEQuery::IsComplete() const
+    {
+    return iState != EStateSearching ? ETrue : EFalse;
+    }
+
+
+EXPORT_C TInt CMdEQuery::Error() const
+    {
+    return iError;
+    }
+
+
+EXPORT_C TInt CMdEQuery::Count() const
+    {
+    if ( iResultMode == EQueryResultModeItem || iResultMode == EQueryResultModeObjectWithFreetexts )
+        {
+        return iResults.Count();
+        }
+    else if ( iResultMode == EQueryResultModeId )
+        {
+        return iIdResults.Count();
+        }
+    else if ( iResultMode == EQueryResultModeDistinctValues )
+    	{
+    	if( iDistinctResults )
+    		{    		
+    		return iDistinctResults->Count();
+    		}
+    	else
+    		{
+    		return 0;
+    		}
+    	}
+    else // count query
+        {
+        return iCountResult;
+        }
+    }
+
+EXPORT_C CMdEItem& CMdEQuery::ResultItem(TInt aIndex) const
+    {
+    return *iResults[aIndex].iItem;
+    }
+
+
+EXPORT_C TItemId CMdEQuery::ResultId(TInt aIndex) const
+    {
+    return iIdResults[aIndex];
+    }
+
+EXPORT_C const RArray<TItemId>& CMdEQuery::ResultIds() const
+	{
+	return iIdResults;
+	}
+
+EXPORT_C CMdEItem* CMdEQuery::TakeOwnershipOfResult(TInt aIndex)
+    {
+    // Panic if an item is taken twice.
+    __ASSERT_DEBUG(iResults[aIndex].iOwned,
+                    TMdEPanic::Panic(TMdEPanic::EQueryDoesntOwnResult));
+
+    // Applies only instance ownership
+    if ( iResultMode == EQueryResultModeItem || iResultMode == EQueryResultModeObjectWithFreetexts )
+        {
+        iResults[aIndex].iOwned = EFalse;
+        return static_cast<CMdEItem*>( iResults[aIndex].iItem );
+        }
+    else
+    	{
+    	return NULL;
+    	}
+    }
+
+
+EXPORT_C TBool CMdEQuery::OwnsResult(TInt aIndex)
+    {
+    return iResults[aIndex].iOwned;
+    }
+
+
+EXPORT_C CMdEQuery::TState CMdEQuery::State() const
+    {
+    return iState;
+    }
+
+void CMdEQuery::DoCancel()
+    {
+    SetState( EStateError );
+    }
+
+void CMdEQuery::SetState(TState aState)
+    {
+    if(aState == iState)
+        {
+        // Already in the specified state.
+        return;
+        }
+        
+    // It's impossible to get out of the Error state.
+    AssertNotInState(EStateError);
+
+    // It's impossible to return to the New state.
+    __ASSERT_ALWAYS(aState > EStateFirst && aState < EStateLast && 
+                    aState != EStateNew, 
+                    TMdEPanic::Panic(TMdEPanic::EInternal));
+
+    // Move out of the old state.
+    switch(iState)
+        {
+        case EStateNew:
+            // Moving out of the New state causes the search conditions to 
+            // be locked.
+            iConditions->SetLocked();
+            break;    
+            
+        case EStateSearching:
+            // Searching has been completed.
+            break;
+
+        case EStateCompleted:
+            // Searching is been restarted.
+            break;
+            
+        default:
+            break;
+        }
+
+    // Set the new state.
+    iState = aState;
+
+    // Move into the new state.
+    switch(iState)
+        {
+        case EStateSearching:
+            // Searching has been started.
+            break;
+
+        case EStateCompleted:
+            // Searching has been completed.
+            break;
+
+        case EStateError:
+            // The query has entered the Error state.
+            break;
+            
+        default:
+            break;
+        }    
+    }
+
+
+void CMdEQuery::AssertInState(TState aState)
+    {
+    __ASSERT_ALWAYS(aState == iState,
+                    TMdEPanic::Panic(TMdEPanic::EQueryStateIllegalOperation));
+    }
+    
+
+void CMdEQuery::AssertNotInState(TState aState)
+    {
+    __ASSERT_ALWAYS(aState != iState,
+                    TMdEPanic::Panic(TMdEPanic::EQueryStateIllegalOperation));
+    }
+    
+
+void CMdEQuery::NotifyNewResultsL(const RPointerArray<CMdEInstanceItem>& aNewResults)
+    {
+    __ASSERT_ALWAYS(iState != EStateNew && iState != EStateError,
+                    TMdEPanic::Panic(TMdEPanic::EInternal));
+
+	TInt firstNewItemIndex = iResults.Count();
+	TInt i = 0;
+
+    // Query gets ownership of the results only if don't leave.
+    // If a leave occurs, the results array is restored to its original
+    // condition before any new results were added.
+
+    const TInt oldCount = iResults.Count();
+
+    TRAPD(err, AppendResultsL(aNewResults));
+    if (err != KErrNone)
+        {
+        // Cleanup: remove the ones that were added.
+        while (iResults.Count() > oldCount)
+            {
+            iResults.Remove(iResults.Count() - 1);
+            }
+        // Leave with the same error.
+        User::Leave(err);
+        }
+
+    // After this no leave can occur.
+
+    const TInt newCount = aNewResults.Count();
+    
+    // Transfer ownership of the results to the query.
+    for (i = 0; i < newCount; i++)
+        {
+        iResults[firstNewItemIndex + i].iOwned = ETrue;
+        }
+
+    const TInt observerCount = iObservers.Count();
+    
+	for (i = 0; i < observerCount; i++)
+		{
+		MMdEQueryObserver* observer = iObservers[i];
+		observer->HandleQueryNewResults( *this, firstNewItemIndex, newCount );
+		}
+    }
+
+
+void CMdEQuery::NotifyNewResultsL(const RArray<TItemId>& aNewResults)
+    {
+    __ASSERT_ALWAYS(iState != EStateNew && iState != EStateError,
+                    TMdEPanic::Panic(TMdEPanic::EInternal));
+
+	TInt firstNewItemIndex = iIdResults.Count();
+	TInt i = 0;
+
+    const TInt oldCount = iIdResults.Count();
+
+    TRAPD(err, AppendResultsL(aNewResults));
+    if (err != KErrNone)
+        {
+        // Cleanup: remove the ones that were added.
+        while (iIdResults.Count() > oldCount)
+            {
+            iIdResults.Remove(iIdResults.Count() - 1);
+            }
+        // Leave with the same error.
+        User::Leave(err);
+        }
+
+    const TInt observerCount = iObservers.Count();
+    
+	for (i = 0; i < observerCount; i++)
+		{
+		MMdEQueryObserver* observer = iObservers[i];
+		observer->HandleQueryNewResults(*this, firstNewItemIndex, 
+                                        aNewResults.Count());
+		}
+    }
+
+void CMdEQuery::NotifyNewResultsL( const CDesCArray& aNewResults )
+    {
+	TInt firstNewItemIndex = aNewResults.Count();
+	TInt i = 0;
+
+	TInt oldCount = 0;
+	if( iDistinctResults )
+		{
+		oldCount = iDistinctResults->Count();
+		}
+	else
+		{
+	    iDistinctResults = new (ELeave) CDesCArrayFlat( 8 );
+		}
+
+    TRAPD( err, AppendResultsL( aNewResults ) );
+    if( err != KErrNone )
+        {
+        // Cleanup: remove the ones that were added.
+        while( iDistinctResults->Count() > oldCount )
+            {
+            iDistinctResults->Delete( iDistinctResults->Count() - 1 );
+            }
+        // Leave with the same error.
+        User::Leave(err);
+        }
+
+    const TInt observerCount = iObservers.Count();
+    
+	for (i = 0; i < observerCount; i++)
+		{
+		MMdEQueryObserver* observer = iObservers[i];
+		observer->HandleQueryNewResults( *this, firstNewItemIndex, 
+                                         aNewResults.Count() );
+		}
+    }
+
+void CMdEQuery::NotifyNewResults(TUint32 aResult)
+	{
+    // Don't call observer here, since only one result
+    iCountResult = aResult;
+    }
+
+void CMdEQuery::AppendResultsL(const RPointerArray<CMdEInstanceItem>& aNewResults)
+    {
+    const TInt newResultCount = aNewResults.Count();
+    iResults.ReserveL( iResults.Count() + newResultCount );
+
+	for (TInt i = 0; i < newResultCount; ++i)
+        {
+        // At this point the ownership isn't transferred yet.
+        TResult result( aNewResults[i] );
+		iResults.AppendL( result );
+		}
+    }
+
+void CMdEQuery::AppendResultsL(const RArray<TItemId>& aNewResults)
+    {
+    const TInt newResultCount = aNewResults.Count();
+    iIdResults.ReserveL( iResults.Count() + newResultCount );
+
+	for (TInt i = 0; i < newResultCount; ++i)
+        {
+        // Add new results to query's list
+		iIdResults.AppendL( aNewResults[i] );
+		}
+    }
+
+void CMdEQuery::AppendResultsL( const CDesCArray& aNewResults )
+    {
+    const TInt count = aNewResults.Count();
+    
+    for ( TInt i = 0; i < count; ++i )
+    	{
+    	iDistinctResults->AppendL( aNewResults[i] );
+    	}
+    }
+    
+void CMdEQuery::NotifyCompleted(TInt aError)
+    {
+    // The implementation must move out of the Searching state before
+    // notifying the base class.
+    __ASSERT_ALWAYS(iState != EStateSearching, TMdEPanic::Panic(TMdEPanic::EInternal));
+
+    // Update the latest error code.
+    iError = aError;
+	for (TInt i = iObservers.Count() - 1; i >= 0; --i)
+		{
+		MMdEQueryObserver* observer = iObservers[i];
+		observer->HandleQueryCompleted(*this, aError);
+		}
+    }
+
+
+EXPORT_C void CMdEQuery::AddObserverL(MMdEQueryObserver& aObserver)
+	{
+	__ASSERT_ALWAYS(iObservers.Find(&aObserver) == KErrNotFound,
+				    TMdEPanic::Panic(TMdEPanic::EQueryDuplicateObserver));
+
+	iObservers.AppendL( &aObserver );
+	}
+
+
+EXPORT_C void CMdEQuery::RemoveObserver(MMdEQueryObserver& aObserver)
+	{
+	TInt index = iObservers.Find(&aObserver);
+
+	__ASSERT_ALWAYS(index != KErrNotFound,
+				    TMdEPanic::Panic(TMdEPanic::EQueryUnknownObserver));
+
+	iObservers.Remove(index);
+	}
+
+
+EXPORT_C void CMdEQuery::SetResultMode( TQueryResultMode aMode )
+    {    
+    iResultMode = aMode;
+    }
+
+EXPORT_C TQueryResultMode CMdEQuery::ResultMode() const
+    {
+    return iResultMode;
+    }
+EXPORT_C CMdEItem& CMdEQuery::ResultObjectItem() const
+    {
+    return *iObjectResult.iItem;
+    }
+
+EXPORT_C TPtrC16 CMdEQuery::ResultDistinctValue(TInt aIndex) const
+	{
+	return (*iDistinctResults)[aIndex];
+	}
+
+RArray<TMdEOrderRule>& CMdEQuery::OrderRules()
+	{
+	return iOrderRules;
+	}