Refactor DataControl request list.
[platform/framework/native/appfw.git] / src / app / FApp_SqlDataControlImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FApp_SqlDataControlImpl.cpp
20  * @brief       This is the implementation for the %_SqlDataControlImpl class.
21  */
22
23 #include <typeinfo>
24 #include <new>
25 #include <unique_ptr.h>
26
27 #include <appsvc/appsvc.h>
28
29 #include <FBaseInteger.h>
30 #include <FBaseString.h>
31 #include <FBaseLongLong.h>
32 #include <FBaseColIList.h>
33 #include <FBaseColIMap.h>
34 #include <FBaseColIMapEnumerator.h>
35 #include <FBaseRtIEventArg.h>
36 #include <FIoFile.h>
37 #include <FAppSqlDataControl.h>
38 #include <FAppISqlDataControlResponseListener.h>
39
40 #include <FBaseSysLog.h>
41
42 #include <FIo_DataControlResultSetEnumerator.h>
43
44 #include "FApp_AppControlManager.h"
45 #include "FApp_SqlDataControlImpl.h"
46 #include "FApp_AppArg.h"
47 #include "FApp_DataControlManager.h"
48
49 using namespace std;
50
51 using namespace Tizen::Base;
52 using namespace Tizen::Base::Collection;
53 using namespace Tizen::Base::Runtime;
54 using namespace Tizen::App;
55 using namespace Tizen::Io;
56
57 namespace Tizen { namespace App
58 {
59
60 static const int MAX_REQUEST_COUNT = 128;
61 static const int _MAX_ARGUMENT_SIZE = 16384; // 16KB
62
63 class _SqlDataControlEventArg
64         : public IEventArg
65 {
66 public:
67                 _SqlDataControlEventArg(_DataControlRequestType requestType, RequestId reqId, String providerId, String dataId,
68                                 _DataControlResultSetEnumerator* pResultSetEnum, long long insertRowId, bool providerResult, String* pErrorMsg)
69                         : __requestType(requestType)
70                         , __reqId(reqId)
71                         , __providerId(providerId)
72                         , __dataId(dataId)
73                         , __pResultSetEnum(pResultSetEnum)
74                         , __insertRowId(insertRowId)
75                         , __providerResult(providerResult)
76                         , __pErrorMsg(pErrorMsg)
77                 {
78                 }
79                 ~_SqlDataControlEventArg(void)
80                 {
81                         delete __pResultSetEnum;
82                         delete __pErrorMsg;
83                 }
84
85                 _DataControlRequestType __requestType;
86                 RequestId __reqId;
87                 String __providerId;
88                 String __dataId;
89                 _DataControlResultSetEnumerator* __pResultSetEnum;
90                 long long __insertRowId;
91                 bool __providerResult;
92                 String* __pErrorMsg;
93 };
94
95 class _SqlDataControlEvent
96         : public Event
97 {
98 protected:
99                 virtual void FireImpl(IEventListener& listener, const IEventArg& arg);
100 };
101
102 void
103 _SqlDataControlEvent::FireImpl(IEventListener& listener, const IEventArg& arg)
104 {
105         const _SqlDataControlEventArg* pArg = dynamic_cast<const _SqlDataControlEventArg*>(&arg);
106         if (pArg != null)
107         {
108                 ISqlDataControlResponseListener* pListener = dynamic_cast<ISqlDataControlResponseListener*> (&listener);
109                 if (pListener != null)
110                 {
111                         switch (pArg->__requestType)
112                         {
113                         case _DATACONTROL_REQUEST_TYPE_SQL_QUERY:
114                                 pListener->OnSqlDataControlSelectResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
115                                                 *(pArg->__pResultSetEnum), pArg->__providerResult, pArg->__pErrorMsg);
116                                 break;
117                         case _DATACONTROL_REQUEST_TYPE_SQL_INSERT:
118                                 pListener->OnSqlDataControlInsertResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
119                                                  pArg->__insertRowId, pArg->__providerResult, pArg->__pErrorMsg);
120                                 break;
121                         case _DATACONTROL_REQUEST_TYPE_SQL_UPDATE:
122                                 pListener->OnSqlDataControlUpdateResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
123                                                 pArg->__providerResult, pArg->__pErrorMsg);
124                                 break;
125                         case _DATACONTROL_REQUEST_TYPE_SQL_DELETE:
126                                 pListener->OnSqlDataControlDeleteResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
127                                                 pArg->__providerResult, pArg->__pErrorMsg);
128                                 break;
129                         default:
130                                 break;
131                         }
132                 }
133         }
134 }
135
136 // private
137 _SqlDataControlImpl::_SqlDataControlImpl(void)
138         : __appId(L"")
139         , __providerId(L"")
140         , __access(_DATACONTROL_ACCESS_UNDEFINED)
141         , __pPreviousListener(null)
142         , __pSqlDataControlEvent(null)
143 {
144 }
145
146 _SqlDataControlImpl::~_SqlDataControlImpl(void)
147 {
148         delete __pSqlDataControlEvent;
149 }
150
151 _SqlDataControlImpl*
152 _SqlDataControlImpl::GetInstance(SqlDataControl& dc)
153 {
154         return dc.__pSqlDataControlImpl;
155 }
156
157 const _SqlDataControlImpl*
158 _SqlDataControlImpl::GetInstance(const SqlDataControl& dc)
159 {
160         return dc.__pSqlDataControlImpl;
161 }
162
163 result
164 _SqlDataControlImpl::StartSqlDataControl(int type, const IList* pDataList, int* pReq)
165 {
166         result r = E_SUCCESS;
167
168         int req = -1;
169         _AppControlManager* pAppManagerImpl = _AppControlManager::GetInstance();
170
171         // Check the request count of DataControl operation
172         int count = pAppManagerImpl->GetLaunchRequestCount();
173         SysLog(NID_APP, "Current launch request count: %d", count);
174
175         SysTryReturnResult(NID_APP, count < MAX_REQUEST_COUNT, E_MAX_EXCEEDED, "The number of requests has exceeded the maximum limit.");
176
177         _AppArg* pArg = new (std::nothrow) _AppArg;  // XXX: pArg will be released in _AppManagerImpl::LaunchApp().
178         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "insufficient memory");
179
180         pArg->Construct(*this, static_cast <_DataControlRequestType>(type), pDataList);
181
182         if (__pSqlDataControlEvent)
183         {
184                 // reqId is system-wide id because the bundle is system-wide.
185
186                 _DataControlManager* pDcMgr = _DataControlManager::GetInstance();
187                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pAppManagerImpl, pArg, SqlDataControlCallback, pDcMgr, -1);
188                 req = reqObj.GetRequestNumber();
189                 pDcMgr->AddEvent(req, __pSqlDataControlEvent);
190                 r = pAppManagerImpl->LaunchApp(__appId, pArg, req);
191                 SysTryCatch(NID_APP, r == E_SUCCESS, reqObj.Invalidate(), r, "[%s] Propagating.", GetErrorMessage(r));
192
193                 if (pReq)
194                 {
195                         *pReq = req;
196                 }
197         }
198         else
199         {
200                 r = pAppManagerImpl->LaunchApp(__appId, pArg);
201                 delete pArg;
202         }
203
204 CATCH:
205         return r;
206 }
207
208 result
209 _SqlDataControlImpl::Select(const String& dataId, const IList* pColumnList, const String* pWhere,
210                 const String *pOrder, RequestId& reqId, int pageNo, int countPerPage)
211 {
212         SysTryReturnResult(NID_APP, pageNo > 0, E_INVALID_ARG, "The specified pageNo parameter is less than 1");
213         SysTryReturnResult(NID_APP, countPerPage > 0, E_INVALID_ARG, "The specified countPerPage parameter is less than 1");
214         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_READ) > 0, E_ILLEGAL_ACCESS,
215                         "The SELECT query is not permitted by DataControl provider.");
216
217         const String* pColumn = null;
218         int id = 0;
219         result r = E_SUCCESS;
220         SysLog(NID_APP, "[DC_CALLER] SqlDataControl SELECT");
221
222         ArrayList* pArgList = new ArrayList();
223         pArgList->Construct();
224
225         pArgList->Add(*(new String(dataId))); // list(0): data ID
226         long long argSize = dataId.GetLength() * sizeof(wchar_t);
227
228         if (pColumnList != null)
229         {
230                 int columnCount = pColumnList->GetCount();
231                 SysTryCatch(NID_APP, columnCount > 0, r = E_INVALID_ARG, E_INVALID_ARG,
232                                 "[E_INVALID_ARG] The specified pColumnList parameter is empty.");
233
234                 pArgList->Add(*(new String(Integer::ToString(columnCount)))); // list(1): selected column count
235                 SysLog(NID_APP, "[DC_CALLER] selected column count: %d", columnCount);
236
237                 int i = 0;
238                 while (i < columnCount) // list(2): column list
239                 {
240                         pColumn = dynamic_cast< const String* >(pColumnList->GetAt(i));
241                         SysTryCatch(NID_APP, pColumn != null, r = E_INVALID_ARG, E_INVALID_ARG,
242                                         "[E_INVALID_ARG] The object is not String class.");
243
244                         pArgList->Add(*(new String(*pColumn)));
245                         argSize += pColumn->GetLength() * sizeof(wchar_t);
246                         SysLog(NID_APP, "[DC_CALLER] column[%d]: %ls", i, pColumn->GetPointer());
247                         i++;
248                 }
249         }
250         else
251         {
252                 pArgList->Add(*(new String(L"NULL")));
253         }
254
255         if (pWhere != null)     // list(3): where clause
256         {
257                 pArgList->Add(*(new String(*pWhere)));
258                 argSize += pWhere->GetLength() * sizeof(wchar_t);
259                 SysLog(NID_APP, "[DC_CALLER] pWhere: %ls", pWhere->GetPointer());
260         }
261         else
262         {
263                 pArgList->Add(*(new String(L"NULL")));
264         }
265
266         if (pOrder != null)     // list(4): order clause
267         {
268                 pArgList->Add(*(new String(*pOrder)));
269                 argSize += pOrder->GetLength() * sizeof(wchar_t);
270                 SysLog(NID_APP, "[DC_CALLER] pOrder: %ls", pOrder->GetPointer());
271         }
272         else
273         {
274                 pArgList->Add(*(new String(L"NULL")));
275         }
276         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
277                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
278
279         pArgList->Add(*(new String(Integer::ToString(pageNo)))); // list(5): page number
280
281         pArgList->Add(*(new String(Integer::ToString(countPerPage)))); // list(6): count per page
282
283         r = StartSqlDataControl(_DATACONTROL_REQUEST_TYPE_SQL_QUERY, pArgList, &id);
284         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
285
286         reqId = static_cast< RequestId >(id);
287
288         SysLog(NID_APP, "[DC_CALLER] dataId: %ls, pColumnList: 0x%x, pWhere: 0x%x, pOrder: 0x%x, reqId: %d, pageNo: %d, countPerPage: %d",
289                         dataId.GetPointer(), pColumnList, pWhere, pOrder, reqId, pageNo, countPerPage);
290
291         // fall through
292 CATCH:
293         pArgList->RemoveAll(true);
294         delete pArgList;
295
296         return r;
297 }
298
299 result
300 _SqlDataControlImpl::SqlDataControlCallback(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop)
301 {
302         ArrayList* pResultList = null;
303         ArrayList* pOrigList = null;
304         String* pResult = null;
305         String* pRequestType = null;
306         String* pReqId = null;
307         String* pProviderId = null;
308         String* pDataId = null;
309         String* pErrorMessage = null;
310         String* pErrorMsg = null;
311         String* pTmpPath = null;
312         String* pInsertRowId = null;
313         _DataControlResultSetEnumerator* pResultSetEnum = null;
314         int requestType = 0;
315         int callerReqId = -1;
316         int providerRes = 0;
317         bool providerResult = true;
318         bundle* origBundle = null;
319         bundle* resBundle = null;
320         _SqlDataControlEventArg* pEventArg = null;
321         result r = E_SUCCESS;
322
323         SysTryReturnResult(NID_APP, pResArg != null, E_INVALID_ARG, "Empty result callback.");
324         SysLog(NID_APP, "appsvc result value: %d", res);
325
326         resBundle = pResArg->GetBundle();
327         if (resBundle)
328         {
329                 const char* pCallerReqId = appsvc_get_data(resBundle, OSP_K_REQUEST_ID);
330                 callerReqId = atoi(pCallerReqId);
331                 _DataControlManager* pDcMgr = static_cast< _DataControlManager* >(data);
332                 _SqlDataControlEvent* pSqlDataControlEvent = dynamic_cast< _SqlDataControlEvent* >(pDcMgr->GetEvent(callerReqId));
333
334                 if (pSqlDataControlEvent != null && typeid(pSqlDataControlEvent) == typeid(_SqlDataControlEvent*))
335                 {
336                         const char* p = null;
337
338                         // result list
339                         pResultList = _AppArg::GetListN(resBundle, OSP_K_ARG);
340                         SysTryCatch(NID_APP, pResultList, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
341
342                         pResult = dynamic_cast <String*>(pResultList->GetAt(0));
343                         SysTryCatch(NID_APP, pResult, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
344                         Integer::Parse(*pResult, providerRes);
345                         providerResult = static_cast< bool >(providerRes);
346
347                         pErrorMessage = dynamic_cast< String* >(pResultList->GetAt(1));
348                         SysTryCatch(NID_APP, pErrorMessage, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
349                         pErrorMsg = new (std::nothrow) String(*pErrorMessage);
350                         SysTryCatch(NID_APP, pErrorMsg, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
351                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
352
353                         origBundle = pArg->GetBundle();
354
355                         // request info
356                         p = appsvc_get_data(resBundle, OSP_K_DATACONTROL_REQUEST_TYPE);
357                         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
358                         pRequestType = new (std::nothrow) String(p);
359                         SysTryCatch(NID_APP, pRequestType, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
360                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
361                         Integer::Parse(*pRequestType, requestType);
362
363
364                         p = appsvc_get_data(resBundle, OSP_K_DATACONTROL_PROVIDER);
365                         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
366                         pProviderId = new (std::nothrow) String(p);
367                         SysTryCatch(NID_APP, pProviderId, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
368                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
369
370                         p = appsvc_get_data(resBundle, OSP_K_DATACONTROL_DATA);
371                         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
372                         pDataId = new (std::nothrow) String(p);
373                         SysTryCatch(NID_APP, pDataId, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
374                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
375
376 #if 0
377                         SysLog(NID_APP, "providerResult: %ld, requestType: %d, reqId: %d, providerId: %ls, dataId: %ls, errorMsg: %ls ",
378                                         providerRes, requestType, reqId, pProviderId->GetPointer(), pDataId->GetPointer(), pErrorMsg->GetPointer());
379 #else
380                         SysLog(NID_APP, "providerResult: %ld, requestType: %d, reqId: %d, providerId: %ls, dataId: %ls, errorMsg: %ls ",
381                                         providerRes, requestType, callerReqId, pProviderId->GetPointer(), pDataId->GetPointer(), pErrorMsg->GetPointer());
382 #endif
383
384                         switch (static_cast <_DataControlRequestType>(requestType))
385                         {
386                         case _DATACONTROL_REQUEST_TYPE_SQL_QUERY:
387                         {
388                                 pResultSetEnum = new (std::nothrow) _DataControlResultSetEnumerator;
389                                 SysTryCatch(NID_APP, pResultSetEnum, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
390                                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
391
392                                 if (providerResult == true)
393                                 {
394                                         pTmpPath = dynamic_cast< String* >(pResultList->GetAt(2)); // result list[2]
395                                         if (pTmpPath == null)
396                                         {
397                                                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] invalid result");
398                                                 delete pResultSetEnum;
399                                                 goto CATCH;
400                                         }
401
402                                         SysLog(NID_APP, "tempPath: %ls", pTmpPath->GetPointer());
403                                         if (pTmpPath->Equals(L"NoResultSet", true) == false) // Result set exists
404                                         {
405                                                 pResultSetEnum->SetPath(*pTmpPath);
406                                         }
407                                 }
408
409                                 pEventArg = new (std::nothrow) _SqlDataControlEventArg(_DATACONTROL_REQUEST_TYPE_SQL_QUERY, static_cast <RequestId>(callerReqId),
410                                                 *pProviderId, *pDataId, pResultSetEnum, -1, providerResult, pErrorMsg);
411                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
412                                 pSqlDataControlEvent->Fire(*pEventArg);
413
414                                 if (pTmpPath)
415                                 {
416                                         r = File::Remove(*pTmpPath); // Remove temporary file after releasing _ResultSetEnumerator.
417                                         SysTryLog(NID_APP, !IsFailed(r), "Failed to remove temp file for result set: %ls", pTmpPath->GetPointer());
418                                 }
419
420                                 break;
421                         }
422                         case _DATACONTROL_REQUEST_TYPE_SQL_INSERT:
423                         {
424                                 long long insertRowId = -1;
425                                 if (providerResult == true)
426                                 {
427                                         pInsertRowId = dynamic_cast< String* >(pResultList->GetAt(2)); // result list[2]
428                                         SysTryCatch(NID_APP, pInsertRowId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
429
430                                         LongLong::Parse(*pInsertRowId, insertRowId);
431                                 }
432
433                                 pEventArg = new (std::nothrow) _SqlDataControlEventArg(_DATACONTROL_REQUEST_TYPE_SQL_INSERT, static_cast <RequestId>(callerReqId),
434                                                 *pProviderId, *pDataId, null, insertRowId, providerResult, pErrorMsg);
435                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
436                                 pSqlDataControlEvent->Fire(*pEventArg);
437                                 break;
438                         }
439                         case _DATACONTROL_REQUEST_TYPE_SQL_UPDATE:
440                         {
441                                 pEventArg = new (std::nothrow) _SqlDataControlEventArg(_DATACONTROL_REQUEST_TYPE_SQL_UPDATE, static_cast <RequestId>(callerReqId),
442                                                 *pProviderId, *pDataId, null, -1, providerResult, pErrorMsg);
443                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
444                                 pSqlDataControlEvent->Fire(*pEventArg);
445                                 break;
446                         }
447                         case _DATACONTROL_REQUEST_TYPE_SQL_DELETE:
448                         {
449                                 pEventArg = new (std::nothrow) _SqlDataControlEventArg(_DATACONTROL_REQUEST_TYPE_SQL_DELETE, static_cast <RequestId>(callerReqId),
450                                                 *pProviderId, *pDataId, null, -1, providerResult, pErrorMsg);
451                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
452                                 pSqlDataControlEvent->Fire(*pEventArg);
453                                 break;
454                         }
455                         default:
456                                 break;
457                         }
458
459                         pResultList->RemoveAll(true);
460                         delete pResultList;
461
462
463                         delete pRequestType;
464                         delete pReqId;
465                         delete pProviderId;
466                 }
467         }
468
469         // Remove the request count
470 #if 0
471         SysLog(NID_APP, "Remove a launch request: reqId: %d", reqId);
472         _AppControlManager::GetInstance()->RemoveLaunchRequest(reqId);
473 #else
474         SysLog(NID_APP, "Remove a launch request: reqId: %d", callerReqId);
475         _AppControlManager::GetInstance()->RemoveLaunchRequest(callerReqId);
476 #endif
477
478         return E_SUCCESS;
479
480 CATCH:
481         if (pResultList)
482         {
483                 pResultList->RemoveAll(true);
484                 delete pResultList;
485         }
486
487
488         delete pRequestType;
489         delete pReqId;
490         delete pProviderId;
491
492         return r;
493 }
494
495 result
496 _SqlDataControlImpl::Insert(const String& dataId, const IMap& insertMap, RequestId& reqId)
497 {
498         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_WRITE) > 0, E_ILLEGAL_ACCESS,
499                         "The INSERT query is not permitted by DataControl provider.");
500
501         int columnCount = 0;
502         int id = 0;
503         int i = 0;
504         result r = E_SUCCESS;
505         SysLog(NID_APP, "[DC_CALLER] SqlDataControl INSERT");
506
507         columnCount = insertMap.GetCount();
508         SysTryReturnResult(NID_APP, columnCount > 0, E_INVALID_ARG, "The specified insertMap parameter is empty.");
509
510         ArrayList* pArgList = new ArrayList();
511         pArgList->Construct();
512
513         pArgList->Add(*(new String(dataId))); // list(0): data ID
514         long long argSize = dataId.GetLength() * sizeof(wchar_t);
515
516         pArgList->Add(*(new String(Integer::ToString(columnCount)))); // list(1): inserted column count
517         SysLog(NID_APP, "[DC_CALLER] inserted column count: %d", columnCount);
518
519         IMapEnumerator* pMapEnum = const_cast< IMap* >(&insertMap)->GetMapEnumeratorN();
520         while (pMapEnum->MoveNext() == E_SUCCESS) // list(2): column-value pairs
521         {
522                 String* pColumn = dynamic_cast< String* >(pMapEnum->GetKey());
523                 SysTryCatch(NID_APP, pColumn != null, r = E_INVALID_ARG, E_INVALID_ARG,
524                                 "[E_INVALID_ARG] The object is not String class.");
525
526                 pArgList->Add(*(new String(*pColumn)));
527                 SysLog(NID_APP, "[DC_CALLER] pColumn[%d]: %ls", i, pColumn->GetPointer());
528
529                 String* pValue = dynamic_cast< String* >(pMapEnum->GetValue());
530                 SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
531                                 "[E_INVALID_ARG] The object is not String class.");
532
533                 pArgList->Add(*(new String(*pValue)));
534                 SysLog(NID_APP, "[DC_CALLER] pValue[%d]: %ls", i, pValue->GetPointer());
535
536                 argSize += pColumn->GetLength() * sizeof(wchar_t);
537                 argSize += pValue->GetLength() * sizeof(wchar_t);
538                 i++;
539         }
540         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
541                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
542
543         r = StartSqlDataControl(_DATACONTROL_REQUEST_TYPE_SQL_INSERT, pArgList, &id);
544         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
545
546         reqId = static_cast< RequestId >(id);
547
548         SysLog(NID_APP, "[DC_CALLER] dataId: %ls, insertMap: 0x%x, reqId: %d", dataId.GetPointer(), &insertMap, reqId);
549
550         // fall through
551 CATCH:
552         pArgList->RemoveAll(true);
553         delete pArgList;
554
555         delete pMapEnum;
556
557         return r;
558 }
559
560 result
561 _SqlDataControlImpl::Update(const String& dataId, const IMap& updateMap, const String* pWhere, RequestId& reqId)
562 {
563         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_WRITE) > 0, E_ILLEGAL_ACCESS,
564                         "The UPDATE query is not permitted by DataControl provider.");
565
566         int columnCount = 0;
567         int id = 0;
568         int i = 0;
569         result r = E_SUCCESS;
570         SysLog(NID_APP, "[DC_CALLER] SqlDataControl UPDATE");
571
572         columnCount = updateMap.GetCount();
573         SysTryReturnResult(NID_APP, columnCount > 0, E_INVALID_ARG, "The specified insertMap parameter is empty.");
574
575         ArrayList* pArgList = new ArrayList();
576         pArgList->Construct();
577
578         pArgList->Add(*(new String(dataId))); // list(0): data ID
579         long long argSize = dataId.GetLength() * sizeof(wchar_t);
580
581         pArgList->Add(*(new String(Integer::ToString(columnCount)))); // list(1): updated column count
582         SysLog(NID_APP, "[DC_CALLER] updated column count: %d", columnCount);
583
584         IMapEnumerator* pMapEnum = const_cast< IMap* >(&updateMap)->GetMapEnumeratorN();
585         while (pMapEnum->MoveNext() == E_SUCCESS) // list(2): column-value pairs
586         {
587                 String* pColumn = dynamic_cast< String* >(pMapEnum->GetKey());
588                 SysTryCatch(NID_APP, pColumn != null, r = E_INVALID_ARG, E_INVALID_ARG,
589                                 "[E_INVALID_ARG] The object is not String class.");
590
591                 pArgList->Add(*(new String(*pColumn)));
592                 SysLog(NID_APP, "[DC_CALLER] pColumn[%d]: %ls", i, pColumn->GetPointer());
593
594                 String* pValue = dynamic_cast< String* >(pMapEnum->GetValue());
595                 SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
596                                 "[E_INVALID_ARG] The object is not String class.");
597
598                 pArgList->Add(*(new String(*pValue)));
599                 SysLog(NID_APP, "[DC_CALLER] pValue[%d]: %ls", i, pValue->GetPointer());
600
601                 argSize += pColumn->GetLength() * sizeof(wchar_t);
602                 argSize += pValue->GetLength() * sizeof(wchar_t);
603                 i++;
604         }
605
606         if (pWhere != null)     // list(3): where clause
607         {
608                 pArgList->Add(*(new String(*pWhere)));
609                 argSize += pWhere->GetLength() * sizeof(wchar_t);
610                 SysLog(NID_APP, "[DC_CALLER] pWhere: %ls", pWhere->GetPointer());
611         }
612         else
613         {
614                 pArgList->Add(*(new String(L"NULL")));
615         }
616         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
617                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
618
619         r = StartSqlDataControl(_DATACONTROL_REQUEST_TYPE_SQL_UPDATE, pArgList, &id);
620         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
621
622         reqId = static_cast< RequestId >(id);
623
624         SysLog(NID_APP, "[DC_CALLER] dataId: %ls, updateMap: 0x%x, pWhere: 0x%x, reqId: %d",
625                                 dataId.GetPointer(), &updateMap, pWhere, reqId);
626
627         // fall through
628 CATCH:
629         pArgList->RemoveAll(true);
630         delete pArgList;
631
632         delete pMapEnum;
633
634         return r;
635 }
636
637 result
638 _SqlDataControlImpl::Delete(const String& dataId, const String* pWhere, RequestId& reqId)
639 {
640         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_WRITE) > 0, E_ILLEGAL_ACCESS,
641                         "The DELETE query is not permitted by DataControl provider.");
642
643         int id = 0;
644         result r = E_SUCCESS;
645         SysLog(NID_APP, "[DC_CALLER] SqlDataControl DELETE");
646
647         ArrayList* pArgList = new ArrayList();
648         pArgList->Construct();
649
650         pArgList->Add(*(new String(dataId))); // list(0): data ID
651         long long argSize = dataId.GetLength() * sizeof(wchar_t);
652
653         if (pWhere != null)     // list(1): where clause
654         {
655                 pArgList->Add(*(new String(*pWhere)));
656                 argSize += pWhere->GetLength() * sizeof(wchar_t);
657                 SysLog(NID_APP, "[DC_CALLER] pWhere: %ls", pWhere->GetPointer());
658         }
659         else
660         {
661                 pArgList->Add(*(new String(L"NULL")));
662         }
663         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
664                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
665
666         r = StartSqlDataControl(_DATACONTROL_REQUEST_TYPE_SQL_DELETE, pArgList, &id);
667         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
668
669         reqId = static_cast< RequestId >(id);
670
671         SysLog(NID_APP, "[DC_CALLER] dataId: %ls, pWhere: 0x%x, reqId: %d", dataId.GetPointer(), pWhere, reqId);
672
673         // fall through
674 CATCH:
675         pArgList->RemoveAll(true);
676         delete pArgList;
677
678         return r;
679 }
680
681 result
682 _SqlDataControlImpl::SetSqlDataControlResponseListener(ISqlDataControlResponseListener* pListener)
683 {
684         result r = E_SUCCESS;
685
686         if (__pPreviousListener != null)
687         {
688                 r =  __pSqlDataControlEvent->RemoveListener(*__pPreviousListener);
689                 SysTryReturnResult(NID_APP, !IsFailed(r), E_SYSTEM, "Remove listener failed.");
690                  __pPreviousListener = null;
691         }
692
693         if (pListener != null)
694         {
695                 r =  __pSqlDataControlEvent->AddListener(*pListener);
696                 if (IsFailed(r))
697                 {
698                         switch (r)
699                         {
700                         case E_OBJ_ALREADY_EXIST:
701                                 return E_SUCCESS;
702                         case E_INVALID_OPERATION:
703                                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] The thread setting the listener is worker thread.");
704                                 return E_SYSTEM;
705                         default:
706                                 SysLogException(NID_APP, r, "[%s] Propagating to caller...", GetErrorMessage(r));
707                                 return r;
708                         }
709                 }
710         }
711
712         __pPreviousListener = pListener;
713
714         return E_SUCCESS;
715 }
716
717 // private
718 SqlDataControl*
719 _SqlDataControlImpl::CreateSqlDataControl(const String& appId, const String& providerId, const String& access)
720 {
721         unique_ptr<SqlDataControl> pDc(new (std::nothrow) SqlDataControl);
722         SysTryReturn(NID_APP, pDc != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient");
723
724         _SqlDataControlImpl* pDcImpl = _SqlDataControlImpl::GetInstance(*pDc);
725         pDcImpl->__appId = appId;
726         pDcImpl->__providerId = providerId;
727         unique_ptr<_SqlDataControlEvent> pSqlDataControlEvent(new (std::nothrow) _SqlDataControlEvent);
728         SysTryReturn(NID_IO, pSqlDataControlEvent != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
729
730         pDcImpl->__pSqlDataControlEvent = pSqlDataControlEvent.release();
731
732         if (access == L"readonly")
733         {
734                 pDcImpl->__access = _DATACONTROL_ACCESS_READ;
735         }
736         else if (access == L"writeonly")
737         {
738                 pDcImpl->__access = _DATACONTROL_ACCESS_WRITE;
739         }
740         else if (access == L"readwrite")
741         {
742                 pDcImpl->__access = _DATACONTROL_ACCESS_READWRITE;
743         }
744         else
745         {
746                 pDcImpl->__access = _DATACONTROL_ACCESS_UNDEFINED;
747                 SysLog(NID_IO, "The accessibility of DataControl provider is invalid.");
748         }
749
750         return pDc.release();
751 }
752
753 }} // Tizen::App
754