diff -r 000000000000 -r 667063e416a2 landmarks/locationlandmarks/localaccess/src/EPos_CPosLmLocalImportOp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/landmarks/locationlandmarks/localaccess/src/EPos_CPosLmLocalImportOp.cpp Tue Feb 02 01:06:48 2010 +0200 @@ -0,0 +1,764 @@ +/* +* Copyright (c) 2002-2005 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: Operation for importing landmarks to a database. +* +* +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "epos_cposlmlocaldatabase.h" +#include "epos_cposlmlocaldbaccess.h" +#include "EPos_LocalLandmarks.h" +#include "EPos_RPosLmLocalAccessSubsession.h" +#include "EPos_CPosLmLocalInternalOpActive.h" +#include "EPos_CPosLmLocalImportOp.h" + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +CPosLmLocalImportOp::CPosLmLocalImportOp( + CPosLmLocalDatabase& aDb, + CPosLandmarkParser& aLandmarkParser, + CPosLandmarkDatabase::TTransferOptions aTransferOptions, + CPosLmDiskUtilities& aDiskUtils) +: CPosLmLocalModifyOp(aDb), + iLandmarkParser(&aLandmarkParser), + iTransferOptions(aTransferOptions), + iImportState(EImportParseLm), + iParserOpStatus(KPosLmOperationNotComplete), + iDiskUtils(&aDiskUtils) + { + iUsesServerData = ETrue; // updates lm name index + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::ConstructL() + { + CPosLandmarkDatabase::TTransferOptions invalidOptions = + iTransferOptions & + ~CPosLandmarkDatabase::EIncludeCategories & + ~CPosLandmarkDatabase::EIncludeGlobalCategoryNames & + ~CPosLandmarkDatabase::ESupressCategoryCreation; + + __ASSERT_ALWAYS(invalidOptions == CPosLandmarkDatabase::EDefaultOptions, + Panic(KPosLandmarksClientPanic, EPosLmInvalidArgument)); + + BaseConstructL(); + + ReadInfoFromResourceFileL(R_POS_LM_LOCAL_IMPORT_LMS_OP); + + if (iTransferOptions & CPosLandmarkDatabase::EIncludeCategories) + { + iReader = CPosLmGlobalCategoryReader::NewL(); + } + + CPosLmOperation* parserOp = iLandmarkParser->ParseContentL(EFalse); + CleanupStack::PushL(parserOp); + + iInternalOpActive = CPosLmLocalInternalOpActive::NewL(*this, parserOp); + CleanupStack::Pop(parserOp); // ownership transferred + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::ConstructL( + const RArray& aLandmarksSelection) + { + if (aLandmarksSelection.Count() == 0) + { + User::Leave(KErrArgument); + } + + for (TInt i = 0; i < aLandmarksSelection.Count(); i++) + { + User::LeaveIfError(iSelectedLmIds.Append(aLandmarksSelection[i])); + } + iSelectedLmIds.SortUnsigned(); + + ConstructL(); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +CPosLmLocalImportOp* CPosLmLocalImportOp::NewL( + CPosLmLocalDatabase& aDb, + CPosLandmarkParser& aLandmarkParser, + CPosLandmarkDatabase::TTransferOptions aTransferOptions, + CPosLmDiskUtilities& aDiskUtils) + { + CPosLmLocalImportOp* self = new (ELeave) + CPosLmLocalImportOp(aDb, aLandmarkParser, aTransferOptions, aDiskUtils); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +CPosLmLocalImportOp* CPosLmLocalImportOp::NewL( + CPosLmLocalDatabase& aDb, + CPosLandmarkParser& aLandmarkParser, + const RArray& aLandmarksSelection, + CPosLandmarkDatabase::TTransferOptions aTransferOptions, + CPosLmDiskUtilities& aDiskUtils) + { + CPosLmLocalImportOp* self = new (ELeave) + CPosLmLocalImportOp(aDb, aLandmarkParser, aTransferOptions, aDiskUtils); + CleanupStack::PushL(self); + self->ConstructL(aLandmarksSelection); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +CPosLmLocalImportOp::~CPosLmLocalImportOp() + { + RollbackAndGenerateEventIfNeeded(Progress()); + + delete iReader; + + delete iCurrentLm; + iCurrentCategoryIds.Close(); + + iSelectedLmIds.Close(); + iImportedLmIds.Close(); + + delete iInternalOpActive; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::ImportedLandmarkItemIdsL( + RArray& aLmItemIds) + { + for (TInt i=0; i iSelectedLmIdPos && + iCurrentLmIndex > iSelectedLmIds[iSelectedLmIdPos]), + Panic(KPosLandmarksClientPanic, EPosInvalidIndex)); + + User::LeaveIfError(GenerateEventIfNeeded(aProgress)); + iStatusFlag = KErrNone; + return EFalse; + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TReal32 CPosLmLocalImportOp::Step() + { + return iCurrentProgress - iLastReportedProgress; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::CheckResourceValue( + TInt /*aResourceId*/, + TInt aNoOfSubOperations) + { + __ASSERT_ALWAYS(aNoOfSubOperations > 0, Panic(KPosLandmarksClientPanic, + EPosInvalidValueSpecifiedInResourceFile)); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::HandleError( + TInt& aError) + { + iStatusFlag = aError; + RollbackAndGenerateEventIfNeeded(Progress()); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::InternalOpCompleted( + TInt aStatus, + TReal32 aProgress, + TRequestStatus& aClientStatus, + TReal32& aClientProgress) + { + iParserOpStatus = aStatus; + iParserProgress = aProgress; + + if (aStatus == KErrNone || aStatus == KPosLmOperationNotComplete) + { + // Internal operation did not fail. Even if parser operation completed + // with KErrNone, this operation is not done; the landmark must be + // imported as well. + + TRAP(aStatus, DoNextStepPreL(aClientProgress)); + + if (aStatus == KErrNone) + { + // Status must be changed to KPosLmOperationNotComplete. Otherwise, + // the client thinks that the operation is done. + aStatus = KPosLmOperationNotComplete; + } + else + { + RollbackAndGenerateEventIfNeeded(aProgress); + } + } + else + { + RollbackAndGenerateEventIfNeeded(aProgress); + } + + TRequestStatus* clientStatus = &aClientStatus; + User::RequestComplete(clientStatus, aStatus); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::DoNextStep( + TRequestStatus& aStatus, + TReal32& aProgress) + { + if (IsInParsingState()) + { + // Performs next step on parser operation with active object. + aStatus = KRequestPending; + PrepareNextParsingStep(); + iInternalOpActive->DoNext(aStatus, aProgress); + } + else + { + // Import landmark or categories. May also be in compacting state. + NextStep(aStatus, aProgress); + } + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::DoExecuteL() + { + TRequestStatus status(KPosLmOperationNotComplete); + TRequestStatus statusInternalOp; + TReal32 progress; + + do + { + if (IsInParsingState()) + { + // Performs next step on parser operation without active object. + // Using an active object would hang the thread when calling + // User::WaitForRequest. + PrepareNextParsingStep(); + iInternalOpActive->InternalOpNextStep(statusInternalOp, progress); + User::WaitForRequest(statusInternalOp); + User::LeaveIfError(statusInternalOp.Int()); + + // To finish a parsing next step, this function must be called. + // The function would have been called by the active object if + // running asynchronously (DoNextStep). + InternalOpCompleted(statusInternalOp.Int(), progress, status, + progress); + } + else + { + // Import landmark or categories. May also be in compacting state. + NextStep(status, progress); + } + + User::WaitForRequest(status); + User::LeaveIfError(status.Int()); + } while (status.Int() == KPosLmOperationNotComplete); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::ParseLandmarkL() + { + // A landmark has previously been parsed when this function is called. + + // Error during parsing of landmarks + if (iParserOpStatus != KErrNone && + iParserOpStatus != KPosLmOperationNotComplete) + { + User::Leave(iParserOpStatus); + } + + // Reset landmark and landmark category + delete iCurrentLm; + iCurrentLm = NULL; + iCurrentCategoryIds.Reset(); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::GetParsedLandmarkL() + { + // Get landmark and landmark category ids + iCurrentLm = iLandmarkParser->LandmarkLC(); + CleanupStack::Pop(); + iCurrentLm->GetCategoriesL(iCurrentCategoryIds); + + // Reset category ids in landmark + iCurrentLm->RemoveLandmarkAttributes(CPosLandmark::ECategoryInfo); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::ImportLandmarkL() + { + iDiskUtils->DiskSpaceBelowCriticalLevelL( + iDiskUtils->EstimatedDiskSizeOfLmOperation( + CPosLmDiskUtilities::EAddLandmarkOp, + *iCurrentLm ), iDb->DatabaseDrive() ); + + // Add landmark to db + PosLmLandmarkHandler::AddLandmarkL( *iDb->DatabaseAccess(), *iCurrentLm ); + iDb->NameIndex().AddL( *iCurrentLm ); + + // Add lm item id to array of imported lm item ids + User::LeaveIfError( iImportedLmIds.Append( iCurrentLm->LandmarkId() ) ); + + // Imported a selected landmark, so point to next id in array + iSelectedLmIdPos++; + + iCurrentCategory = 0; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::ImportLmCategoriesL() + { + for (TInt i = 0; + i < iNoOfSubOperations && + iCurrentCategory < iCurrentCategoryIds.Count(); + i++) + { + // Get next gategory + CPosLandmarkCategory* lmcat = + iLandmarkParser->LandmarkCategoryLC( + iCurrentCategoryIds[iCurrentCategory++]); + TPosLmItemId dbItemId; + TBool lmCatInDb = ETrue; + + // Is global category ? + if (lmcat->GlobalCategory() != KPosLmNullGlobalCategory) + { + TBool dummyBool; + // Is global category in db ? + if (PosLmCategoryHandler::IsGlobalCategoryExistingL( + *iDb->DatabaseAccess(), lmcat->GlobalCategory(), + dbItemId, dummyBool)) + { + // Set category id for global category + PosLmImplExtension::SetCategoryIdL(*lmcat, dbItemId); + + // Import global category names ? + if (iTransferOptions & + CPosLandmarkDatabase::EIncludeGlobalCategoryNames) + { + // Update global category name in db + TPtrC categoryName; + TInt err = lmcat->GetCategoryName(categoryName); + if (err == KErrNone) + { + PosLmCategoryHandler::UpdateGlobalCategoryNameL( + *iDb->DatabaseAccess(), *lmcat); + iLastChangedCategoryId = lmcat->CategoryId(); + iNrOfCategoriesUpdated++; + } + } + } + else + { + // Is global category in resource ? + HBufC* categoryNameFromResource = + GlobalCategoryNameInResourceL(lmcat); + CleanupStack::PushL(categoryNameFromResource); + if (categoryNameFromResource) + { + // Import global category names ? + if (iTransferOptions & + CPosLandmarkDatabase::EIncludeGlobalCategoryNames) + { + // Add global category to db with imported name + lmCatInDb = AddCategoryL(*lmcat); + } + else + { + // Add global category to db with name from resource + lmcat->SetCategoryNameL( + categoryNameFromResource->Des()); + lmCatInDb = AddCategoryL(*lmcat); + } + } + else + { + // Global category neither in db or resource file + lmCatInDb = AddLocalCategoryL(*lmcat, dbItemId); + } + + CleanupStack::PopAndDestroy(categoryNameFromResource); + } + } + else + { + // Not a global category + lmCatInDb = AddLocalCategoryL(*lmcat, dbItemId); + } + + if (lmCatInDb) + { + // Add category id to landmark + iCurrentLm->AddCategoryL(lmcat->CategoryId()); + } + + CleanupStack::PopAndDestroy(lmcat); + } + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TBool CPosLmLocalImportOp::AddLocalCategoryL( + CPosLandmarkCategory& aLmCat, + TPosLmItemId& aLmItemId) + { + // Set category id for category + PosLmImplExtension::SetGlobalCategory(aLmCat, KPosLmNullGlobalCategory); + + // Category name doesn't exists in db ? + if (PosLmCategoryHandler::VerifyCategoryNameNotExistsL( + *iDb->DatabaseAccess(), aLmCat, PosLmCategoryHandler::EAddCheck, + aLmItemId) == KErrNone) + { + // Add local category + return AddCategoryL(aLmCat); + } + else + { + // Set category id for category + PosLmImplExtension::SetCategoryIdL(aLmCat, aLmItemId); + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::UpdateProgress(TReal32& aProgress) + { + iLastReportedProgress = iCurrentProgress; + + // Set the progress for the operation + TReal32 importStateProgress; + // Three (3) step are taken per imported landmark for each NextStepL call + TReal32 importStatePartProgress = + (iParserProgress - iOldParserProgress) / 3; + if (iImportState == EImportAddLmCatToDb) + { + TReal32 importLmCatPart = importStatePartProgress; + // Add current lm cat index + if (iCurrentCategoryIds.Count() > 0) + { + importStatePartProgress = + (TReal32(1) / iCurrentCategoryIds.Count()) * + importStatePartProgress; + importLmCatPart = importStatePartProgress * + (iCurrentCategory + 1); + } + aProgress = iOldParserProgress + importLmCatPart; + } + else if (iImportState == EImportAddLmToDb) + { + importStateProgress = importStatePartProgress; + aProgress = iOldParserProgress + (2 * importStateProgress); + } + else + { + // iImportState == EImportParseLm + aProgress = iParserProgress; + } + + iCurrentProgress = aProgress; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TBool CPosLmLocalImportOp::LandmarkSelection() + { + return (iSelectedLmIds.Count() > 0); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TBool CPosLmLocalImportOp::IsSelectedLandmark() + { + if (!LandmarkSelection() || + (LandmarkSelection() && + iSelectedLmIds.Count() > iSelectedLmIdPos && + iCurrentLmIndex == iSelectedLmIds[iSelectedLmIdPos])) + { + return ETrue; + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TBool CPosLmLocalImportOp::IsSelectedLandmarksImported() + { + if (LandmarkSelection() && + iSelectedLmIds.Count() == iSelectedLmIdPos) + { + return ETrue; + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +HBufC* CPosLmLocalImportOp::GlobalCategoryNameInResourceL( + CPosLandmarkCategory* aCategory) + { + HBufC* name = NULL; + TPosLmGlobalCategory globalCat = aCategory->GlobalCategory(); + + for (TInt i = 0; i < iReader->Count() && !name; i++) + { + CPosLandmarkCategory* readerCategory = iReader->GlobalCategoryLC(i); + + TPtrC catName; + if (readerCategory->GlobalCategory() == globalCat && + readerCategory->GetCategoryName(catName) == KErrNone) + { + name = catName.AllocL(); + } + + CleanupStack::PopAndDestroy(readerCategory); + } + + return name; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::RollbackAndGenerateEventIfNeeded( + TReal32 aProgress) + { + RollbackIfNeeded(); + + GenerateEventIfNeeded(aProgress); + + // Reset flag: rollback and event generation should not be done twice. + iStatusFlag = KErrNone; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TInt CPosLmLocalImportOp::GenerateEventIfNeeded( + TReal32 /*aProgress*/) + { + TInt status = KErrNone; + if (iStatusFlag != KErrNone && iImportedLmIds.Count() > 0) + { + if (iImportedLmIds.Count() == 1) + { + status = iDb->RegisterEvent(EPosLmEventLandmarkCreated, + iImportedLmIds[0]); + if (status != KErrNone) + { + return status; + } + } + if (iNrOfCategoriesAdded == 1 && iNrOfCategoriesUpdated <= 1) + { + status = iDb->RegisterEvent(EPosLmEventCategoryCreated, + iLastChangedCategoryId); + if (status != KErrNone) + { + return status; + } + } + if (iNrOfCategoriesUpdated == 1 && iNrOfCategoriesAdded <= 1) + { + status = iDb->RegisterEvent(EPosLmEventCategoryUpdated, + iLastChangedCategoryId); + if (status != KErrNone) + { + return status; + } + } + + if (iImportedLmIds.Count() > 1 && + (iNrOfCategoriesAdded > 1 || iNrOfCategoriesUpdated > 1)) + { + return iDb->RegisterEvent(EPosLmEventUnknownChanges); + } + else if (iImportedLmIds.Count() > 1) + { + return iDb->RegisterEvent(EPosLmEventLandmarkUnknownChanges); + } + else if (iNrOfCategoriesAdded > 1 || iNrOfCategoriesUpdated > 1) + { + return iDb->RegisterEvent(EPosLmEventCategoryUnknownChanges); + } + } + return status; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TBool CPosLmLocalImportOp::AddCategoryL( + CPosLandmarkCategory& aCategory) + { + TBool toreturn = ETrue; + + if (iTransferOptions & + CPosLandmarkDatabase::ESupressCategoryCreation) + { + toreturn = EFalse; + } + else + { + iDiskUtils->DiskSpaceBelowCriticalLevelL( + iDiskUtils->EstimatedDiskSizeOfLmOperation( + CPosLmDiskUtilities::EAddLmCategoryOp, aCategory), + iDb->DatabaseDrive()); + + PosLmCategoryHandler::AddCategoryL(*iDb->DatabaseAccess(), aCategory); + iLastChangedCategoryId = aCategory.CategoryId(); + iNrOfCategoriesAdded++; + } + + return toreturn; + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +void CPosLmLocalImportOp::PrepareNextParsingStep() + { + iOldParserProgress = iParserProgress; + iCurrentLmIndex = iLandmarkParser->NumOfParsedLandmarks(); + } + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// +TBool CPosLmLocalImportOp::IsInParsingState() + { + return (iImportState == EImportParseLm && !IsInCompactingState() && + iParserOpStatus == KPosLmOperationNotComplete); + } +