merge with master
[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 WidgetInterfaceDAO::WidgetInterfaceDAO(int widgetHandle) :
48     m_widgetHandle(widgetHandle),
49     m_databaseInterface(databaseFileName(widgetHandle), DATABASE_FLAGS)
50 {
51     if (!checkDatabase()) {
52         LogError("There is a problem with database");
53     }
54     m_databaseInterface.AttachToThread(DPL::DB::SqlConnection::Flag::RW);
55 }
56
57 WidgetInterfaceDAO::~WidgetInterfaceDAO()
58 {
59     m_databaseInterface.DetachFromThread();
60 }
61
62 bool WidgetInterfaceDAO::checkDatabase()
63 {
64     using namespace WrtDB::GlobalConfig;
65     std::string databaseFile = databaseFileName(m_widgetHandle);
66     struct stat buffer;
67     if (stat(databaseFile.c_str(), &buffer) != 0) {
68         //Create fresh database
69
70         LogInfo("Creating database " << databaseFile);
71
72         std::fstream file;
73         file.open(GetWrtWidgetInterfaceDatabaseFilePath(), std::ios_base::in);
74         if (!file) {
75             LogError("Cannot create database. SQL file is missing.");
76             return false;
77         }
78
79         std::stringstream buffer;
80         buffer << file.rdbuf();
81
82         file.close();
83
84         Try
85         {
86             DPL::DB::SqlConnection con(databaseFile,
87                                        DATABASE_FLAGS, DATABASE_OPTIONS);
88             con.ExecCommand(buffer.str().c_str());
89         }
90         Catch(DPL::DB::SqlConnection::Exception::Base)
91         {
92             LogError("Cannot create database");
93             return false;
94         }
95         copyPropertiesFromWrtDatabase();
96     }
97     return true;
98 }
99
100 bool WidgetInterfaceDAO::copyPropertiesFromWrtDatabase()
101 {
102     using namespace DPL::DB::ORM;
103     using namespace DPL::DB::ORM::widget_interface;
104
105     bool result = true;
106     WrtDB::WrtDatabase::attachToThreadRO();
107     m_databaseInterface.AttachToThread(DPL::DB::SqlConnection::Flag::RW);
108
109     Try
110     {
111         WrtDB::PropertyDAOReadOnly::WidgetPreferenceList existing =
112             WrtDB::PropertyDAOReadOnly::GetPropertyList(m_widgetHandle);
113
114         Try
115         {
116             //save all properties read from config.xml
117             FOREACH(prop, existing) {
118                 std::string key = DPL::ToUTF8String(prop->key_name);
119                 if (key != KEY_WIDGET_ARG) {
120                     std::string value;
121                     if (!prop->key_value.IsNull()) {
122                         value = DPL::ToUTF8String(*(prop->key_value));
123                     }
124                     bool readonly =
125                         !prop->readonly.IsNull() && (*prop->readonly);
126                     setItem(key, value, readonly, true);
127                 }
128             }
129         }
130         Catch(Commons::Exception)
131         {
132             LogError("Cannot copy properties read from config.xml");
133             result = false;
134         }
135     }
136     Catch(DPL::DB::SqlConnection::Exception::Base)
137     {
138         LogError("Cannot copy properties read from config.xml");
139         result = false;
140     }
141     WrtDB::WrtDatabase::detachFromThread();
142     m_databaseInterface.DetachFromThread();
143     return result;
144 }
145
146 void WidgetInterfaceDAO::setItem(const std::string& key,
147                                  const std::string& value,
148                                  bool readOnly)
149 {
150     setItem(key, value, readOnly, false);
151 }
152
153 void WidgetInterfaceDAO::setItem(const std::string& key,
154                                  const std::string& value,
155                                  bool readOnly,
156                                  bool fromConfigXml)
157 {
158     using namespace DPL::DB::ORM;
159     using namespace DPL::DB::ORM::widget_interface;
160
161     Try
162     {
163         ScopedTransaction tran(&m_databaseInterface);
164         //check if key exists
165         Properties::Select select(&m_databaseInterface);
166         select.Where(
167             Equals<Properties::key>(DPL::FromUTF8String(key)));
168         std::list<Properties::Row> rows = select.GetRowList();
169
170         if (rows.empty()) {
171             Properties::Insert insert(&m_databaseInterface);
172             Properties::Row row;
173             row.Set_key(DPL::FromUTF8String(key));
174             row.Set_value(DPL::FromUTF8String(value));
175             row.Set_readonly(readOnly ? 1 : 0);
176             row.Set_configxml(fromConfigXml ? 1 : 0);
177             insert.Values(row);
178             insert.Execute();
179         } else {
180             Assert(rows.size() == 1);
181             Properties::Row row = rows.front();
182             if (row.Get_readonly() != 0) {
183                 Throw(Commons::LocalStorageValueNoModifableException);
184             }
185             row.Set_value(DPL::FromUTF8String(value));
186             row.Set_readonly(readOnly ? 1 : 0);
187             Properties::Update update(&m_databaseInterface);
188             update.Where(Equals<Properties::key>(DPL::FromUTF8String(key)));
189             update.Values(row);
190             update.Execute();
191         }
192         tran.Commit();
193     }
194     Catch(DPL::DB::SqlConnection::Exception::Base)
195     {
196         LogError("Cannot set item " << key << " with value " << value);
197         ReThrow(Commons::PlatformException);
198     }
199 }
200
201 void WidgetInterfaceDAO::removeItem(const std::string& key)
202 {
203     using namespace DPL::DB::ORM;
204     using namespace DPL::DB::ORM::widget_interface;
205
206     Try
207     {
208         Properties::Select select(&m_databaseInterface);
209         select.Where(Equals<Properties::key>(DPL::FromUTF8String(key)));
210         bool readonly = select.GetSingleValue<Properties::readonly>();
211         if (readonly) {
212             ThrowMsg(Commons::LocalStorageValueNoModifableException,
213                      "Cannot delete item. Item is readonly");
214         }
215         Properties::Delete deleteItem(&m_databaseInterface);
216         deleteItem.Where(Equals<Properties::key>(DPL::FromUTF8String(key)));
217         deleteItem.Execute();
218     }
219     Catch(DPL::DB::SqlConnection::Exception::Base)
220     {
221         LogError("Cannot delete item " << key);
222         ReThrow(Commons::PlatformException);
223     }
224 }
225
226 DPL::Optional<std::string> WidgetInterfaceDAO::getValue(
227     const std::string& key) const
228 {
229     using namespace DPL::DB::ORM;
230     using namespace DPL::DB::ORM::widget_interface;
231
232     Try
233     {
234         Properties::Select select(&m_databaseInterface);
235         select.Where(Equals<Properties::key>(DPL::FromUTF8String(key)));
236         std::list<DPL::String> value = select.GetValueList<Properties::value>();
237         if (value.empty()) {
238             return DPL::Optional<std::string>();
239         }
240         return DPL::Optional<std::string>(DPL::ToUTF8String(value.front()));
241     }
242     Catch(DPL::DB::SqlConnection::Exception::Base)
243     {
244         LogError("Not found item " << key);
245         ReThrow(Commons::PlatformException);
246     }
247 }
248
249 void WidgetInterfaceDAO::clear(bool removeReadOnly)
250 {
251     using namespace DPL::DB::ORM;
252     using namespace DPL::DB::ORM::widget_interface;
253     Try
254     {
255         Properties::Delete deleteItem(&m_databaseInterface);
256         if (!removeReadOnly) {
257             deleteItem.Where(Equals<Properties::readonly>(0));
258         }
259         deleteItem.Execute();
260     }
261     Catch(DPL::DB::SqlConnection::Exception::Base)
262     {
263         LogError("Cannot delete all items");
264         ReThrow(Commons::PlatformException);
265     }
266 }
267
268 size_t WidgetInterfaceDAO::getStorageSize() const
269 {
270     using namespace DPL::DB::ORM;
271     using namespace DPL::DB::ORM::widget_interface;
272
273     Try
274     {
275         Properties::Select select(&m_databaseInterface);
276         std::list<DPL::String> list =
277             select.GetValueList<Properties::key>();
278         return list.size();
279     }
280     Catch(DPL::DB::SqlConnection::Exception::Base)
281     {
282         LogError("Cannot get item count");
283         ReThrow(Commons::PlatformException);
284     }
285     return 0;
286 }
287
288 std::string WidgetInterfaceDAO::getKeyByIndex(size_t index) const
289 {
290     using namespace DPL::DB::ORM;
291     using namespace DPL::DB::ORM::widget_interface;
292
293     Try
294     {
295         Properties::Select select(&m_databaseInterface);
296         select.OrderBy("key");
297         std::list<DPL::String> list =
298             select.GetValueList<Properties::key>();
299         if (index >= list.size()) {
300             Throw(Commons::InvalidArgumentException);
301         }
302         for (size_t i = 0; i < index; ++i) {
303             list.pop_front();
304         }
305         return DPL::ToUTF8String(list.front());
306     }
307     Catch(DPL::DB::SqlConnection::Exception::Base)
308     {
309         LogError("Cannot get item count");
310         ReThrow(Commons::PlatformException);
311     }
312 }
313
314 std::string WidgetInterfaceDAO::databaseFileName(int widgetHandle)
315 {
316     using namespace DPL::DB::ORM;
317     using namespace WrtDB::WidgetConfig;
318     using namespace WrtDB::GlobalConfig;
319
320     WrtDB::WrtDatabase::attachToThreadRO();
321
322     std::stringstream filename;
323     Try
324     {
325         WrtDB::WidgetDAOReadOnly widgetDAO(widgetHandle);
326         WrtDB::TizenPkgId pkgid = widgetDAO.getTizenPkgId();
327
328         filename << GetWidgetPersistentStoragePath(pkgid)
329                  << "/"
330                  << GetWidgetInterfaceDatabaseFile();
331     }
332     Catch(DPL::DB::SqlConnection::Exception::Base)
333     {
334         LogError("Cannot get item count");
335         ReThrow(Commons::PlatformException);
336     }
337     WrtDB::WrtDatabase::detachFromThread();
338     return filename.str();
339 }
340 }