sync
[platform/framework/web/wrt-plugins-common.git] / src / modules / tizen / WidgetInterfaceDAO / WidgetInterfaceDAO.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @author      Lukasz Marek (l.marek@samsung.com)
18  * @version     0.1
19  * @brief
20  */
21
22 #include "WidgetInterfaceDAO.h"
23 #include <string>
24 #include <sstream>
25 #include <fstream>
26 #include <sys/stat.h>
27 #include <dpl/db/sql_connection.h>
28 #include <dpl/log/log.h>
29 #include <dpl/foreach.h>
30 #include <dpl/string.h>
31 #include <Commons/Exception.h>
32 #include <dpl/wrt-dao-ro/property_dao_read_only.h>
33 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
34 #include <dpl/wrt-dao-ro/WrtDatabase.h>
35 #include <dpl/wrt-dao-ro/widget_config.h>
36 #include <dpl/wrt-dao-ro/global_config.h>
37 #include "orm_generator_widget_interface.h"
38 namespace {
39 DPL::DB::SqlConnection::Flag::Type DATABASE_FLAGS =
40     DPL::DB::SqlConnection::Flag::UseLucene;
41 DPL::DB::SqlConnection::Flag::Option DATABASE_OPTIONS =
42     DPL::DB::SqlConnection::Flag::RW;
43 const char *KEY_WIDGET_ARG = "widget_arg";
44 }
45
46 namespace WrtDeviceApis {
47
48 WidgetInterfaceDAO::WidgetInterfaceDAO(int widgetHandle) :
49     m_widgetHandle(widgetHandle),
50     m_databaseInterface(databaseFileName(widgetHandle), DATABASE_FLAGS)
51 {
52     if (!checkDatabase()) {
53         LogError("There is a problem with database");
54     }
55     m_databaseInterface.AttachToThread(DPL::DB::SqlConnection::Flag::RW);
56 }
57
58 WidgetInterfaceDAO::~WidgetInterfaceDAO()
59 {
60     m_databaseInterface.DetachFromThread();
61 }
62
63 bool WidgetInterfaceDAO::checkDatabase()
64 {
65     using namespace WrtDB::GlobalConfig;
66     std::string databaseFile = databaseFileName(m_widgetHandle);
67     struct stat buffer;
68     if (stat(databaseFile.c_str(), &buffer) != 0) {
69
70         //Create fresh database
71
72         LogInfo("Creating database " << databaseFile);
73
74         std::fstream file;
75         file.open(GetWrtWidgetInterfaceDatabaseFilePath(), std::ios_base::in);
76         if (!file) {
77             LogError("Cannot create database. SQL file is missing.");
78             return false;
79         }
80
81         std::stringstream buffer;
82         buffer << file.rdbuf();
83
84         file.close();
85
86         Try
87         {
88             DPL::DB::SqlConnection con(databaseFile,
89                 DATABASE_FLAGS, DATABASE_OPTIONS);
90             con.ExecCommand(buffer.str().c_str());
91         }
92         Catch(DPL::DB::SqlConnection::Exception::Base)
93         {
94             LogError("Cannot create database");
95             return false;
96         }
97         copyPropertiesFromWrtDatabase();
98     }
99     return true;
100 }
101
102 bool WidgetInterfaceDAO::copyPropertiesFromWrtDatabase()
103 {
104     using namespace DPL::DB::ORM;
105     using namespace DPL::DB::ORM::widget_interface;
106
107     bool result = true;
108     WrtDB::WrtDatabase::attachToThreadRO();
109     m_databaseInterface.AttachToThread(DPL::DB::SqlConnection::Flag::RW);
110
111     Try
112     {
113         WrtDB::PropertyDAOReadOnly::WidgetPreferenceList existing =
114             WrtDB::PropertyDAOReadOnly::GetPropertyList(m_widgetHandle);
115
116         Try
117         {
118             //save all properties read from config.xml
119             FOREACH(prop, existing) {
120                 std::string key = DPL::ToUTF8String(prop->key_name);
121                 if (key != KEY_WIDGET_ARG) {
122                     std::string value;
123                     if (!prop->key_value.IsNull()) {
124                         value = DPL::ToUTF8String(*(prop->key_value));
125                     }
126                     bool readonly =
127                         !prop->readonly.IsNull() && (*prop->readonly);
128                     setItem(key, value, readonly, true);
129                 }
130             }
131         }
132         Catch(Commons::Exception)
133         {
134             LogError("Cannot copy properties read from config.xml");
135             result = false;
136         }
137     }
138     Catch(DPL::DB::SqlConnection::Exception::Base)
139     {
140         LogError("Cannot copy properties read from config.xml");
141         result = false;
142     }
143     WrtDB::WrtDatabase::detachFromThread();
144     m_databaseInterface.DetachFromThread();
145     return result;
146 }
147
148 void WidgetInterfaceDAO::setItem(const std::string& key,
149                                  const std::string& value,
150                                  bool readOnly)
151 {
152     setItem(key, value, readOnly, false);
153 }
154
155 void WidgetInterfaceDAO::setItem(const std::string& key,
156                                  const std::string& value,
157                                  bool readOnly,
158                                  bool fromConfigXml)
159 {
160     using namespace DPL::DB::ORM;
161     using namespace DPL::DB::ORM::widget_interface;
162
163     Try
164     {
165         ScopedTransaction tran(&m_databaseInterface);
166         //check if key exists
167         Properties::Select select(&m_databaseInterface);
168         select.Where(
169             Equals<Properties::key>(DPL::FromUTF8String(key)));
170         std::list<Properties::Row> rows = select.GetRowList();
171
172         if (rows.size() == 0) {
173             Properties::Insert insert(&m_databaseInterface);
174             Properties::Row row;
175             row.Set_key(DPL::FromUTF8String(key));
176             row.Set_value(DPL::FromUTF8String(value));
177             row.Set_readonly(readOnly ? 1 : 0);
178             row.Set_configxml(fromConfigXml ? 1 : 0);
179             insert.Values(row);
180             insert.Execute();
181         }
182         else {
183             Assert(rows.size() == 1);
184             Properties::Row row = rows.front();
185             if (row.Get_readonly() != 0) {
186                 Throw(Commons::LocalStorageValueNoModifableException);
187             }
188             row.Set_value(DPL::FromUTF8String(value));
189             row.Set_readonly(readOnly ? 1 : 0);
190             Properties::Update update(&m_databaseInterface);
191             update.Where(Equals<Properties::key>(DPL::FromUTF8String(key)));
192             update.Values(row);
193             update.Execute();
194         }
195         tran.Commit();
196     }
197     Catch(DPL::DB::SqlConnection::Exception::Base)
198     {
199         LogError("Cannot set item " << key << " with value " << value);
200         ReThrow(Commons::PlatformException);
201     }
202
203 }
204
205 void WidgetInterfaceDAO::removeItem(const std::string& key)
206 {
207     using namespace DPL::DB::ORM;
208     using namespace DPL::DB::ORM::widget_interface;
209
210     Try
211     {
212         Properties::Select select(&m_databaseInterface);
213         select.Where(Equals<Properties::key>(DPL::FromUTF8String(key)));
214         bool readonly = select.GetSingleValue<Properties::readonly>();
215         if (readonly) {
216             ThrowMsg(Commons::LocalStorageValueNoModifableException,
217                 "Cannot delete item. Item is readonly");
218         }
219         Properties::Delete deleteItem(&m_databaseInterface);
220         deleteItem.Where(Equals<Properties::key>(DPL::FromUTF8String(key)));
221         deleteItem.Execute();
222     }
223     Catch(DPL::DB::SqlConnection::Exception::Base)
224     {
225         LogError("Cannot delete item " << key);
226         ReThrow(Commons::PlatformException);
227     }
228 }
229
230 DPL::Optional<std::string> WidgetInterfaceDAO::getValue(
231         const std::string& key) const
232 {
233     using namespace DPL::DB::ORM;
234     using namespace DPL::DB::ORM::widget_interface;
235
236     Try
237     {
238         Properties::Select select(&m_databaseInterface);
239         select.Where(Equals<Properties::key>(DPL::FromUTF8String(key)));
240         std::list<DPL::String> value = select.GetValueList<Properties::value>();
241         if (value.size() == 0) {
242             return DPL::Optional<std::string>();
243         }
244         return DPL::Optional<std::string>(DPL::ToUTF8String(value.front()));
245     }
246     Catch(DPL::DB::SqlConnection::Exception::Base)
247     {
248         LogError("Not found item " << key);
249         ReThrow(Commons::PlatformException);
250     }
251 }
252
253 void WidgetInterfaceDAO::clear(bool removeReadOnly)
254 {
255     using namespace DPL::DB::ORM;
256     using namespace DPL::DB::ORM::widget_interface;
257     Try
258     {
259         Properties::Delete deleteItem(&m_databaseInterface);
260         if (!removeReadOnly) {
261             deleteItem.Where(Equals<Properties::readonly>(0));
262         }
263         deleteItem.Execute();
264     }
265     Catch(DPL::DB::SqlConnection::Exception::Base)
266     {
267         LogError("Cannot delete all items");
268         ReThrow(Commons::PlatformException);
269     }
270 }
271
272 size_t WidgetInterfaceDAO::getStorageSize() const
273 {
274     using namespace DPL::DB::ORM;
275     using namespace DPL::DB::ORM::widget_interface;
276
277     Try
278     {
279         Properties::Select select(&m_databaseInterface);
280         std::list<DPL::String> list =
281             select.GetValueList<Properties::key>();
282         return list.size();
283     }
284     Catch(DPL::DB::SqlConnection::Exception::Base)
285     {
286         LogError("Cannot get item count");
287         ReThrow(Commons::PlatformException);
288     }
289     return 0;
290 }
291
292 std::string WidgetInterfaceDAO::getKeyByIndex(size_t index) const
293 {
294     using namespace DPL::DB::ORM;
295     using namespace DPL::DB::ORM::widget_interface;
296
297     Try
298     {
299         Properties::Select select(&m_databaseInterface);
300         select.OrderBy("key");
301         std::list<DPL::String> list =
302             select.GetValueList<Properties::key>();
303         if (index >= list.size()) {
304             Throw(Commons::InvalidArgumentException);
305         }
306         for (size_t i = 0; i < index; ++i) {
307             list.pop_front();
308         }
309         return DPL::ToUTF8String(list.front());
310     }
311     Catch(DPL::DB::SqlConnection::Exception::Base)
312     {
313         LogError("Cannot get item count");
314         ReThrow(Commons::PlatformException);
315     }
316 }
317
318 std::string WidgetInterfaceDAO::databaseFileName(int widgetHandle)
319 {
320     using namespace DPL::DB::ORM;
321     using namespace WrtDB::WidgetConfig;
322     using namespace WrtDB::GlobalConfig;
323
324     WrtDB::WrtDatabase::attachToThreadRO();
325
326     std::stringstream filename;
327     Try
328     {
329         WrtDB::WidgetDAOReadOnly widgetDAO(widgetHandle);
330         WrtDB::WidgetPkgName pkgname = widgetDAO.getPkgName();
331
332         filename << GetWidgetPersistentStoragePath(pkgname)
333                  << "/"
334                  << GetWidgetInterfaceDatabaseFile();
335     }
336     Catch(DPL::DB::SqlConnection::Exception::Base)
337     {
338         LogError("Cannot get item count");
339         ReThrow(Commons::PlatformException);
340     }
341     WrtDB::WrtDatabase::detachFromThread();
342     return filename.str();
343 }
344
345 }