Refactor DataControl request list.
[platform/framework/native/appfw.git] / src / app / FApp_DataControlProviderManagerImpl.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_DataControlProviderManagerImpl.cpp
20  * @brief       This is the implementation for the %_DataControlProviderManagerImpl class.
21  */
22
23 #include <unique_ptr.h>
24
25 #include <FBaseDataType.h>
26 #include <FBaseInteger.h>
27 #include <FBaseString.h>
28 #include <FBaseLongLong.h>
29 #include <FBaseColArrayList.h>
30 #include <FBaseColIList.h>
31 #include <FBaseErrors.h>
32 #include <FAppAppManager.h>
33 #include <FAppSqlDataControl.h>
34 #include <FAppMapDataControl.h>
35 #include <FAppDataControlProviderManager.h>
36
37 #include <FBaseSysLog.h>
38 #include <FIo_DataControlResultSetImpl.h>
39
40 #include "FApp_Aul.h"
41 #include "FApp_AppArg.h"
42 #include "FApp_AppInfo.h"
43 #include "FApp_AppImpl.h"
44 #include "FApp_AppControlManager.h"
45 #include "FApp_SqlDataControlImpl.h"
46 #include "FApp_MapDataControlImpl.h"
47 #include "FApp_DataControlProviderManagerImpl.h"
48
49 using namespace Tizen::Base;
50 using namespace Tizen::Base::Collection;
51 using namespace Tizen::Io;
52
53 extern const char* _DATACONTROL_RESULTSET_DIR;
54
55 namespace Tizen { namespace App
56 {
57
58 static const int _MAX_ARGUMENT_SIZE = 16384; // 16KB
59
60 result
61 _DataControlProviderManagerImpl::SetSqlDataControlProviderEventListener(ISqlDataControlProviderEventListener* pListener)
62 {
63         _AppImpl* pAppImpl = _AppImpl::GetInstance();
64         SysTryReturn(NID_APP, pAppImpl, false, E_INVALID_STATE, "[E_INVALID_STATE] Getting _AppImpl instance failed.");
65
66         return pAppImpl->SetSqlDataControlProviderEventListener(pListener);
67 }
68
69 result
70 _DataControlProviderManagerImpl::SetMapDataControlProviderEventListener(IMapDataControlProviderEventListener* pListener)
71 {
72         _AppImpl* pAppImpl = _AppImpl::GetInstance();
73         SysTryReturn(NID_APP, pAppImpl, false, E_INVALID_STATE, "[E_INVALID_STATE] Getting _AppImpl instance failed.");
74
75         return pAppImpl->SetMapDataControlProviderEventListener(pListener);
76 }
77
78 result
79 _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataControlRequestType apiType,
80                 IDbEnumerator* pDbEnum, IList* pResultValueList, long long insertRowId, bool providerResult, const String* pErrorMsg)
81 {
82         ArrayList* pList = null;
83         String* pAppId = null;
84         String reqType;
85         int type = 0;
86         _DataControlRequestType requestType = _DATACONTROL_REQUEST_TYPE_UNDEFINED;
87         String* pProviderId = null;
88         String* pCallerReqId = null;
89         int callerReqId = -1;
90         ArrayList* pResultArgList = null;
91         String* pResult = null;
92         String* pErrorMessage = null;
93         String* pTempFilePath = null;
94         String* pNo = null;
95         int pageNo = 0;
96         String* pCount = null;
97         int countPerPage = 0;
98         String* pResultCount = null;
99         String* pResultValue = null;
100         _AppArg resultArg;
101         String* pDataId = null;
102         result r = E_SUCCESS;
103
104         _AppControlManager* pAppMgr = _AppControlManager::GetInstance();
105         SysTryReturnResult(NID_APP, pAppMgr, E_SYSTEM, "Failed to get instance.");
106
107         _ResultInfo* pResultInfo = pAppMgr->__resultManager.FindItem(static_cast< int >(reqId));
108         SysTryReturnResult(NID_APP, pResultInfo, E_OBJ_NOT_FOUND,
109                         "The data control request specified with the reqId (%ld) did not exist.", reqId);
110
111         const _AppArg& arg = pResultInfo->arg;
112
113         pList = arg.GetArgListN(0);
114         SysTryCatch(NID_APP, pList, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
115
116         // key-based request
117         pAppId = dynamic_cast< String* >(pList->GetAt(0)); // request key[0]
118         SysTryCatch(NID_APP, pAppId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
119
120         reqType = arg.GetValue(OSP_K_DATACONTROL_REQUEST_TYPE);
121         Integer::Parse(reqType, type);
122         requestType = static_cast< _DataControlRequestType >(type);
123
124         if (providerResult == true && apiType != requestType)
125         {
126                 if ((apiType == _DATACONTROL_REQUEST_TYPE_SQL_UPDATE /*UpdateDelete*/ && requestType == _DATACONTROL_REQUEST_TYPE_SQL_DELETE) ||
127                                 apiType == _DATACONTROL_REQUEST_TYPE_UNDEFINED /*MAP*/)
128                 {
129                         r = E_SUCCESS;
130                 }
131                 else
132                 {
133                         r = E_INVALID_ARG;
134                         SysLog(NID_APP, "[E_INVALID_ARG] This method cannot send the result set for the specified reqId.");
135                         goto CATCH;
136                 }
137         }
138
139         pCallerReqId = dynamic_cast< String* >(pList->GetAt(2)); // request key[2]
140         SysTryCatch(NID_APP, pCallerReqId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
141         Integer::Parse(*pCallerReqId, callerReqId);
142
143         pProviderId = dynamic_cast< String* >(pList->GetAt(3)); // request key[3]
144         SysTryCatch(NID_APP, pProviderId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
145
146         pDataId = dynamic_cast< String* >(pList->GetAt(4)); // list[0]
147         SysTryCatch(NID_APP, pDataId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
148
149         // Serializes the result
150         pResultArgList = new (std::nothrow) ArrayList();
151         SysTryCatch(NID_APP, pResultArgList, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
152                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
153         pResultArgList->Construct();
154
155         pResult = new (std::nothrow) String();
156         SysTryCatch(NID_APP, pResult, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
157                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
158         pResult->Append(static_cast< int >(providerResult));
159         pResultArgList->Add(*pResult); // result list[0]
160
161         if (pErrorMsg == null)
162         {
163                 pErrorMessage = new (std::nothrow) String();
164         }
165         else
166         {
167                 pErrorMessage = new (std::nothrow) String(*pErrorMsg);
168         }
169         SysTryCatch(NID_APP, pErrorMessage, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
170                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
171         SysTryCatch(NID_APP, pErrorMessage->GetLength() <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
172                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", pErrorMessage->GetLength());
173         pResultArgList->Add(*pErrorMessage); // result list[1]
174
175         switch (requestType)
176         {
177         case _DATACONTROL_REQUEST_TYPE_SQL_QUERY:
178         {
179                 if (pDbEnum)
180                 {
181                         std::unique_ptr<_DataControlResultSetImpl> pResultSet(new (std::nothrow) _DataControlResultSetImpl(reqId));
182                         SysTryCatch(NID_APP, pResultSet, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
183                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
184
185                         r = pResultSet->FillWith(pDbEnum);
186                         SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM,
187                                         "[E_SYSTEM] The method cannot proceed due to a severe system error.");
188
189                         String tempFilePath(_DATACONTROL_RESULTSET_DIR);
190                         tempFilePath.Append(*pAppId);
191                         tempFilePath.Append(*pCallerReqId);
192                         pTempFilePath = new (std::nothrow) String(tempFilePath);
193                 }
194                 else
195                 {
196                         pTempFilePath = new (std::nothrow) String(L"NoResultSet");
197                 }
198                 SysTryCatch(NID_APP, pTempFilePath, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
199                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
200
201                 pResultArgList->Add(*pTempFilePath); // result list[2]
202                 break;
203         }
204         case _DATACONTROL_REQUEST_TYPE_SQL_INSERT:
205                 pResultArgList->Add(*(new String(LongLong::ToString(insertRowId)))); // result list[2]
206                 break;
207
208         case _DATACONTROL_REQUEST_TYPE_SQL_UPDATE:
209                 // fall through
210         case _DATACONTROL_REQUEST_TYPE_SQL_DELETE:
211                 break;
212
213         case _DATACONTROL_REQUEST_TYPE_MAP_QUERY:
214         {
215                 SysTryCatch(NID_APP, !(providerResult == true && pResultValueList == null), r = E_INVALID_ARG, E_INVALID_ARG,
216                                 "[E_INVALID_ARG] The specified pResultValueList should not be null if the request is GetValue query.");
217
218                 if (pResultValueList)
219                 {
220                         // list-based request
221                         pNo = dynamic_cast< String* >(pList->GetAt(6)); // request list[2]
222                         SysTryCatch(NID_APP, pNo, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
223                         Integer::Parse(*pNo, pageNo);
224
225                         pCount = dynamic_cast< String* >(pList->GetAt(7)); // request list[3]
226                         SysTryCatch(NID_APP, pCount, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
227                         Integer::Parse(*pCount, countPerPage);
228
229                         String resultCount;
230                         int num = pResultValueList->GetCount();
231                         int currentoffset = (pageNo - 1) * countPerPage;
232                         int remainingNum = num - currentoffset;
233                         remainingNum = (remainingNum > 0) ? remainingNum : 0; // round off to zero if negative num is found
234                         int addItemCount = (countPerPage > remainingNum) ? remainingNum : countPerPage;
235                         resultCount.Append(addItemCount);
236
237                         pResultCount = new (std::nothrow) String(resultCount);
238                         SysTryCatch(NID_APP, pResultCount, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
239                                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
240                         pResultArgList->Add(*pResultCount); // result list[2]
241
242                         long long argSize = 0;
243                         for (int i = currentoffset; i < num; i++)
244                         {
245                                 String* pTempValue = dynamic_cast< String* >(pResultValueList->GetAt(i));
246                                 SysTryCatch(NID_APP, pTempValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
247                                                 "[E_INVALID_ARG] The specified pResultValueList parameter should be String class.");
248
249                                 pResultValue = new (std::nothrow) String(*pTempValue);
250                                 SysTryCatch(NID_APP, pResultValue, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
251                                                 "[E_OUT_OF_MEMORY] The memory was insufficient.");
252                                 pResultArgList->Add(*pResultValue); // list[3] ~
253                                 argSize += pResultValue->GetLength() * sizeof(wchar_t);
254                         }
255                         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
256                                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
257                 }
258                 break;
259         }
260         case _DATACONTROL_REQUEST_TYPE_MAP_INSERT:
261                 // fall through
262         case _DATACONTROL_REQUEST_TYPE_MAP_UPDATE:
263                 // fall through
264         case _DATACONTROL_REQUEST_TYPE_MAP_DELETE:
265                 SysTryCatch(NID_APP, !(providerResult == true && pResultValueList != null), r = E_INVALID_ARG, E_INVALID_ARG,
266                                 "[E_INVALID_ARG] The specified pResultValueList should be null if the request is \
267                                 one of AddValue, SetValue, RemoveValue queries.");
268                 break;
269
270         default:
271                 SysTryCatch(NID_APP, false, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
272                 break;
273         }
274
275         r = resultArg.ConstructResult(arg, pResultArgList);
276         SysTryCatch(NID_APP, !IsFailed(r), r = E_SYSTEM, r, "[%s] Propagating.", GetErrorMessage(r));
277         resultArg.UpdateRequestId(callerReqId);
278         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_REQUEST_TYPE, reqType);
279         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_PROVIDER, *pProviderId);
280         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_DATA, *pDataId);
281
282         //resultArg.Print();
283         r = _Aul::SendResult(resultArg.GetBundle(), static_cast< appsvc_result_val >(0));
284         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Failed to send result.", GetErrorMessage(r));
285
286         // Erases _AppArg after sending the result back to the caller
287         pAppMgr->__resultManager.RemoveItem(static_cast< int >(reqId));
288
289 CATCH:
290         if (pList)
291         {
292                 pList->RemoveAll(true);
293         }
294         delete pList;
295
296         if (pResultArgList)
297         {
298                 pResultArgList->RemoveAll(true);
299         }
300         delete pResultArgList;
301
302         return r;
303 }
304
305 result
306 _DataControlProviderManagerImpl::SendSqlDataControlSelectResult(RequestId reqId, IDbEnumerator* pDbEnum)
307 {
308         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_SQL_QUERY,
309                         pDbEnum, null, -1, true, null);
310 }
311
312 result
313 _DataControlProviderManagerImpl::SendSqlDataControlInsertResult(RequestId reqId, long long insertRowId)
314 {
315         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_SQL_INSERT,
316                         null, null, insertRowId, true, null);
317 }
318
319 result
320 _DataControlProviderManagerImpl::SendSqlDataControlUpdateDeleteResult(RequestId reqId)
321 {
322         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_SQL_UPDATE,
323                         null, null, -1, true, null);
324 }
325
326 result
327 _DataControlProviderManagerImpl::SendMapDataControlResult(RequestId reqId, IList* pResultValueList)
328 {
329         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_UNDEFINED,
330                         null, pResultValueList, -1, true, null);
331 }
332
333 result
334 _DataControlProviderManagerImpl::SendDataControlError(RequestId reqId, const String& errorMsg)
335 {
336         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_UNDEFINED,
337                         null, null, -1, false, &errorMsg);
338 }
339
340 DataControlProviderManager*
341 _DataControlProviderManagerImpl::GetInstance(void)
342 {
343         static DataControlProviderManager* pDcMgr = null;
344
345         if (pDcMgr == null)
346         {
347                 pDcMgr = new (std::nothrow) DataControlProviderManager();
348                 SysTryReturn(NID_APP, pDcMgr, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory was insufficient.");
349         }
350
351         return pDcMgr;
352 }
353
354 // private
355 _DataControlProviderManagerImpl::_DataControlProviderManagerImpl(void)
356 {
357 }
358
359 _DataControlProviderManagerImpl::~_DataControlProviderManagerImpl(void)
360 {
361 }
362
363 } } // Tizen::App
364