First public contribution.
2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
15 * Implements a read-only interface for UPS Database.
27 #include "upscommon.h"
29 using namespace UserPromptService;
36 CDecisionView::CDecisionView():CActive(EPriorityStandard)
38 Constructor for decision view object.
41 CActiveScheduler::Add(this);
46 CDecisionView::~CDecisionView()
48 Destructor for the decision view object.
57 EXPORT_C CDecisionView* CDecisionView::NewLC()
59 Creates a decision view object. The function leaves, if creation of the view object fails.
61 @return A pointer to the newly allocated view object, if creation is successful.
62 The pointer is also put onto the cleanup stack.
65 CDecisionView* self = new(ELeave) CDecisionView();
66 CleanupStack::PushL(self);
71 void CDecisionView::DoCancel()
77 User::RequestComplete(iClientStatus, KErrCancel);
82 TInt CDecisionView::RunError(TInt aError)
87 User::RequestComplete(iClientStatus, aError);
93 void CDecisionView::RunL()
96 TInt status = iStatus.Int();
97 User::LeaveIfError(status);
101 iDbView.Evaluate(iStatus);
106 User::RequestComplete(iClientStatus,status);
111 EXPORT_C void CDecisionView::EvaluateView(TRequestStatus& aStatus)
113 Performs all steps of the view evaluation, returning immediately and
114 signalling when all steps are complete.
116 @param aStatus The request status used to contain completion information for the function.
117 On completion, the status value should be interpreted as follows:
118 0, evaluation is complete.< 0, an error code.
121 __ASSERT_ALWAYS(!IsActive(), User::Panic(KDecisionViewPanic,KErrInUse));
123 aStatus = KRequestPending;
124 iClientStatus = &aStatus;
126 iDbView.Evaluate(iStatus);
133 CDecisionRecord* CDecisionView::GenerateRecordL(RDbRowSet& aRowSet, CDbColSet* aColSet)
135 Retrieves all decision record fileds from the given rowset and generates
136 a decision record from these information.
138 @param aRowSet A database rowset object.
139 @param aColSet A database column set object.
141 @return The newly,created decision record if it is successful; otherwise, leaves.
144 TSecureId clientSid(aRowSet.ColUint32(aColSet->ColNo(KColClientSid))); //Client Secure Id
145 TSecureId serverId = TSecureId(aRowSet.ColUint32(aColSet->ColNo(KColServerSid))); //Service Secure Id
146 TUid evaluatorId = TUid::Uid(aRowSet.ColUint32(aColSet->ColNo(KColEvaluatorId))); //Evaluator Uid
147 TUid serviceId = TUid::Uid(aRowSet.ColUint32(aColSet->ColNo(KColServiceId))); //Service Uid
148 TPtrC8 fingerprint = aRowSet.ColDes8(aColSet->ColNo(KColFingerprint)); //Fingerprint
149 TPtrC8 clientEntity = aRowSet.ColDes8(aColSet->ColNo(KColClientEntity)); //Client Entity
150 TInt8 result = aRowSet.ColInt8(aColSet->ColNo(KColResult)); //Result
151 TUint16 ver = aRowSet.ColUint16(aColSet->ColNo(KColMajorPolicyVersion)); //Major Policy Version
152 TUint32 recordId = aRowSet.ColUint32(aColSet->ColNo(KColRecordId)); //Unique Record ID
153 TUint32 evaluatorInfo = aRowSet.ColUint32(aColSet->ColNo(KColEvaluatorInfo)); //EvaluatorInfo
155 //a stream is used to read long columns
156 TDbColNo col = aColSet->ColNo(KColDescription);
157 TInt len = aRowSet.ColLength(col);
160 CleanupClosePushL(description);
161 description.CreateL(len);
163 RDbColReadStream str;
164 str.OpenLC(aRowSet,col);
165 str.ReadL(description,len);
167 CleanupStack::PopAndDestroy(&str);
169 CDecisionRecord *retval = CDecisionRecord::NewL(clientSid,evaluatorId,serviceId,serverId,fingerprint,
170 clientEntity,description,result,ver,evaluatorInfo,recordId);
172 CleanupStack::PopAndDestroy(&description);
177 EXPORT_C CDecisionRecord* CDecisionView::NextDecisionL()
179 Moves the cursor to the next row in the view object and returns the current decision row.
180 If there are no more rows, the cursor is positioned to the end of the view object.
182 @return 0, If the cursor is positioned at the end of the view. Otherwise, current record.
185 CDecisionRecord *record(0);
190 record = GenerateRecordL(iDbView,iColSet);
206 CDecisionDb::CDecisionDb()
208 Constructor for read-only decision database object
215 CDecisionDb::~CDecisionDb()
217 Destructor for read-only decision database object
223 const TDesC* CDecisionDb::GetComparisonOperator(const TUint32& aFlag) const
225 Finds and returns the correspondent comparision operator string.
230 UserPromptService::TComparisonOp op = static_cast<UserPromptService::TComparisonOp>(aFlag & 0xFFFF0000);
233 case UserPromptService::EEqual:
235 return &KSQLQueryEqual;
237 case UserPromptService::ENotEqual:
239 return &KSQLQueryNotEqual;
241 case UserPromptService::ELessThan:
243 return &KSQLQueryLessThan;
245 case UserPromptService::EGreaterThan:
247 return &KSQLQueryGreaterThan;
249 case UserPromptService::ELessThanOrEqual:
251 return &KSQLQueryLessThanOrEqual;
253 case UserPromptService::EGreaterThanOrEqual:
255 return &KSQLQueryGreaterThanOrEqual;
258 return &KSQLQueryEqual;
262 void CDecisionDb::CreateSqlStatementLC(CDecisionFilter& aFilter, RBuf& aSql)
264 Creates an sql statement from a given filter.
266 @param aFilter A filter object used to create the SQL statement.
267 @param aSql The newly created SQL statement.
270 //Estimate the maximum required buffer (maxLen) to save the sql statement.
271 //KSQLQueryBase must be in the statement at least.
272 TInt maxLen = KBaseSQLLength;
274 //Get the bits belonging to ID values (ClientSid,EvaluatorId,ServiceId,ServerSid)
275 TUint32 combinedFlags = (aFilter.iSetFlag[KPosClientSid] | aFilter.iSetFlag[KPosEvaluatorId] |
276 aFilter.iSetFlag[KPosServiceId] | aFilter.iSetFlag[KPosServerSid] |
277 aFilter.iSetFlag[KPosFingerprint] | aFilter.iSetFlag[KPosClientEntity]|
278 aFilter.iSetFlag[KPosMajorPolicyVersion] | aFilter.iSetFlag[KPosRecordId] |
279 aFilter.iSetFlag[KPosDescription] | aFilter.iSetFlag[KPosResult] |
280 aFilter.iSetFlag[KPosEvaluatorInfo]);
282 TUint16 flag = combinedFlags & 0x000006CF;
283 //Count how many bits are set, and add KMaxIntCondition for each set bit
287 maxLen += KMaxIntCondition;
289 //Get the bits belonging to string values (Fingerprint and ClientEntity)
290 flag = combinedFlags & 0x00000130;
291 //Count how many bits are set, and add KMaxStringCondition length for each set bit
295 maxLen += KMaxStringCondition;
298 //Allocate the estimated number of bytes for the sql statement
299 aSql.CreateL(maxLen);
300 aSql.CleanupClosePushL();
301 //First copy the basic SQL statement
302 aSql.AppendFormat(KSQLQueryBase,&KDecisionTable);
304 //If the filter is empty, there is no condition to add to the sql statement.
305 //So, simply return the base sql statement. In this case, all rows of
306 //the decision table are listed.
307 if(maxLen == KBaseSQLLength)
312 //Filter is not empty, add 'WHERE' key word into the statement
313 aSql.Append(KSQLQueryWhere);
315 TBool multiple = EFalse;
316 //Append server SID if exists in the filter
317 AppendQueryInteger(aFilter.iServerSid.iId, aSql, multiple, aFilter.iSetFlag[KPosServerSid], KSetServerSid, KColServerSid);
318 //Append service UID if exists in the filter
319 AppendQueryInteger(aFilter.iServiceId.iUid, aSql, multiple, aFilter.iSetFlag[KPosServiceId], KSetServiceId, KColServiceId);
320 //Append client SID if exists in the filter
321 AppendQueryInteger(aFilter.iClientSid.iId, aSql, multiple, aFilter.iSetFlag[KPosClientSid], KSetClientSid, KColClientSid);
322 //Append evaluator UID if exists in the filter
323 AppendQueryInteger(aFilter.iEvaluatorId.iUid, aSql, multiple, aFilter.iSetFlag[KPosEvaluatorId], KSetEvaluatorId, KColEvaluatorId);
324 //Append major policy version if exists in the filter
325 AppendQueryInteger(aFilter.iMajorPolicyVersion, aSql, multiple, aFilter.iSetFlag[KPosMajorPolicyVersion], KSetMajorPolicyVersion, KColMajorPolicyVersion);
326 //Append record id if exists in the filter
327 AppendQueryInteger(aFilter.iRecordId, aSql, multiple, aFilter.iSetFlag[KPosRecordId], KSetRecordId, KColRecordId);
328 //Append result if exists in the filter
329 AppendQueryInteger(aFilter.iResult, aSql, multiple, aFilter.iSetFlag[KPosResult], KSetResult, KColResult);
330 //Append evaluator info if exists in the filter
331 AppendQueryInteger(aFilter.iEvaluatorInfo, aSql, multiple, aFilter.iSetFlag[KPosEvaluatorInfo], KSetEvaluatorInfo, KColEvaluatorInfo);
332 //Append description if exists in the filter
333 AppendQueryStringL(*aFilter.iDescription, aSql, multiple, aFilter.iSetFlag[KPosDescription], KSetDescription, KColDescription);
335 //Append fingerprint if exists in the filter
336 //Convert 8-bit value to 16-bit
337 if(aFilter.iFingerprint)
339 HBufC* fp = HBufC::NewLC(aFilter.iFingerprint->Length());
340 TPtr ptrFp(fp->Des());
341 ptrFp.Copy(*aFilter.iFingerprint);
343 AppendQueryStringL(*fp, aSql, multiple, aFilter.iSetFlag[KPosFingerprint], KSetFingerprint, KColFingerprint);
344 CleanupStack::PopAndDestroy(fp);
347 //Append client entity if exists in the filter
348 //Convert 8-bit value to 16-bit
349 if(aFilter.iClientEntity)
351 HBufC* ce = HBufC::NewLC(aFilter.iClientEntity->Length());
352 TPtr ptrCe(ce->Des());
353 ptrCe.Copy(*aFilter.iClientEntity);
355 AppendQueryStringL(*ce, aSql, multiple, aFilter.iSetFlag[KPosClientEntity], KSetClientEntity, KColClientEntity);
356 CleanupStack::PopAndDestroy(ce);
361 void CDecisionDb::AppendQueryInteger(const TUint32& aValue, TDes& aSql, TBool& aMultiple, const TUint32& aFlag, const TUint32& aSetCol, const TDesC& aColName)
363 Appends an integer-based query key field to an SQL query string.
365 @param aValue The integer value which will be added to the query.
366 @param aSql The SQL query string.
367 @param aMultiple EFalse, if there is only one query key in the query string. Otherwise, ETrue.
368 @param aFlag The flag value corresponding to the query key.
369 @param aSetCol A constant value indicating whether or not a specific column is set.
370 @param aColName The column name of the query key.
377 aSql.Append(KSQLQueryAnd);
384 aSql.Append(aColName);
385 aSql.AppendFormat(KSQLQueryString,GetComparisonOperator(aFlag));
386 aSql.AppendFormat(KSQLQueryConditionInt,aValue);
391 void CDecisionDb::AppendQueryStringL(const TDesC& aValue, TDes& aSql, TBool& aMultiple, const TUint32& aFlag, const TUint32& aSetCol, const TDesC& aColName)
393 Appends an string query key to an SQL query string.
395 @param aValue The string value which will be added to the query.
396 @param aSql The SQL query string.
397 @param aMultiple EFalse, if there is only one query key in the query string. Otherwise, ETrue.
398 @param aFlag The flag value corresponding to the query key.
399 @param aSetCol A constant value indicating whether or not a specific column is set.
400 @param aColName The column name of the query key.
407 aSql.Append(KSQLQueryAnd);
414 aSql.Append(aColName);
416 if(aValue.Length() != 0)
418 //Scan for single quote
420 DoubleSingleQuotesL(aValue, dbValue);
421 dbValue.CleanupClosePushL();
423 aSql.AppendFormat(KSQLQueryString,GetComparisonOperator(aFlag));
424 aSql.AppendFormat(KSQLQueryConditionString,&dbValue);
426 CleanupStack::PopAndDestroy(&dbValue);
430 aSql.Append(KSQLQueryNull);
436 void CDecisionDb::DoubleSingleQuotesL(const TDesC& aSource, RBuf& aDestination)
438 Copies a source descriptor into a destination descriptor. If a single quote
439 character is found an extra single quote is copied to the destination.
440 Because, it is not possible to search for a string in SQL with single quote (').
442 @param aSource A source descriptor.
443 @param aDestination A destination descriptor.
446 _LIT(KSingleQuote,"'");
448 aDestination.Close();
450 if(aSource.FindF(KSingleQuote) > KErrNotFound)
452 const TUint16 KSingleQuoteHex = 0x27;
453 TInt len = aSource.Length();
455 //Define a temporary buffer and set its maximum size to twice of the original (if it contained all quotes!)
458 CleanupClosePushL(temp);
460 const TUint16 *ptrSrc = aSource.Ptr();
461 TUint16 *ptrDes = (TUint16 *)temp.Ptr();
465 for(srcIndex=0; srcIndex<len; ++srcIndex,++desIndex)
467 ptrDes[desIndex] = ptrSrc[srcIndex];
468 if(ptrSrc[srcIndex] == KSingleQuoteHex) //is single quote?
470 ptrDes[++desIndex] = ptrSrc[srcIndex];//add extra single quote
474 //Set the actual length
475 temp.SetLength(desIndex);
476 //Copy temp into destination. destination's maximum length is the same as the length of temp
477 aDestination.CreateL(temp);
478 CleanupStack::PopAndDestroy(&temp);
482 //there is no single quote, just copy it
483 aDestination.CreateL(aSource);
488 EXPORT_C CDecisionView *CDecisionDb::CreateViewL(CDecisionFilter& aFilter)
490 Generates an SQL view rowset to the decision table by using a filter.
491 The view rowset contains a set of rows which depend on the filter.
493 @param aFilter A filter object to query the decision database
494 @param aDecisionView A decision view object containing handle to the newly created SQL view rowset.
498 CreateSqlStatementLC(aFilter, sqlStatement);
500 CDecisionView *dbView = CDecisionView::NewLC();
502 User::LeaveIfError(dbView->iDbView.Prepare(iDatabase,TDbQuery(sqlStatement),TDbWindow::EUnlimited));
504 dbView->iColSet = dbView->iDbView.ColSetL();
506 CleanupStack::Pop(dbView);
507 CleanupStack::PopAndDestroy(&sqlStatement); //sqlStatement