diff -r 000000000000 -r dfb7c4ff071f commsconfig/commsdatabaseshim/commdbshim/SCDB/commdb_impl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commsconfig/commsdatabaseshim/commdbshim/SCDB/commdb_impl.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,1424 @@ +// Copyright (c) 2006-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: +// Comms Database Table View defintions +// +// + +/** + @file + @deprecated since v9.1. Functionality is replaced with commsdat. +*/ + +#include +#include +#include +#include +#include + +#include "commdb_impl.H" +#include "Commsdat_Log.h" +#include "commsdattypeinfov1_1_internal.h" + +const TInt KFirstRecord = 0; + +// Additional funtions to implement Connection Preference table protection - in a separate +// class so as not to break BC. +CCommDbTableExtension::CCommDbTableExtension() +/** +Constructor +*/ + { + } + +CCommDbTableExtension* CCommDbTableExtension::NewL() + { + CCommDbTableExtension* self = new(ELeave) CCommDbTableExtension; + TInt err = self->iCommitSeqProperty.Attach(KUidCommsDatStatusEvent, KCommsDatStatusEventCommitSeq); + if(err != KErrNone) + { + delete self; + User::Leave(err); + } + return self; + } + +void CCommDbTableExtension::GetRecordInfoL(const TDesC& aColumn, TDbColType& aColType, TUint32& aAttrib) + { + CMDBRecordSetBase* recSet = GetRecordSetL(); + + TBuf buf; // This holds Column name + TBool found(EFalse); + + // create dummy record to read info from it + CMDBRecordBase* dummyRecord = CCDRecordBase::RecordFactoryL(recSet->TypeId()); + const SRecordTypeInfo* recordInfo = dummyRecord->GetRecordInfo(); + + // Loop through all the columns of the record + while(recordInfo->iTypeId != 0 && !found) + { + // Get name of the field into buffer + buf = recordInfo->iTypeName; + + if(buf.CompareF(aColumn) == 0) + { + found = ETrue; + } + else + { + // Switch to Next column + recordInfo++; + } + } + + // check if column is not found + if(!found) + { + delete dummyRecord; + User::Leave(KErrNotFound); + } + else + { + aColType = GetColType(recordInfo->iValType); + recordInfo->iTypeAttr == ENotNull ? aAttrib = TDbCol::ENotNull : aAttrib = 0; + } + + delete dummyRecord; + } + +TDbColType CCommDbTableExtension::GetColType(TInt aType) + { + TDbColType ret; + switch(aType) + { + case EText: + case EMedText: + ret = EDbColText16; + break; + case ELongText: + ret = EDbColLongText; + break; + case EDesC8: + ret = EDbColText8; + break; + case EUint32: + ret = EDbColUint32; + break; + case EInt: + ret = EDbColUint32; + break; + case EBool: + ret = EDbColBit; + break; + default: + ret = EDbColInt32; + } + + return ret; + } + +TInt CCommDbTableExtension::GetMaxTypeLength(TInt aType) + { + TInt ret; + + switch(aType) + { + case EText: + ret = KMaxTextLength; + break; + case EDesC8: + ret = KMaxTextLength; + break; + case EUint32: + ret = KMaxNumLength; + break; + case EInt: + ret = KMaxNumLength; + break; + case EBool: + ret = KMaxNumLength; + break; + case ELongText: + ret = KMaxLongTextLength; + break; + case EMedText: + ret = KMaxMedTextLength; + break; + default: + ret = 0; + } + + return ret; + } + +void CCommDbTableExtension::UpdateLastCommitSeq() + { + // Update the global commit sequence, for detecting possible changes when deciding whether to refresh records + TInt currCommitSeq; + if(iCommitSeqProperty.Get(currCommitSeq) == KErrNone) + { + iLastCommitSeq = currCommitSeq; + } + } + +TInt CCommDbTableExtension::MaybeRefreshCurrentRecord(CMDBSession& aDbs) + { + // If the global commit sequence number differs from the last one set or observed by us then we need to refresh to ensure we + // acquire any relevant changes + TInt err = KErrNone; + TInt currCommitSeq = iLastCommitSeq; + if(iCommitSeqProperty.Get(currCommitSeq) != KErrNone || currCommitSeq != iLastCommitSeq) + { + TRAP(err,iCurrentRecord->RefreshL(aDbs)); + if(err == KErrNone) + { + iLastCommitSeq = currCommitSeq; + } + } + return err; + } + +TInt CCommDbTableExtension::GotoFirstRecord(CMDBSession& aDbs) + { + TInt err(KErrNotFound); + + TInt countContRec = iRecordSetContainer->iRecords.Count(); + + if (iRecordSetContainer && countContRec) + { + // set up stating point + iCurrentRecord = NULL; + // set up first valid record + TInt valid = FindFirstNextValidRecord(ETrue); + + if(valid) + { + // save current record before change + CMDBRecordBase* currRecBackup(iCurrentRecord); + + if ( iCurrentRecord->RecordId() == KCDDefaultRecord && + (iCurrentRecord->Attributes() & ECDHidden ) && + ! aDbs.IsSetAttributeMask(ECDHidden) ) + { + err = GotoNextRecord(aDbs); + } + else + { + err = MaybeRefreshCurrentRecord(aDbs); + if (err != KErrNone) + { + __FLOG_STATIC1(KLogComponent, KCommDbShim, _L("CCommDbTableExtension::GotoFirstRecord failed to Refresh the data Err=%d"),err); + iCurrentRecord = currRecBackup; + } + } + } + + iEndOfTableRecordBackup = NULL; + iBeginingOfTableRecordBackup = NULL; + } + + // record set is empty + return err; + } + +TInt CCommDbTableExtension::GotoNextRecord(CMDBSession& aDbs) + { + TInt err(KErrNone); + TInt currIndex(0); + + if (!iRecordSetContainer) + { + return KErrNotFound; + } + + if (iCurrentRecord) + { + TInt count = iRecordSetContainer->iRecords.Count(); + currIndex = iRecordSetContainer->iRecords.Find(iCurrentRecord); + if (currIndex == count-1) + { + // record set is either empty or going out of scope + err = KErrNotFound; + // the marker is going beyond end of the table, so backup last record and use the value as end marker + iEndOfTableRecordBackup = iCurrentRecord; + iCurrentRecord = NULL; + } + else + { + // save current record before change + CMDBRecordBase* currRecBackup(iCurrentRecord); + // set up first next valid record + TInt valid = FindFirstNextValidRecord(EFalse); + if (valid) + { + err = MaybeRefreshCurrentRecord(aDbs); + if (err != KErrNone) + { + // return to status prior to failure + iCurrentRecord = currRecBackup; + __FLOG_STATIC1(KLogComponent, KCommDbShim, _L("CCommDbTableExtension::GotoNextRecord failed to Refresh the data Err=%d"),err); + } + } + else + { + err = KErrNotFound; + } + } + } + else + { + // if position was on the begining of the table then retrieve back first record and set up begining of table marker to null + if (iBeginingOfTableRecordBackup) + { + iCurrentRecord = iBeginingOfTableRecordBackup; + iBeginingOfTableRecordBackup = NULL; + } + else + { + err = KErrNotFound; + } + } + + return err; + } + +TInt CCommDbTableExtension::GotoPreviousRecord(CMDBSession& aDbs) + { + TInt err = KErrNone; + + if (!iRecordSetContainer) + { + return KErrNotFound; + } + + if (iCurrentRecord) + { + const TInt count = iRecordSetContainer->iRecords.Count(); + TInt currIndex = iRecordSetContainer->iRecords.Find(iCurrentRecord); + if (currIndex == 0) + { + // record set is either empty or going out of scope + err = KErrNotFound; + } + else + { + // save current record before change + CMDBRecordBase* currRecBackup(iCurrentRecord); + // set up first prev valid record + TInt valid = FindFirstPrevValidRecord(); + if (valid) + { + err = MaybeRefreshCurrentRecord(aDbs); + if (err != KErrNone) + { + // return to status prior to failure + iCurrentRecord = currRecBackup; + __FLOG_STATIC1(KLogComponent, KCommDbShim, _L("CCommDbTableExtension::GotoPreviousRecord failed to Refresh the data Err=%d"),err); + } + } + else + { + err = KErrNotFound; + } + } + } + else + { + // if position was on the end of the table then retrieve back last record and set up end of table marker to null + if (iEndOfTableRecordBackup) + { + iCurrentRecord = iEndOfTableRecordBackup; + iEndOfTableRecordBackup = NULL; + } + else + { + err = KErrNotFound; + } + } + + return err; + } + +void CCommDbTableExtension::InsertConnPrefRecordL(CCDConnectionPrefsRecord* aConnPref, CMDBSession& aDbs) + { + __FLOG_STATIC0(KLogComponent, KCommDbShim, _L("CCommDbTableExtension::InsertConnPrefRecordL -> Entry Point")); + + CMDBRecordSetBase* recSet = GetRecordSetL(); + + // store newly created record + aConnPref->SetRecordId(KCDNewRecordRequest); + + aConnPref->StoreL(aDbs); + User::LeaveIfError(recSet->iRecords.Append(aConnPref)); + + iCurrentRecord = recSet->iRecords[recSet->iRecords.Count()-1]; + iInsertedRecords.Insert(iCurrentRecord->RecordId(), KFirstRecord); + + TInt index = iDeletedRecords.Find(iCurrentRecord->RecordId()); + + // check if inserted record has the same record id as previously deleted record + if(index>=0) + { + iDeletedRecords.Remove(index); + } + + SortByRank(); + __FLOG_STATIC0(KLogComponent, KCommDbShim, _L("CCommDbTableExtension::InsertConnPrefRecordL -> Record Inserted")); + } + + +TBool CCommDbTableExtension::IsGenericRecord(TMDBElementId aElementId) const + { + const TMDBElementId tableType = (aElementId & KCDMaskShowRecordType); + return (tableType >= KCDInitialUDefRecordType); + } + +void CCommDbTableExtension::InsertRecordL(TBool aCopy, TUint32& aId, CMDBSession& aDbs, TBool aIsTemplate) +/** +Deletes the current record from commsdat and from queue. +Updates the value of record index. +*/ + { + CMDBRecordSetBase* recSet = GetRecordSetL(); + // storing empty string in order to get RecordId for newly inserted record + CMDBRecordBase* newRecord; + + if(aCopy) + { + CMDBRecordBase* record = GetCurrentRecordL(); + newRecord = CCDRecordBase::CreateCopyRecordL(*record); + CleanupStack::PushL(newRecord); + if(IsGenericRecord(newRecord->ElementId())) + { + newRecord->LoadL(aDbs); + } + } + else + { + newRecord = CCDRecordBase::RecordFactoryL(recSet->TypeId()); + CleanupStack::PushL(newRecord); + if(IsGenericRecord(newRecord->ElementId())) + { + newRecord->LoadL(aDbs); + } + } + + TBool removeHiddenMask = EFalse; + if(aIsTemplate) + { + // this will mark record as template record + newRecord->SetRecordId(KCDDefaultRecord); + if (! aDbs.IsSetAttributeMask(ECDHidden)) + { + aDbs.SetAttributeMask(ECDHidden); + removeHiddenMask = ETrue; + } + } + else + { + // this will give next valid record number + newRecord->SetRecordId(KCDNewRecordRequest); + } + + // create and store record placeholder + newRecord->StoreL(aDbs); + + if (removeHiddenMask) + { + aDbs.ClearAttributeMask(ECDHidden); + } + + // check if inserted record has the same record id as previously deleted record + TInt index = iDeletedRecords.Find(newRecord->RecordId()); + + if(index >= 0) + { + iDeletedRecords.Remove(index); + } + + // append inserted record + User::LeaveIfError(recSet->iRecords.Append(newRecord)); + CleanupStack::Pop(newRecord); + + iCurrentRecord = newRecord; + iInsertedRecords.Insert(iCurrentRecord->RecordId(), KFirstRecord); + SortById(); + + aId = newRecord->RecordId(); + } + +TInt CCommDbTableExtension::CancelRecordChanges(CMDBSession& aDbs) + { + TInt err = KErrNone; + if (!iRecordSetContainer) + { + return KErrNotFound; + } + + TRAP(err,iCurrentRecord->LoadL(aDbs)); + if (err != KErrNone) + { + // return to status prior to failure + __FLOG_STATIC1(KLogComponent, KCommDbShim, _L("CCommDbTableExtension::CancelRecordChanges failed to Refresh the data, Err=%d"),err); + return err; + } + + if (iInsertedRecords.Count()) + { + TInt index = FindValueInRecSet(iInsertedRecords[KFirstRecord]); + + if(index >= 0) + { + delete iRecordSetContainer->iRecords[index]; + iRecordSetContainer->iRecords.Remove(index); + iRecordSetContainer->iRecords.Compress(); + // reuse index variable + index = iRecordSetContainer->iRecords.Count(); + index ? iCurrentRecord = iRecordSetContainer->iRecords[index-1] : iCurrentRecord = NULL; + } + } + + ResetArrays(aDbs); + + return err; + } + +void CCommDbTableExtension::ResetArrays(CMDBSession& aSession) + { + if(!aSession.IsInTransaction()) + { + iInsertedRecords.Reset(); + iDeletedRecords.Reset(); + } + // else they will be reseted on Commit or Rolback Transaction + } + +void CCommDbTableExtension::ResetAndDestroyL() + { + GetRecordSetL()->iRecords.ResetAndDestroy(); + iCurrentRecord = NULL; + } + +void CCommDbTableExtension::DeleteCurrentRecordL(CMDBSession& aDbs, TBool aContainerOnly) +/** +Deletes the current record from commsdat and from queue. +Updates the value of record index. +*/ + { + // check for validity of current record through GetCurrentRecord call + CMDBRecordBase* currRec = GetCurrentRecordL(); + /* TODO: Add iShowHidden in conditions. This might not be necessary checking */ + /*if(iRecordIndex == 0) + { + // it is not possible to delete template record + User::Leave(KErrNotSupported); + }*/ + if(!aContainerOnly) + { + if (currRec->IsSetAttribute(ECDProtectedWrite)) + { + User::Leave(KErrAccessDenied); + } + + User::LeaveIfError(iDeletedRecords.Append(currRec->RecordId())); + + __FLOG_STMT(TInt count = iDeletedRecords.Count();) + __FLOG_STATIC1(KLogComponent, KCommDbShim, _L("CCommDbTableExtension::DeleteCurrentRecordL added to deleted record queue, as No:%d"), count); + + currRec->DeleteL(aDbs); + } + + TInt currIndex = iRecordSetContainer->iRecords.Find(currRec); + + iCurrentRecord = NULL; + + // If we just deleted the last or first non-deleted record then update the appropriate "backup" so that a next/prev + // will work + TInt probeIndex = currIndex; + iBeginingOfTableRecordBackup = NULL; + iEndOfTableRecordBackup = NULL; + if(!AdvanceIndexToPrevValidRecord(probeIndex)) + { + // Deleted first record; Next from here should move to first record + probeIndex = currIndex; + if(AdvanceIndexToNextValidRecord(probeIndex)) + { + iBeginingOfTableRecordBackup = iRecordSetContainer->iRecords[probeIndex]; + } + } + else + { + iBeginingOfTableRecordBackup = iRecordSetContainer->iRecords[probeIndex]; + } + probeIndex = currIndex; + if(!AdvanceIndexToNextValidRecord(probeIndex)) + { + // Deleted last record; Prev from here should move to last record + probeIndex = currIndex; + if(AdvanceIndexToPrevValidRecord(probeIndex)) + { + iEndOfTableRecordBackup = iRecordSetContainer->iRecords[probeIndex]; + } + } + else + { + iEndOfTableRecordBackup = iRecordSetContainer->iRecords[probeIndex]; + } + + if(!aContainerOnly) + { + // remove an entry from container + delete iRecordSetContainer->iRecords[currIndex]; + iRecordSetContainer->iRecords.Remove(currIndex); + iRecordSetContainer->iRecords.Compress(); + } + } + +void CCommDbTableExtension::SetRecordSet(CMDBRecordSetBase* aRecordSetContainer) + { + iRecordSetContainer = aRecordSetContainer; + TInt currIndex = iRecordSetContainer->iRecords.Count(); + + currIndex == 0 ? iCurrentRecord = NULL : iCurrentRecord = iRecordSetContainer->iRecords[0]; + + #ifdef _DEBUG + __FLOG_STATIC0(KLogComponent, KCommDbShim, _L("Start of Table Contents")); + CCDRecordBase* ptrTemp; + CMDBRecordBase* currRec; + CMDBRecordSetBase* recSet = static_cast(iRecordSetContainer); + TInt count = recSet->iRecords.Count(); + for(TInt i=0;iiRecords[i]; + ptrTemp = static_cast(currRec); + const TDesC& field = ptrTemp->iRecordName; + + __FLOG_STATIC3(KLogComponent, KCommDbShim, _L("Record[%d], RecordId:%d, RecordName:%S"), + i, currRec->RecordId(), &field); + } + __FLOG_STATIC0(KLogComponent, KCommDbShim, _L("End of Table Contents")); + #endif + }; + +CMDBRecordSetBase* CCommDbTableExtension::RecordSetFactoryL(const TDesC& aTableName, TBool preparePriming, CMDBSession& aDbs) + { + TMDBElementId recordSetId = 0; + CMDBRecordSetBase* recordSetContainer = NULL; + + if (aTableName.CompareF(TPtrC(KCDTypeNameConnectionPrefs)) == 0) + { + // connection preferance needs to be created via CommDbConnectionPref class + User::Leave(KErrNotSupported); + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameGlobalSettings)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdGlobalSettingsRecord); + recordSetId = KCDTIdGlobalSettingsRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameNetwork)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdNetworkRecord); + recordSetId = KCDTIdNetworkRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameLocation)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdLocationRecord); + recordSetId = KCDTIdLocationRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameIAP)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdIAPRecord); + recordSetId = KCDTIdIAPRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameWAPAccessPoint)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdWAPAccessPointRecord); + recordSetId = KCDTIdWAPAccessPointRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameDialOutISP)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdDialOutISPRecord); + recordSetId = KCDTIdDialOutISPRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameDialInISP)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdDialInISPRecord); + recordSetId = KCDTIdDialInISPRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameLANService)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdLANServiceRecord); + recordSetId = KCDTIdLANServiceRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameWLANServiceExt)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdWLANServiceExtRecord); + recordSetId = KCDTIdWLANServiceExtRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNamePANServiceExt)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdPANServiceExtRecord); + recordSetId = KCDTIdPANServiceExtRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameVPNService)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdVPNServiceRecord); + recordSetId = KCDTIdVPNServiceRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameDefaultWCDMA)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdDefaultWCDMARecord); + recordSetId = KCDTIdDefaultWCDMARecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameIncomingWCDMA)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdIncomingGprsRecord); + recordSetId = KCDTIdIncomingGprsRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameOutgoingWCDMA)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdOutgoingGprsRecord); + recordSetId = KCDTIdOutgoingGprsRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameModemBearer)) == 0 || aTableName.CompareF(TPtrC(OLD_MODEM_TABLE)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdModemBearerRecord); + recordSetId = KCDTIdModemBearerRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameLANBearer)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdLANBearerRecord); + recordSetId = KCDTIdLANBearerRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameVirtualBearer)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdVirtualBearerRecord); + recordSetId = KCDTIdVirtualBearerRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameWAPSMSBearer)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdWAPSMSBearerRecord); + recordSetId = KCDTIdWAPSMSBearerRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameWAPIPBearer)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdWAPIPBearerRecord); + recordSetId = KCDTIdWAPIPBearerRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameChargecard)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdChargecardRecord); + recordSetId = KCDTIdChargecardRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameProxies)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdProxiesRecord); + recordSetId = KCDTIdProxiesRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameSSProto)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdSSProtoRecord); + recordSetId = KCDTIdSSProtoRecord; + } + else if (aTableName.CompareF(TPtrC(KCDTypeNameAgentLookup)) == 0) + { + recordSetContainer = new (ELeave) CMDBRecordSet(KCDTIdAgentLookupRecord); + recordSetId = KCDTIdAgentLookupRecord; + } + else + { + // Create a temporary example of the user defined record, in order to do the lookup by name and get the Id back. + + CMDBGenericRecord* tempUserDefinedRecord = static_cast(CCDRecordBase::RecordFactoryL(0)); + CleanupStack::PushL(tempUserDefinedRecord); + tempUserDefinedRecord->InitializeL(aTableName, NULL); + tempUserDefinedRecord->LoadL(aDbs); + + // Get the Id that we're interested in... + recordSetId = tempUserDefinedRecord->TableId(); + + // ..and validate it. + if ((recordSetId & KCDMaskShowRecordType) < KCDInitialUDefRecordType) + { + User::Leave(KErrNotFound); + } + + + recordSetContainer = new (ELeave) CMDBRecordSet(recordSetId); + + if (preparePriming) + { + CleanupStack::PushL(recordSetContainer); + recordSetContainer->iRecords.AppendL(tempUserDefinedRecord); + CleanupStack::Pop(2); + } + else + { + CleanupStack::PopAndDestroy(tempUserDefinedRecord); + } + return recordSetContainer; + } + + if (preparePriming) + { + CleanupStack::PushL(recordSetContainer); + CMDBRecordBase* record = CCDRecordBase::RecordFactoryL(recordSetId); + TInt err = recordSetContainer->iRecords.Append(record); + if(err != KErrNone) + { + delete record; + User::Leave(err); + } + CleanupStack::Pop(recordSetContainer); + } + return recordSetContainer; + } + +void CCommDbTableExtension::SetRecordSetL(const TDesC& aTableName, CMDBSession& aDbs, TBool aPreparePriming, TBool aLoadTable, TBool aTemplate) +/** +Sets the value of the member iRecordSetContainer +*/ + { + __FLOG_STATIC1(KLogComponent, KCommDbShim, _L("SetRecordSetL -> TableName=%S"), &aTableName); + + // delete existing container + delete iRecordSetContainer; + iCurrentRecord = NULL; + + TBool removeHiddenMask = EFalse; + if (aTemplate) + { + // keeping BC compatibility + TRAPD(err, iRecordSetContainer = RecordSetFactoryL(aTableName, aPreparePriming, aDbs)); + if (err == KErrNotFound) + { + err = KErrArgument; + } + User::LeaveIfError(err); + iRecordSetContainer->iRecords[0]->SetAttributes(ECDHidden); + if (! aDbs.IsSetAttributeMask(ECDHidden)) + { + aDbs.SetAttributeMask(ECDHidden); + removeHiddenMask = ETrue; + } + } + else + { + iRecordSetContainer = RecordSetFactoryL(aTableName, aPreparePriming, aDbs); + } + + // load data + if (aLoadTable) + { + TRAPD(err, iRecordSetContainer->LoadL(aDbs)); + // if table is empty don't leave + if (err != KErrNone && err != KErrNotFound) + { + User::LeaveIfError(err); + } + #ifdef _DEBUG + else + { + __FLOG_STATIC0(KLogComponent, KCommDbShim, _L("Start of Table Contents")); + CCDRecordBase* ptrTemp; + CMDBRecordBase* currRec; + CMDBRecordSetBase* recSet = static_cast(iRecordSetContainer); + TInt count = recSet->iRecords.Count(); + for(TInt i=0;iiRecords[i]; + ptrTemp = static_cast(currRec); + const TDesC& field = ptrTemp->iRecordName; + + __FLOG_STATIC3(KLogComponent, KCommDbShim, _L("Record[%d], RecordId:%d, RecordName:%S"), + i, currRec->RecordId(), &field); + } + __FLOG_STATIC0(KLogComponent, KCommDbShim, _L("End of Table Contents")); + } + #endif + + UpdateLastCommitSeq(); + } + + if (removeHiddenMask) + { + aDbs.ClearAttributeMask(ECDHidden); + } + + + // reset the index + TInt currIndex = iRecordSetContainer->iRecords.Count(); + currIndex ? iCurrentRecord = iRecordSetContainer->iRecords[0] : iCurrentRecord = NULL; + } + + +CMDBRecordSetBase* CCommDbTableExtension::GetRecordSetL() +/** +Gets the value of the member iRecordIndex + +@return A wrapper for an SQL string combined with a text comparison mode. +*/ { + if (!iRecordSetContainer) + { + User::Leave(KErrNotFound); + } + return iRecordSetContainer; + } + +TInt CCommDbTableExtension::GetRecordSet(CMDBRecordSetBase*& aRecSet) + { + TInt ret = KErrNone; + if (!iRecordSetContainer) + { + ret = KErrNotFound; + } + else + { + aRecSet = iRecordSetContainer; + } + return ret; + } + +TInt CCommDbTableExtension::GetCurrentRecord(CMDBRecordBase*& aRecord) + { + TInt index(0); + TInt err = GetRecordSetIndex(index); + + aRecord = 0; + + if (err == KErrNone) + { + aRecord = iRecordSetContainer->iRecords[index]; + err = KErrNone; + } + + return err; + } + +CMDBRecordBase* CCommDbTableExtension::GetCurrentRecordL() + { + if(iCurrentRecord) + { + return iCurrentRecord; + } + + User::Leave(KErrNotFound); + + return NULL; + } + +TInt CCommDbTableExtension::GetRecordSetIndex(TInt &aIndex) +/** +Gets the value of the member iRecordIndex + +@return A wrapper for an SQL string combined with a text comparison mode. +*/ + { + TInt err = KErrNotFound; + + if(iRecordSetContainer) + { + if (iCurrentRecord) + { + aIndex = iRecordSetContainer->iRecords.Find(iCurrentRecord); + err = KErrNone; + } + } + + return err; + } + +TInt CCommDbTableExtension::GetRecordSetIndexL() +/** +Gets the value of the member iRecordIndex + +@return A wrapper for an SQL string combined with a text comparison mode. +*/ + { + if (iCurrentRecord) + { + User::Leave(KErrNotFound); + } + + return iRecordSetContainer->iRecords.Find(iCurrentRecord); + } + +void CCommDbTableExtension::RefreshDatabaseL(CMDBSession& aDbs) +/** +Refresh the container +*/ + { + if(iRecordSetContainer) + { + iRecordSetContainer->RefreshL(aDbs); + } + } + +CCommDbTableExtension::~CCommDbTableExtension() +/** +Deletes the memory allocated to the members iColSet, iQueryText and iAccess +*/ + { + delete iRecordSetContainer; + iInsertedRecords.Reset(); + iDeletedRecords.Reset(); + iCommitSeqProperty.Close(); + } + +TInt CCommDbTableExtension::CompareRecordsById(const CMDBRecordBase& aLeft, const CMDBRecordBase& aRight) +/** + +@param +@return +*/ + { + //We assume there can't be 2records with same record IDs + return (aLeft.RecordId()) < (aRight.RecordId()) ? -1 : 1; + } + +TInt CCommDbTableExtension::CompareRecordsByRank( + const CMDBRecordBase& aLeft, const CMDBRecordBase& aRight) +/** + +@param +@param +@return +*/ + { + return ( ((CCDConnectionPrefsRecord&)aLeft).iRanking < ((CCDConnectionPrefsRecord&)aRight).iRanking) ? -1 : 1; + } + +void CCommDbTableExtension::SortById() +/** + Sorting values in iRecordSetContainer by Id value +*/ + { + TLinearOrder order(CompareRecordsById); + if(iRecordSetContainer) + { + iRecordSetContainer->iRecords.Sort(order); + } + } + +void CCommDbTableExtension::SortByRank() +/** + +@param +@return +*/ + { + TLinearOrder order(CompareRecordsByRank); + if(iRecordSetContainer) + { + iRecordSetContainer->iRecords.Sort(order); + } + } + +TInt CCommDbTableExtension::GetTableAccess(RDbRowSet::TAccess &aAccess) + { + if( ! iRecordSetContainer) + return KErrNotFound; + + if (iRecordSetContainer->IsSetAttribute(ECDProtectedWrite)) + { + aAccess = RDbRowSet::EReadOnly; + } + else + { + aAccess = RDbRowSet::EUpdatable; + } + + return KErrNone; + } + +void CCommDbTableExtension::CommitTransaction() + { + __FLOG_STATIC0(KLogComponent, KCommDbShim, _L("CCommDbTableExtension::CommitTransaction()")); + // remove flags since everything is valid + iInsertedRecords.Reset(); + iDeletedRecords.Reset(); + } + +void CCommDbTableExtension::RollBackTransaction() + { + __FLOG_STATIC0(KLogComponent, KCommDbShim, _L("CCommDbTableExtension::RollBackTransaction()")); + + // we don't need to keep inserted records anymore + TInt index; + for (TInt i = 0; i < iInsertedRecords.Count(); ++i) + { + index = FindValueInRecSet(iInsertedRecords[i]); + + if(index >= 0) + { + delete iRecordSetContainer->iRecords[index]; + iRecordSetContainer->iRecords.Remove(index); + } + } + iRecordSetContainer->iRecords.Compress(); + index = iRecordSetContainer->iRecords.Count(); + index ? iCurrentRecord = iRecordSetContainer->iRecords[index-1] : iCurrentRecord = NULL; + + // remove flags since everything is returned to begining + iInsertedRecords.Reset(); + iDeletedRecords.Reset(); + } + +TInt CCommDbTableExtension::GetCurrentRecordIndex() const + { + // If iCurrentRecord is valid then start with it, else start with most recently deleted record + const TInt numRecs = iRecordSetContainer->iRecords.Count(); + TInt idx = -1; + const TInt numDeleted = iDeletedRecords.Count(); + if(iCurrentRecord) + { + ASSERT(iDeletedRecords.Find(iCurrentRecord->RecordId()) == KErrNotFound); // dbl-check it isn't somehow deleted too + idx = iRecordSetContainer->iRecords.Find(iCurrentRecord); + ASSERT(idx >= 0); + } + else + { + if(numDeleted > 0) + { + idx = FindValueInRecSet(iDeletedRecords[numDeleted - 1]); + } + else + { + // No deleted records either, special case is going to -1, ie preparatory to advancing to first record + } + } + return idx; + } + +TBool CCommDbTableExtension::AdvanceIndexToNextValidRecord(TInt& aIdx) const + { + // Advance to the next visible & not deleted in this view; hidden may not be visible + const TInt numRecs = iRecordSetContainer->iRecords.Count(); + TInt idx; + for(idx = aIdx + 1; idx < numRecs; ++idx) + { + CMDBRecordBase* rec = iRecordSetContainer->iRecords[idx]; + if(iDeletedRecords.Find(rec->RecordId()) >= 0) + { + continue; // deleted are always invisible + } + if(iShowHidden || !rec->IsSetAttribute(ECDHidden)) + { + break; + } + } + if(idx < numRecs) + { + aIdx = idx; + return ETrue; + } + return EFalse; + } + +TBool CCommDbTableExtension::AdvanceIndexToPrevValidRecord(TInt& aIdx) const + { + // Advance to the previous visible & not deleted in this view; hidden may not be visible + TInt idx; + for(idx = aIdx - 1; idx >= 0; --idx) + { + CMDBRecordBase* rec = iRecordSetContainer->iRecords[idx]; + if(iDeletedRecords.Find(rec->RecordId()) >= 0) + { + continue; // deleted are always invisible + } + if(iShowHidden || !rec->IsSetAttribute(ECDHidden)) + { + break; + } + } + if(idx >= 0) + { + aIdx = idx; + return ETrue; + } + return EFalse; + } + +TBool CCommDbTableExtension::FindFirstNextValidRecord(TBool aResetToStart) + { + TInt idx; + if(aResetToStart) + { + iCurrentRecord = NULL; + idx = -1; + } + else + { + idx = GetCurrentRecordIndex(); + } + if(!AdvanceIndexToNextValidRecord(idx)) + { + return EFalse; + } + iCurrentRecord = iRecordSetContainer->iRecords[idx]; + __FLOG_STMT(TInt recNo = iRecordSetContainer->iRecords.Find(iCurrentRecord);) + __FLOG_STATIC1(KLogComponent, KCommDbShim, _L("GotoNextRecord -> CurrentRecord is RecNo:%d"), recNo); + return ETrue; + } + +TBool CCommDbTableExtension::FindFirstPrevValidRecord() + { + TInt idx = GetCurrentRecordIndex(); + if(!AdvanceIndexToPrevValidRecord(idx)) + { + return EFalse; + } + iCurrentRecord = iRecordSetContainer->iRecords[idx]; + __FLOG_STMT(TInt recNo = iRecordSetContainer->iRecords.Find(iCurrentRecord);) + __FLOG_STATIC1(KLogComponent, KCommDbShim, _L("GotoPreviousRecord -> CurrentRecord is RecNo:%d"), recNo); + return ETrue; + } + +TInt CCommDbTableExtension::FindValueInRecSet(TInt aValue) const + { + // in case of insertion remove inserted record + for(TInt index=0; index < iRecordSetContainer->iRecords.Count();index++) + { + if(iRecordSetContainer->iRecords[index]->RecordId() == aValue) + { + return index; + } + } + + return KErrNotFound; + } + +//-------------------------------------------------------------------- +// CCommsDatabaseImpl +//-------------------------------------------------------------------- + +CCommsDatabaseImpl::CCommsDatabaseImpl() + :iHaveCheckedGSTableExists(EFalse), iDbs(NULL) + { + + } +CCommsDatabaseImpl::~CCommsDatabaseImpl() + { + iTableViews.ResetAndDestroy(); + iConnPrefViews.ResetAndDestroy(); + + //Cancel any pending notifications + CancelRequestNotification(); + + + // do not delete iDbs before destroying the view arrays above + delete iDbs; + } + +void CCommsDatabaseImpl::RegisterViewL(CCommsDbTableView* aTable) + { + iTableViews.AppendL(aTable); + } + +void CCommsDatabaseImpl::UnRegisterView(CCommsDbTableView* aTable) + { + TInt index = iTableViews.Find(aTable); + if (index>=0) + { + iTableViews.Remove(index); + } + } + +void CCommsDatabaseImpl::RegisterConnPrefViewL(CCommsDbConnectionPrefTableView* aTable) + { + iConnPrefViews.AppendL(aTable); + } + +void CCommsDatabaseImpl::UnRegisterConnPrefView(CCommsDbConnectionPrefTableView* aTable) + { + TInt index = iConnPrefViews.Find(aTable); + if (index>=0) + { + iConnPrefViews.Remove(index); + } + } + +void CCommsDatabaseImpl::CheckGlobalSettingsTableExistsL() +/** + Important, this function requires 'ECapabilityWriteDeviceData' capability. +*/ + { + // We only need to check that the global settings table exists once, because if it doesn't we'll create a placeholder. + if (!iHaveCheckedGSTableExists) + { + // Ensure that a global record always exists. + + CCDGlobalSettingsRecord* pNewGlobalRecord = static_cast(CCDRecordBase::RecordFactoryL(KCDTIdGlobalSettingsRecord)); + CleanupStack::PushL(pNewGlobalRecord); + + const TInt KGlobalSettingsRecordID = 1; + + pNewGlobalRecord->SetRecordId(KGlobalSettingsRecordID); + + TRAPD(err, pNewGlobalRecord->StoreL(*iDbs)); + if (!(err == KErrNone || err == KErrAlreadyExists)) + { + User::Leave(err); + } + + iHaveCheckedGSTableExists = ETrue; + + CleanupStack::PopAndDestroy(pNewGlobalRecord); + } + } + +TInt CCommsDatabaseImpl::RequestNotification(TRequestStatus& aStatus) + { + TInt ret(KErrNone); + if(!iShimNotifier.Handle()) + { + ret = iShimNotifier.Connect(); //Also starts the server if not running allready + } + + if(ret == KErrNone) + { + iShimNotifier.RequestNotification(aStatus); + } + + return ret; + } + +void CCommsDatabaseImpl::CancelRequestNotification() + { + if(iShimNotifier.Handle()) + { + iShimNotifier.CancelNotification(); + } + iShimNotifier.Close(); + } + + + +// ------------------------ CommDb Shim Utils ------------------------- + +/** +@internalTechnology +*/ +typedef struct + { + const TText* iTableName; + TUint iTableId; + } TCommDbTableMapping; + +/** +Number of mappings in the table +@internalTechnology +*/ +const TInt KTableMappingsCount = 30; + +/** +Mappings between legacy commdb table names and the commsdat table element id's +@internalTechnology +*/ +const TCommDbTableMapping tableMappings[KTableMappingsCount] = + { + { KCDTypeNameModemBearer, CommsDat::KCDTIdModemBearerRecord }, + { KCDTypeNameLANBearer, CommsDat::KCDTIdLANBearerRecord }, + { KCDTypeNameVirtualBearer, CommsDat::KCDTIdVirtualBearerRecord }, + { KCDTypeNameWAPSMSBearer, CommsDat::KCDTIdWAPSMSBearerRecord }, + { KCDTypeNameWAPIPBearer, CommsDat::KCDTIdWAPIPBearerRecord }, + { KCDTypeNameGlobalSettings, CommsDat::KCDTIdGlobalSettingsRecord }, + { KCDTypeNameConnectionPrefs, CommsDat::KCDTIdConnectionPrefsRecord }, + { KCDTypeNameNetwork, CommsDat::KCDTIdNetworkRecord }, + { KCDTypeNameLocation, CommsDat::KCDTIdLocationRecord }, + { KCDTypeNameIAP, CommsDat::KCDTIdIAPRecord }, + { KCDTypeNameWAPAccessPoint, CommsDat::KCDTIdWAPAccessPointRecord }, + { KCDTypeNameDialOutISP, CommsDat::KCDTIdDialOutISPRecord }, + { KCDTypeNameDialInISP, CommsDat::KCDTIdDialInISPRecord }, + { KCDTypeNameLANService, CommsDat::KCDTIdLANServiceRecord }, + { KCDTypeNameWLANServiceExt, CommsDat::KCDTIdWLANServiceExtRecord }, + { KCDTypeNameVPNService, CommsDat::KCDTIdVPNServiceRecord }, + { KCDTypeNameOutgoingWCDMA, CommsDat::KCDTIdOutgoingGprsRecord }, + { KCDTypeNameIncomingWCDMA, CommsDat::KCDTIdIncomingGprsRecord }, + { KCDTypeNamePANServiceExt, CommsDat::KCDTIdPANServiceExtRecord }, + { KCDTypeNameDefaultWCDMA, CommsDat::KCDTIdDefaultWCDMARecord }, + { KCDTypeNameChargecard, CommsDat::KCDTIdChargecardRecord }, + { KCDTypeNameProxies, CommsDat::KCDTIdProxiesRecord }, + { KCDTypeNameSSProto, CommsDat::KCDTIdSSProtoRecord }, + { KCDTypeNameAgentLookup, CommsDat::KCDTIdAgentLookupRecord }, + { KCDTTypeNameEAPSec, CommsDat::KCDTIdEAPSecRecord }, + { KCDTTypeNameTunEAP, CommsDat::KCDTIdTunEAPRecord }, + { KCDTTypeNameEAPTLS, CommsDat::KCDTIdEAPTLSRecord }, + { KCDTTypeNameLEAP, CommsDat::KCDTIdLEAPRecord }, + + // These didn't exist in Commdb and don't have textual names + // KCDTIdAccessPointRecord + // KCDTIdIapPrioritySelectionPolicyRecord + // KCDTIdWCDMAPacketServiceRecord + // KCDTIdUmtsR99QoSAndOnTableRecord + }; + + + +/** +@internalTechnology +*/ +EXPORT_C CommsDat::TMDBElementId CommDbShimUtil::GetElementIdFromFieldNameL(const TDesC& aFieldName) + { + _LIT(KSlashCharacter, "\\"); + TInt slashPos = aFieldName.Find(KSlashCharacter); + if(slashPos < 0) + { + User::Leave(KErrArgument); + } + TPtrC tableName(aFieldName.Ptr(), slashPos); + TPtrC fieldName(aFieldName.Ptr() + slashPos + 1, aFieldName.Length() - slashPos - 1); + + CMDBRecordBase* record = NULL; + TInt i = 0; + while (record == NULL && i < KTableMappingsCount) + { + if (!tableName.CompareF(TPtrC(tableMappings[i].iTableName))) + { + record = CCDRecordBase::RecordFactoryL(tableMappings[i].iTableId); + CleanupStack::PushL(record); + break; + } + i++; + } + + TMDBElementId elementId; + if (!record) + { + // Create a temporary example of the user defined record, in order to do the lookup by name and get the Id back. + CMDBGenericRecord* tempUserDefinedRecord = static_cast(CCDRecordBase::RecordFactoryL(0)); + CleanupStack::PushL(tempUserDefinedRecord); + + tempUserDefinedRecord->InitializeL(tableName, NULL); + + CMDBSession* dbs = CMDBSession::NewLC(KCDVersion1_1); + tempUserDefinedRecord->LoadL(*dbs); + + // Get the Id that we're interested in... + TUint tableId = tempUserDefinedRecord->TableId(); + + CleanupStack::PopAndDestroy(); // dbs + CleanupStack::PopAndDestroy(); // tempUserDefinedRecord + + record = CCDRecordBase::RecordFactoryL(tableId); + CleanupStack::PushL(record); + } + + TInt tempType; + CMDBElement* field = record->GetFieldByNameL(fieldName, tempType); + elementId = field->ElementId(); + CleanupStack::PopAndDestroy(); // record + return elementId; + } + +//EOF