Replace QueryBuilder with hiberlite ORM library 08/187908/8
authorTomasz Jeschke <t.jeschke@samsung.com>
Wed, 29 Aug 2018 10:45:15 +0000 (12:45 +0200)
committerTomasz Jeschke <t.jeschke@samsung.com>
Mon, 17 Sep 2018 09:12:19 +0000 (11:12 +0200)
The goal is to replace building queries manually
with a dedicated ORM library.

hiberlite library included in the repository
https://github.com/paulftw/hiberlite
Latest commit ffd558a4917b33668d1001b4bba8e11b508be06a

QueryBuilder source files have been deleted.
SQLiteConfiguration files have been replaced
with HiberliteConfiguration.

Change-Id: If3f2e5caca633f1d4b167a79f2b9c1ceef39f74b

53 files changed:
src/CMakeLists.txt
src/Configuration.hpp
src/DBusInterface.cpp
src/HiberliteConfiguration.cpp [new file with mode: 0644]
src/HiberliteConfiguration.hpp [moved from src/SQLiteConfiguration.hpp with 50% similarity]
src/NavigationInterface.cpp
src/QueryBuilder.cpp [deleted file]
src/QueryBuilder.hpp [deleted file]
src/SQLiteConfiguration.cpp [deleted file]
src/SwitchConfigurationItem.cpp
src/SwitchConfigurationItem.hpp
src/UniversalSwitch.cpp
src/hiberlite/LICENSE [new file with mode: 0644]
src/hiberlite/include/BeanLoader.h [new file with mode: 0644]
src/hiberlite/include/BeanLoader_impl.hpp [new file with mode: 0644]
src/hiberlite/include/BeanUpdater.h [new file with mode: 0644]
src/hiberlite/include/BeanUpdater_impl.hpp [new file with mode: 0644]
src/hiberlite/include/ChildKiller.h [new file with mode: 0644]
src/hiberlite/include/ChildKiller_impl.hpp [new file with mode: 0644]
src/hiberlite/include/CppModel.h [new file with mode: 0644]
src/hiberlite/include/Database.h [new file with mode: 0644]
src/hiberlite/include/Database_tmpl_impl.hpp [new file with mode: 0644]
src/hiberlite/include/ModelExtractor.h [new file with mode: 0644]
src/hiberlite/include/ModelExtractor_impl.hpp [new file with mode: 0644]
src/hiberlite/include/Registry.h [new file with mode: 0644]
src/hiberlite/include/Registry_impl.hpp [new file with mode: 0644]
src/hiberlite/include/SQLiteStmt.h [new file with mode: 0644]
src/hiberlite/include/UpdateVisitor_tmpl.hpp [new file with mode: 0644]
src/hiberlite/include/Visitor.h [new file with mode: 0644]
src/hiberlite/include/Visitor_tmpl_impl.hpp [new file with mode: 0644]
src/hiberlite/include/bean_ptr.h [new file with mode: 0644]
src/hiberlite/include/bean_ptr_impl.hpp [new file with mode: 0644]
src/hiberlite/include/common.h [new file with mode: 0644]
src/hiberlite/include/db_error.h [new file with mode: 0644]
src/hiberlite/include/hiberdefs.h [new file with mode: 0644]
src/hiberlite/include/hiberlite.h [new file with mode: 0644]
src/hiberlite/include/nvp.h [new file with mode: 0644]
src/hiberlite/include/shared_res.h [new file with mode: 0644]
src/hiberlite/include/some_types.h [new file with mode: 0644]
src/hiberlite/src/BeanLoader.cpp [new file with mode: 0644]
src/hiberlite/src/BeanUpdater.cpp [new file with mode: 0644]
src/hiberlite/src/ChildKiller.cpp [new file with mode: 0644]
src/hiberlite/src/CppModel.cpp [new file with mode: 0644]
src/hiberlite/src/Database.cpp [new file with mode: 0644]
src/hiberlite/src/ModelExtractor.cpp [new file with mode: 0644]
src/hiberlite/src/Registry.cpp [new file with mode: 0644]
src/hiberlite/src/SQLiteStmt.cpp [new file with mode: 0644]
src/hiberlite/src/Visitor.cpp [new file with mode: 0644]
src/hiberlite/src/shared_res.cpp [new file with mode: 0644]
src/main.cpp
tests/CMakeLists.txt
tests/ui-scenarios/ConfigurationTests.cpp
tests/ui-scenarios/ConfigurationTests.hpp

index 3fc32d3..e3d588e 100644 (file)
@@ -1,8 +1,8 @@
-FILE(GLOB SRCS *.cpp batch/*.cpp)
+FILE(GLOB SRCS *.cpp batch/*.cpp ./hiberlite/src/*.cpp)
 
 ADD_LIBRARY(universal-switch-obj OBJECT ${SRCS})
 
-INCLUDE_DIRECTORIES(${pkgs_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(${pkgs_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/src/hiberlite/include)
 
 ADD_EXECUTABLE(${PROJECT_NAME}  $<TARGET_OBJECTS:universal-switch-obj>)
 TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LIBRARIES})
index 17f6d54..3ed6729 100644 (file)
@@ -31,7 +31,7 @@ public:
 
        virtual void add(const std::shared_ptr<SwitchConfigurationItem> &item) = 0;
        virtual void update(const std::shared_ptr<SwitchConfigurationItem> &item) = 0;
-       virtual void remove(const std::string &switchId) = 0;
+       virtual void remove(const std::shared_ptr<SwitchConfigurationItem> &item) = 0;
        virtual std::shared_ptr<SwitchConfigurationItem> findBySwitchId(const std::string &switchId) const = 0;
        virtual std::vector<std::shared_ptr<SwitchConfigurationItem>> findAll() const = 0;
 };
index e9a9898..d335f3f 100644 (file)
@@ -16,7 +16,7 @@
 
 
 #include "DBusInterface.hpp"
-#include "SQLiteConfiguration.hpp"
+#include "Configuration.hpp"
 #include "ActivityFactory.hpp"
 #include "UniversalSwitch.hpp"
 #include "localization.hpp"
@@ -197,8 +197,15 @@ class DBusInterfaceImpl: public DBusInterface
                }
 
                DEBUG("removing SwitchConfigurationItem switchId: %s", switchId.c_str());
-               configuration->remove(switchId);
-               return DBus::Success{};
+
+               auto configurationItem = configuration->findBySwitchId(switchId);
+               if (configurationItem) {
+                       configuration->remove(configurationItem);
+                       return DBus::Success{};
+               } else {
+                       ERROR("configurationItem switchId: %s not found", switchId.c_str());
+                       return DBus::Error{ "configurationItem switchId: " + switchId + " not found" };
+               }
        }
 
        class DBusSwitchObserver : public Observer<Switch>, public std::enable_shared_from_this<DBusSwitchObserver>
diff --git a/src/HiberliteConfiguration.cpp b/src/HiberliteConfiguration.cpp
new file mode 100644 (file)
index 0000000..8e038d9
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2017  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <service_app.h>
+#include <dlog.h>
+#include <vector>
+
+#include "HiberliteConfiguration.hpp"
+
+HiberliteConfiguration::HiberliteConfiguration(bool resetDB)
+{
+       auto resource = app_get_data_path();
+       if (!resource)
+               ERROR("app_get_data_path() failed");
+
+       dbName = (resource ? resource : "") + std::string{"UniversalSwitch.db"};
+       free(resource);
+
+       db.open(dbName);
+       db.registerBeanClass<SwitchConfigurationItem>();
+
+       if (resetDB)
+               db.dropModel();
+
+       try {
+               db.createModel();
+       } catch (hiberlite::database_error e) {
+               ERROR("error %s", e.what());
+       }
+}
+
+HiberliteConfiguration::~HiberliteConfiguration() {}
+
+void HiberliteConfiguration::add(const std::shared_ptr<SwitchConfigurationItem> &item)
+{
+       SwitchConfigurationItem scItem;
+       scItem.setSwitchId(item->getSwitchId());
+       scItem.setUserName(item->getUserName());
+       scItem.setActivityType(item->getActivityType());
+
+       hiberlite::bean_ptr<SwitchConfigurationItem> p = db.copyBean(scItem);
+
+       item->setChangeType(ChangeType::ADD);
+       if (p) {
+               notify(item);
+               mappingSwitchIdToHiberlitePtr.insert({item->getSwitchId(), p});
+       }
+}
+
+void HiberliteConfiguration::update(const std::shared_ptr<SwitchConfigurationItem> &item)
+{
+       auto switchId = item->getSwitchId();
+       if (mappingSwitchIdToHiberlitePtr.find(switchId) == mappingSwitchIdToHiberlitePtr.end()) {
+               INFO("Updating non existing item");
+               return;
+       }
+
+       auto scItem = mappingSwitchIdToHiberlitePtr[switchId];
+       scItem->setUserName(item->getUserName());
+       scItem->setActivityType(item->getActivityType());
+       scItem.save();
+
+       item->setChangeType(ChangeType::UPDATE);
+       notify(item);
+}
+
+void HiberliteConfiguration::remove(const std::shared_ptr<SwitchConfigurationItem> &item)
+{
+       auto switchId = item->getSwitchId();
+       if (mappingSwitchIdToHiberlitePtr.find(switchId) == mappingSwitchIdToHiberlitePtr.end()) {
+               INFO("Removing non existing item");
+               return;
+       }
+
+       auto scItem = mappingSwitchIdToHiberlitePtr[switchId];
+       item->setChangeType(ChangeType::REMOVE);
+       scItem.destroy();
+
+       mappingSwitchIdToHiberlitePtr.erase(switchId);
+       notify(item);
+}
+
+std::shared_ptr<SwitchConfigurationItem> HiberliteConfiguration::findBySwitchId(const std::string &switchId) const
+{
+       auto p = findAll();
+       for (auto a : p)
+               if (a->getSwitchId() == switchId)
+                       return a;
+
+       return nullptr;
+}
+
+std::vector<std::shared_ptr<SwitchConfigurationItem>> HiberliteConfiguration::findAll() const
+{
+       auto v = db.getAllBeans<SwitchConfigurationItem>();
+
+       std::vector<std::shared_ptr<SwitchConfigurationItem>> res;
+       for (auto p : v) {
+               auto item = std::make_shared<SwitchConfigurationItem>();
+
+               item->setSwitchId(p->getSwitchId());
+               item->setUserName(p->getUserName());
+               item->setActivityType(p->getActivityType());
+
+               mappingSwitchIdToHiberlitePtr[item->getSwitchId()] = p;
+
+               res.push_back(item);
+       }
+
+       return res;
+}
\ No newline at end of file
similarity index 50%
rename from src/SQLiteConfiguration.hpp
rename to src/HiberliteConfiguration.hpp
index 8c5def7..adca06a 100644 (file)
  * limitations under the License.
  */
 
-#ifndef SQLITE_CONFIGURATION_HPP
-#define SQLITE_CONFIGURATION_HPP
+#ifndef HIBERLITE_CONFIGURATION_HPP
+#define HIBERLITE_CONFIGURATION_HPP
 
 #include "Configuration.hpp"
-
-#include <sqlite3.h>
-#include <openssl/aes.h>
-#include <openssl/crypto.h>
-#include <openssl/rand.h>
-#include <openssl/evp.h>
+#include "hiberlite.h"
 
 #include <string>
 #include <functional>
 #include <memory>
 
-class SQLiteConfiguration : public Configuration
+class HiberliteConfiguration : public Configuration
 {
 public:
-       SQLiteConfiguration(bool createInMemory = false);
-       ~SQLiteConfiguration();
+       HiberliteConfiguration(bool resetDB = false);
+       ~HiberliteConfiguration();
 
        void add(const std::shared_ptr<SwitchConfigurationItem> &item) override;
        void update(const std::shared_ptr<SwitchConfigurationItem> &item) override;
-       void remove(const std::string &switchId) override;
+       void remove(const std::shared_ptr<SwitchConfigurationItem> &item) override;
        std::shared_ptr<SwitchConfigurationItem> findBySwitchId(const std::string &switchId) const override;
        std::vector<std::shared_ptr<SwitchConfigurationItem>> findAll() const override;
-
-       void clearTable();
-
-       using execCallback_t = std::function<void(int, char **, char **)>;
 private:
-       bool executeQuery(const std::string &query, const execCallback_t &cb) const;
-       bool executeQuery(const std::string &query) const;
-       void createTable();
-       static std::shared_ptr<SwitchConfigurationItem> constructItem(int argc, char **argv, char **azColName);
-
-       static void update_callback(void *data, int operation, char const *database, char const *table, sqlite_int64 rowid);
-
-       const std::string password;
-       const std::string dbName;
-       const std::string tableName;
+       std::string dbName;
 
-       const std::string switchIdCol;
-       const std::string userNameCol;
-       const std::string activityTypeCol;
+       mutable hiberlite::Database db;
 
-       sqlite3 *dbHandler;
+       mutable std::map< std::string, hiberlite::bean_ptr<SwitchConfigurationItem> > mappingSwitchIdToHiberlitePtr;
 };
 
 #endif
index d3ad2a0..2b3c7f5 100644 (file)
@@ -782,7 +782,7 @@ private:
                                        auto name = wins.all.names[ptr];
                                        if (name == keyboardRootName) {
                                                w.visibility = this->isfPanelStateValue == VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW
-                                                               ? Atspi::WindowVisibility::unobscured : Atspi::WindowVisibility::fully_obscured;
+                                                                          ? Atspi::WindowVisibility::unobscured : Atspi::WindowVisibility::fully_obscured;
                                        }
                                        bool visibility =
                                                w.visibility == Atspi::WindowVisibility::unobscured ||
diff --git a/src/QueryBuilder.cpp b/src/QueryBuilder.cpp
deleted file mode 100644 (file)
index f0f9302..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2017  Samsung Electronics Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "QueryBuilder.hpp"
-
-#include "UniversalSwitchLog.hpp"
-
-QueryBuilder &QueryBuilder::select(const std::initializer_list<std::string> &list)
-{
-       query << "select ";
-
-       bool first = true;
-       for (auto &elem : list) {
-               if (first)
-                       first = false;
-               else
-                       query << ", ";
-               query << elem;
-       }
-       return *this;
-}
-
-QueryBuilder &QueryBuilder::from(const std::string &s)
-{
-       query << " from " << s << " ";
-       return *this;
-}
-
-QueryBuilder &QueryBuilder::where(const std::string &lv, const std::string &op, const std::string &rv)
-{
-       query << "where " << lv << op << "'" << rv  << "' ";
-       return *this;
-}
-
-QueryBuilder &QueryBuilder::set(const std::initializer_list<std::pair<std::string, std::string>> &pairs)
-{
-       query << "set ";
-
-       bool first = true;
-       for (auto &elem : pairs) {
-               if (first)
-                       first = false;
-               else
-                       query << ", ";
-               query << elem.first << "='" << elem.second << "'";
-       }
-       return *this;
-}
-
-QueryBuilder &QueryBuilder::replaceInto(const std::string &s)
-{
-       query << "replace into " << s << " ";
-       return *this;
-}
-
-QueryBuilder &QueryBuilder::values(const std::initializer_list<std::string> &list)
-{
-       query << "values (";
-
-       bool first = true;
-       for (auto &elem : list) {
-               if (first)
-                       first = false;
-               else
-                       query << ", ";
-               query << "'" << elem << "'";
-       }
-
-       query << ") ";
-       return *this;
-}
-
-QueryBuilder &QueryBuilder::update(const std::string &s)
-{
-       query << "update " << s << " ";
-       return *this;
-}
-
-QueryBuilder &QueryBuilder::deleteFrom(const std::string &s)
-{
-       query << "delete from " << s << " ";
-       return *this;
-}
-
-std::string QueryBuilder::build()
-{
-       query << ";";
-       return query.str();
-}
diff --git a/src/QueryBuilder.hpp b/src/QueryBuilder.hpp
deleted file mode 100644 (file)
index 08dcd58..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2017  Samsung Electronics Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef QUERY_BUILDER_HPP
-#define QUERY_BUILDER_HPP
-
-#include <string>
-#include <sstream>
-
-// This function is temporary solution.
-// Better one will be provided in the future.
-
-class QueryBuilder
-{
-public:
-       QueryBuilder &select(const std::initializer_list<std::string> &list);
-       QueryBuilder &from(const std::string &s);
-       QueryBuilder &where(const std::string &lv, const std::string &op, const std::string &rv);
-       QueryBuilder &set(const std::initializer_list<std::pair<std::string, std::string>> &pairs);
-       QueryBuilder &replaceInto(const std::string &s);
-       QueryBuilder &values(const std::initializer_list<std::string> &list);
-       QueryBuilder &update(const std::string &s);
-       QueryBuilder &deleteFrom(const std::string &s);
-       QueryBuilder &onDuplicateUpdate(const std::initializer_list<std::string> &argNames);
-       QueryBuilder &argumentNames(const std::initializer_list<std::string> &argNames);
-
-       std::string build();
-
-private:
-       std::ostringstream query;
-};
-
-#endif
diff --git a/src/SQLiteConfiguration.cpp b/src/SQLiteConfiguration.cpp
deleted file mode 100644 (file)
index a84746b..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright 2017  Samsung Electronics Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SQLiteConfiguration.hpp"
-#include <service_app.h>
-#include <dlog.h>
-
-#include "QueryBuilder.hpp"
-
-enum SwitchConfigurationItemFields {
-       SWITCH_ID,
-       USER_NAME,
-       ACTIVITY_TYPE,
-       Count
-};
-
-SQLiteConfiguration::SQLiteConfiguration(bool createInMemory)
-       : password("UniversalSwitchPassword"), dbName(createInMemory ? ":memory:" : "UniversalSwitch.db"), tableName("`UNIVERSAL_SWITCH`"),
-         switchIdCol("`SWITCH_ID`"), userNameCol("`USER_NAME`"),
-         activityTypeCol("`ACTIVITY_TYPE`")
-{
-       sqlite3_shutdown();
-
-       sqlite3_config(SQLITE_CONFIG_URI, 1);
-       sqlite3_initialize();
-
-       std::string path;
-       if (createInMemory) {
-               auto resource = app_get_data_path();
-               if (!resource)
-                       ERROR("app_get_data_path() failed");
-
-               path = (resource ? resource : "") + dbName;
-               free(resource);
-       } else {
-               path = dbName;
-       }
-
-       if (sqlite3_open(path.c_str(), &dbHandler) != SQLITE_OK) {
-               ERROR("sqlite3_open() failed");
-               throw std::runtime_error("SQLite connection failed");
-       }
-
-       sqlite3_update_hook(dbHandler, update_callback, nullptr);
-       createTable();
-}
-
-SQLiteConfiguration::~SQLiteConfiguration()
-{
-       sqlite3_close(dbHandler);
-       sqlite3_shutdown();
-}
-
-void SQLiteConfiguration::add(const std::shared_ptr<SwitchConfigurationItem> &item)
-{
-       auto query = QueryBuilder().replaceInto(tableName).values({item->getSwitchId(),
-                                item->getUserName(),
-                                item->getActivityType()
-                                                                                                                         }).build();
-
-       item->setChangeType(ChangeType::ADD);
-       if (executeQuery(query))
-               notify(item);
-}
-
-void SQLiteConfiguration::update(const std::shared_ptr<SwitchConfigurationItem> &item)
-{
-       std::initializer_list<std::pair<std::string, std::string>> setCollection {
-               {userNameCol, item->getUserName()},
-               {activityTypeCol, item->getActivityType()}
-       };
-
-       auto query = QueryBuilder().update(tableName).set(setCollection).where(switchIdCol, "=", item->getSwitchId()).build();
-
-       INFO("update query: %s", query.c_str());
-
-       item->setChangeType(ChangeType::UPDATE);
-       if (executeQuery(query))
-               notify(item);
-}
-
-void SQLiteConfiguration::remove(const std::string &switchId)
-{
-       auto item = findBySwitchId(switchId);
-
-       if (!item) {
-               INFO("empty item");
-               return;
-       }
-
-       INFO("item to remove: %s, %s", item->getSwitchId().c_str(), item->getActivityType().c_str());
-
-       auto query = QueryBuilder().deleteFrom(tableName).where(switchIdCol, "=", switchId).build();
-
-       INFO("remove query: %s", query.c_str());
-       item->setChangeType(ChangeType::REMOVE);
-       if (executeQuery(query))
-               notify(item);
-}
-
-std::shared_ptr<SwitchConfigurationItem> SQLiteConfiguration::findBySwitchId(const std::string &switchId) const
-{
-       auto query = QueryBuilder().select({"*"}).from(tableName).where(switchIdCol, "=", switchId).build();
-       INFO("query: %s", query.c_str());
-
-       std::shared_ptr<SwitchConfigurationItem> item;
-
-       if (!executeQuery(query, [&item](int argc, char **argv, char **azColName) {
-       item = constructItem(argc, argv, azColName);
-       }))
-       return nullptr;
-
-       if (!item) {
-               DEBUG("No item found");
-               return nullptr;
-       }
-
-       INFO("Found: %s, %s, %s", item->getSwitchId().c_str(), item->getUserName().c_str(), item->getActivityType().c_str());
-       return item;
-}
-
-std::vector<std::shared_ptr<SwitchConfigurationItem>> SQLiteConfiguration::findAll() const
-{
-       auto query = QueryBuilder().select({"*"}).from(tableName).build();
-
-       auto collection = std::vector<std::shared_ptr<SwitchConfigurationItem>>();
-
-       if (!executeQuery(query, [&collection](int argc, char **argv, char **azColName) {
-       collection.emplace_back(constructItem(argc, argv, azColName));
-       }))
-       return {};
-
-       return collection;
-}
-
-static int call_functor(void *data, int argc, char **argv, char **colName)
-{
-       auto &callback = *(const SQLiteConfiguration::execCallback_t *)data;
-       callback(argc, argv, colName);
-       return 0;
-}
-
-bool SQLiteConfiguration::executeQuery(const std::string &query, const execCallback_t &cb) const
-{
-       INFO("executeQuery: %s", query.c_str());
-       char *errorMessage = nullptr;
-       auto result = sqlite3_exec(dbHandler, query.c_str(), call_functor, const_cast<execCallback_t *>(&cb), &errorMessage);
-       if (result != SQLITE_OK) {
-               ERROR("sqlite ERROR: %s", errorMessage);
-               sqlite3_free(errorMessage);
-               return false;
-       }
-       return true;
-}
-
-bool SQLiteConfiguration::executeQuery(const std::string &query) const
-{
-       return executeQuery(query, nullptr);
-}
-
-void SQLiteConfiguration::createTable()
-{
-       auto query = "CREATE TABLE IF NOT EXISTS " + tableName + "("
-                                + switchIdCol + " TEXT NOT NULL, "
-                                + userNameCol + " TEXT, "
-                                + activityTypeCol + " TEXT NOT NULL, "
-                                + "PRIMARY KEY (" + switchIdCol + "));";
-
-       INFO("query: %s", query.c_str());
-       executeQuery(query);
-}
-
-std::shared_ptr<SwitchConfigurationItem> SQLiteConfiguration::constructItem(int argc, char **argv, char **azColName)
-{
-       if (argc != SwitchConfigurationItemFields::Count) {
-               ERROR("Fields number does not match the one in SwitchConfigurationItem");
-               return nullptr;
-       }
-
-       auto item = std::make_shared<SwitchConfigurationItem>();
-
-       item->setSwitchId(argv[SwitchConfigurationItemFields::SWITCH_ID]);
-       item->setUserName(argv[SwitchConfigurationItemFields::USER_NAME]);
-       item->setActivityType(argv[SwitchConfigurationItemFields::ACTIVITY_TYPE]);
-
-       INFO("switchId: %s, userName: %s, activityType: %s", item->getSwitchId().c_str(), item->getUserName().c_str(), item->getActivityType().c_str());
-
-       return item;
-}
-
-void SQLiteConfiguration::clearTable()
-{
-       auto query = "DELETE FROM " + tableName ;
-
-       executeQuery(query);
-}
-
-void SQLiteConfiguration::update_callback(void *data, int operation, char const *database, char const *table, sqlite_int64 rowid)
-{
-       INFO(">>> update callback <<<");
-       INFO("insert: %d, delete: %d, update: %d, current: %d", SQLITE_INSERT, SQLITE_DELETE, SQLITE_UPDATE, operation);
-       INFO("operation: %d, db: %s, table: %s, %ld", operation, database, table, rowid);
-       INFO(">>> update callback done <<<");
-}
index a7b55d3..a05828a 100644 (file)
@@ -18,6 +18,8 @@
 
 #include <dlog.h>
 
+HIBERLITE_EXPORT_CLASS(SwitchConfigurationItem)
+
 SwitchConfigurationItem::SwitchConfigurationItem(const std::string &switchId, const std::string &activityType)
        : switchId(switchId), activityType(activityType)
 {}
index 8f3fe59..a19a499 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <string>
 
+#include "hiberlite.h"
 #include "UniversalSwitchLog.hpp"
 
 enum ChangeType {
@@ -45,6 +46,14 @@ public:
        ChangeType getChangeType() const;
        void setChangeType(ChangeType type);
 
+       friend class hiberlite::access;
+       template<class Archive>
+       void hibernate(Archive &ar)
+       {
+               ar &HIBERLITE_NVP(switchId);
+               ar &HIBERLITE_NVP(userName);
+               ar &HIBERLITE_NVP(activityType);
+       }
 private:
        std::string switchId;
        std::string userName;
index af1fdb5..1a890b7 100644 (file)
@@ -23,7 +23,7 @@
 #include "ScreenScannerManager.hpp"
 #include "ScreenSwitchProvider.hpp"
 #include "SoundFeedback.hpp"
-#include "SQLiteConfiguration.hpp"
+#include "HiberliteConfiguration.hpp"
 #include "SwitchConfigurationItem.hpp"
 #include "SwitchManager.hpp"
 #include "TextToSpeech.hpp"
@@ -55,8 +55,7 @@ bool UniversalSwitch::initialize(const std::array<Optional<std::string>, (size_t
        compositeSwitchProvider->add(std::make_shared<AccessoriesSwitchProvider>());
        compositeSwitchProvider->add(std::make_shared<CameraSwitchProvider>());
 
-       //TODO: temporarily memory database is used (change to file database)
-       auto configuration = std::make_shared<SQLiteConfiguration>(true);
+       auto configuration = std::make_shared<HiberliteConfiguration>(false);
 
        setCompositeSwitchProvider(compositeSwitchProvider);
        setConfiguration(configuration);
diff --git a/src/hiberlite/LICENSE b/src/hiberlite/LICENSE
new file mode 100644 (file)
index 0000000..7f4b30d
--- /dev/null
@@ -0,0 +1,25 @@
+Copyright (c) 2008-2014, Paul Korzhyk
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+ * Neither the name of Hiberlite nor the names of its contributors may be used
+   to endorse or promote products derived from this software without specific
+   prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/hiberlite/include/BeanLoader.h b/src/hiberlite/include/BeanLoader.h
new file mode 100644 (file)
index 0000000..0991bad
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef BeanLoader_H
+#define BeanLoader_H
+
+namespace hiberlite
+{
+
+       class LoadBean
+       {
+       public:
+               template<class AV>
+               inline void notifyInitWalk(AV &av);
+
+               template<class AV>
+               inline void notifyDoneWalk(AV &av);
+
+               template<class AV, class C>
+               inline void act(AV &av, db_atom<C> atom)
+               {
+                       int col_indx = locateCol(av.getScope().prefix());
+                       atom.loadValue(stmt.top().first, col_indx);
+               }
+
+               template<class AV, class E, class S>
+               inline void act(AV &av, collection_nvp<E, S> nvp);
+
+       protected:
+               std::stack< std::pair<SQLiteSelect, sqlid_t> > stmt;
+
+               inline int locateCol(std::string name)
+               {
+                       SQLiteSelect &sel = stmt.top().first;
+                       unsigned int n = sel.column_count();
+                       for (unsigned int i = 0; i < n; i++)
+                               if (sel.get_name(i) == name)
+                                       return i;
+                       throw database_error(name + ": column not found in SELECT query results");
+               }
+       };
+
+       class BeanLoader : AVisitor<LoadBean>
+       {
+       public:
+               BeanLoader();
+
+               template<class C>
+               C *loadBean(bean_key k);
+
+       protected:
+               LoadBean actor;
+
+       private:
+       };
+
+} //namespace hiberlite
+
+#endif // BeanLoader_H
diff --git a/src/hiberlite/include/BeanLoader_impl.hpp b/src/hiberlite/include/BeanLoader_impl.hpp
new file mode 100644 (file)
index 0000000..fda8737
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef BeanLoader_IMPL_HPP_INCLUDED
+#define BeanLoader_IMPL_HPP_INCLUDED
+
+namespace hiberlite
+{
+
+       template<class AV>
+       void LoadBean::notifyInitWalk(AV &av)
+       {
+               while (!stmt.empty())
+                       stmt.pop();
+
+               sqlid_t curId = av.getRootId();
+
+               std::string query = "SELECT * FROM " + av.getScope().table()
+                                                       + " WHERE " + HIBERLITE_PRIMARY_KEY_COLUMN + "=" + Transformer::toSQLiteValue(curId) + ";";
+
+               SQLiteSelect sel(av.getConnection(), query);
+               if (!sel.step())
+                       throw database_error("Id " + std::to_string(curId) + " not found in table " + av.getScope().table());
+               stmt.push(std::make_pair(sel, curId));
+       }
+
+       template<class AV>
+       void LoadBean::notifyDoneWalk(AV &av)
+       {
+               while (!stmt.empty())
+                       stmt.pop();
+       }
+
+       template<class AV, class E, class S>
+       void LoadBean::act(AV &av, collection_nvp<E, S> nvp)
+       {
+               av.diveTable(nvp.name);
+               std::string tab = av.getScope().table();
+               std::vector<sqlid_t> children = Database::dbSelectChildIds(av.getConnection(), tab, stmt.top().second);
+               nvp.stream.startLoadFromDb();
+
+               for (size_t i = 0; i < children.size(); i++) {
+                       E *entry;
+                       construct(av, &entry, static_cast<unsigned int>(0));
+
+                       std::string query = "SELECT * FROM " + tab
+                                                               + " WHERE " + HIBERLITE_PRIMARY_KEY_COLUMN + "=" + Transformer::toSQLiteValue(children[i]) + ";";
+                       SQLiteSelect sel(av.getConnection(), query);
+                       if (!sel.step())
+                               throw database_error("id not found in the database");
+                       stmt.push(std::make_pair(sel, children[i]));
+
+                       sql_nvp<E> el("item", *entry);
+                       av &el;
+
+                       stmt.pop();
+                       nvp.stream.putNext(*entry);
+                       destroy(*this, entry, static_cast<unsigned int>(0));
+               }
+               av.pop();
+       }
+
+       template<class C>
+       C *BeanLoader::loadBean(bean_key key)
+       {
+               C *bean;
+               construct(*this, &bean, static_cast<unsigned int>(0));
+               startWalk(*bean, key);
+               return bean;
+       }
+
+} //namespace hiberlite
+
+#endif // BEANUPDATER_IMPL_HPP_INCLUDED
diff --git a/src/hiberlite/include/BeanUpdater.h b/src/hiberlite/include/BeanUpdater.h
new file mode 100644 (file)
index 0000000..9d65c97
--- /dev/null
@@ -0,0 +1,168 @@
+#ifndef BEANUPDATER_H
+#define BEANUPDATER_H
+
+#include <stdio.h>
+#include <string.h>
+
+namespace hiberlite
+{
+
+       struct RowScope {
+               static const int FirstAtom = 100;
+               std::vector<abstract_atom *> atoms;
+               std::string table;
+               std::string query;
+               sqlid_t id;
+               bool needComma;
+               template<class C>
+               inline void addAssignment(const std::string name, db_atom<C> &atom);
+
+               void addSimpleAssign(const std::string name, std::string value);
+
+               ~RowScope();
+       };
+
+       class Transformer
+       {
+       public:
+               static std::string toSQLiteValue(const double &val)
+               {
+                       char s[64];
+                       sprintf(s, "%lf", val);
+                       return s;
+               }
+               static std::string toSQLiteValue(const float &val)
+               {
+                       char s[64];
+                       sprintf(s, "%f", val);
+                       return s;
+               }
+               static std::string toSQLiteValue(const long double &val)
+               {
+                       char s[64];
+                       sprintf(s, "%Lf", val);
+                       return s;
+               }
+
+#define HIBERLITE_STRINGIFY_NUM(VALTYPE) \
+       static std::string toSQLiteValue(const VALTYPE &val){ \
+               char s[64];                                     \
+               char* p=s+63;                           \
+               *(p--)=0;                                       \
+               VALTYPE tmp=val;                        \
+               bool needmin=0;                         \
+               if(tmp<(VALTYPE)0)                      \
+                       needmin=1,tmp*=-1;              \
+               do{                                                     \
+                       *(p--)='0' + (tmp%10);  \
+                       tmp/=10;                                \
+               }while(tmp);                            \
+               if(needmin) *(p--)='-';         \
+               return p+1;                                     \
+       }
+
+#define HIBERLITE_STRINGIFY_UNSIGNED_NUM(VALTYPE) \
+       static std::string toSQLiteValue(const VALTYPE &val){ \
+               char s[64];                                     \
+               char* p=s+63;                           \
+               *(p--)=0;                                       \
+               VALTYPE tmp=val;                        \
+               do{                                                     \
+                       *(p--)='0' + (tmp%10);  \
+                       tmp/=10;                                \
+               }while(tmp);                            \
+               return p+1;                                     \
+       }
+
+               HIBERLITE_STRINGIFY_NUM(int)
+               HIBERLITE_STRINGIFY_UNSIGNED_NUM(unsigned int)
+               HIBERLITE_STRINGIFY_NUM(signed char)
+//HIBERLITE_STRINGIFY_NUM(unsigned char)
+               HIBERLITE_STRINGIFY_NUM(long long int)
+               HIBERLITE_STRINGIFY_UNSIGNED_NUM(unsigned long long int)
+#undef HIBERLITE_STRINGIFY_NUM
+
+               static std::string toSQLiteValue(const unsigned char &val)
+               {
+                       char s[64];
+                       int i = 63;
+                       s[i--] = 0;
+                       unsigned char tmp = val;
+                       do {
+                               s[i--] = '0' + (tmp % 10);
+                               tmp /= 10;
+                       } while (tmp);
+                       return s + i + 1;
+               }
+
+
+               static std::string toSQLiteValue(const char *val)
+               {
+                       size_t n = strlen(val);
+                       char *s = new char[4 + 2 * n];
+                       int x = sprintf(s, "X'");
+
+                       for (unsigned int i = 0; i < n; i++) {
+                               unsigned char cc = (unsigned char)val[i];
+                               x += sprintf(s + x, "%02X", (int)cc);
+                       }
+                       sprintf(s + x, "'");
+                       std::string res(s);
+                       delete[] s;
+                       return res;
+               }
+
+               static std::string toSQLiteValue(const std::string val)
+               {
+                       return toSQLiteValue(val.c_str());
+               }
+
+               static std::string toSQLiteValue(const bool val)
+               {
+                       return val ? "1" : "0";
+               }
+       };
+
+       class UpdateBean
+       {
+       public:
+               template<class AV>
+               inline void notifyInitWalk(AV &av);
+
+               template<class AV>
+               inline void notifyDoneWalk(AV &av);
+
+               template<class AV, class C>
+               inline void act(AV &av, db_atom<C> atom)
+               {
+                       curRow()->addAssignment(av.getScope().prefix(), atom);
+               }
+
+               template<class AV, class E, class S>
+               inline void act(AV &av, collection_nvp<E, S> nvp);
+
+       protected:
+               std::stack< shared_res<RowScope> > rowStack;
+               RowScope *curRow();
+
+               void startRow(std::string table, sqlid_t rowid, sqlid_t parent_id, sqlid_t index);
+               void commitRow(shared_connection con, sqlid_t rowid);
+       };
+
+       class BeanUpdater : AVisitor<UpdateBean>
+       {
+       public:
+               BeanUpdater();
+
+               template<class C>
+               void update(bean_key k, C &bean);
+
+       protected:
+               UpdateBean actor;
+
+       private:
+       };
+
+} //namespace hiberlite
+
+#endif // BEANUPDATER_H
diff --git a/src/hiberlite/include/BeanUpdater_impl.hpp b/src/hiberlite/include/BeanUpdater_impl.hpp
new file mode 100644 (file)
index 0000000..b82a04d
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef BEANUPDATER_IMPL_HPP_INCLUDED
+#define BEANUPDATER_IMPL_HPP_INCLUDED
+
+namespace hiberlite
+{
+
+       template<class C>
+       inline void RowScope::addAssignment(const std::string name, db_atom<C> &atom)
+       {
+               int id = FirstAtom + static_cast<int>(atoms.size());
+
+               addSimpleAssign(name, "?" + Transformer::toSQLiteValue(id));
+
+               db_atom<C> *x = new db_atom<C>(atom);
+               atoms.push_back(x);
+       }
+
+       template<class AV>
+       void UpdateBean::notifyInitWalk(AV &av)
+       {
+               startRow(av.getScope().table(), av.getRootId(), Database::NULL_ID, 0);
+       }
+
+       template<class AV>
+       void UpdateBean::notifyDoneWalk(AV &av)
+       {
+               commitRow(av.getConnection(), av.getRootId());
+       }
+
+       template<class AV, class E, class S>
+       void UpdateBean::act(AV &av, collection_nvp<E, S> nvp)
+       {
+
+               sqlid_t index = 0;
+               S &stream = nvp.stream;
+
+               av.diveTable(nvp.name);
+               std::string tab = av.getScope().table();
+               while (!stream.done()) {
+                       E &el = stream.getNext();
+                       sqlid_t entry_id = Database::allocId(av.getConnection(), tab);
+
+                       startRow(tab, entry_id, curRow()->id, index);
+                       sql_nvp<E> el_nvp("item", el);
+                       av &el_nvp;
+                       commitRow(av.getConnection(), entry_id);
+                       index++;
+               }
+               av.pop();
+       }
+
+       template<class C>
+       void BeanUpdater::update(bean_key key, C &bean)
+       {
+               startWalk(bean, key);
+       }
+
+} //namespace hiberlite
+
+#endif // BEANUPDATER_IMPL_HPP_INCLUDED
diff --git a/src/hiberlite/include/ChildKiller.h b/src/hiberlite/include/ChildKiller.h
new file mode 100644 (file)
index 0000000..8f947cc
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef CHILDKILLER_H
+#define CHILDKILLER_H
+
+namespace hiberlite
+{
+
+       class KillChildren
+       {
+       public:
+               template<class AV>
+               inline void notifyInitWalk(AV &av);
+
+               template<class AV>
+               inline void notifyDoneWalk(AV &av);
+
+               template<class AV, class C>
+               inline void act(AV &av, db_atom<C> nvp) {}
+
+               template<class AV, class E, class S>
+               inline void act(AV &av, collection_nvp<E, S> nvp);
+
+       protected:
+               std::stack<sqlid_t> rowId;
+       };
+
+       class ChildKiller : AVisitor<KillChildren>
+       {
+       public:
+               ChildKiller();
+
+               template<class C>
+               void killChildren(bean_key k, C &bean);
+
+       protected:
+               KillChildren actor;
+
+       private:
+       };
+
+} //namespace hiberlite
+
+#endif // CHILDKILLER_H
diff --git a/src/hiberlite/include/ChildKiller_impl.hpp b/src/hiberlite/include/ChildKiller_impl.hpp
new file mode 100644 (file)
index 0000000..137bf8b
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef CHILDKILLER_IMPL_HPP_INCLUDED
+#define CHILDKILLER_IMPL_HPP_INCLUDED
+
+namespace hiberlite
+{
+
+       template<class AV>
+       void KillChildren::notifyInitWalk(AV &av)
+       {
+               rowId = std::stack<sqlid_t>();
+               rowId.push(av.getRootId());
+       }
+
+       template<class AV>
+       void KillChildren::notifyDoneWalk(AV &av)
+       {
+       }
+
+       template<class AV, class E, class S>
+       void KillChildren::act(AV &av, collection_nvp<E, S> nvp)
+       {
+               av.diveTable(nvp.name);
+               std::string tab = av.getScope().table();
+               std::vector<sqlid_t> children = Database::dbSelectChildIds(av.getConnection(), tab, rowId.top());
+               for (size_t i = 0; i < children.size(); i++) {
+                       E *entry;
+                       construct(av, &entry, static_cast<unsigned int>(0));
+                       rowId.push(children[i]);
+                       sql_nvp<E> el("item", *entry);
+                       av &el;
+                       rowId.pop();
+                       destroy(*this, entry, static_cast<unsigned int>(0));
+               }
+               av.pop();
+
+               Database::dbDeleteRows(av.getConnection(), tab, HIBERLITE_PARENTID_COLUMN, rowId.top());
+       }
+
+       template<class C>
+       void ChildKiller::killChildren(bean_key key, C &bean)
+       {
+               startWalk(bean, key);
+       }
+
+} //namespace hiberlite
+
+
+#endif // BEANUPDATER_IMPL_HPP_INCLUDED
diff --git a/src/hiberlite/include/CppModel.h b/src/hiberlite/include/CppModel.h
new file mode 100644 (file)
index 0000000..d83f9b7
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef CPPMODEL_H
+#define CPPMODEL_H
+
+namespace hiberlite
+{
+
+       class Scope
+       {
+       public:
+               std::string _table, _prefix;
+               int prefix_depth;
+
+               inline Scope(std::string t, std::string p): _table(t)
+                       , _prefix(p)
+                       , prefix_depth(0)
+               {}
+               inline Scope() : prefix_depth(0) {}
+
+               inline std::string table()
+               {
+                       return _table;
+               }
+               inline std::string prefix()
+               {
+                       return _prefix;
+               }
+
+               std::string name_column(std::string name);
+               std::string full();
+       };
+
+       class Column
+       {
+       public:
+               inline Column(std::string _n = "", std::string _s = "") : name(_n), storage_type(_s) {}
+               std::string name;
+               std::string storage_type;
+       };
+
+       class Table
+       {
+       public:
+               Table();
+               std::string name;
+               std::map<std::string, Column> columns;
+               void add(Column c);
+               bool contains(std::string colname);
+       };
+
+       class Model : public std::map<std::string, Table>
+       {
+       public:
+               void add(Table t);
+       };
+
+}//namespace hiberlite
+
+#endif // CPPMODEL_H
diff --git a/src/hiberlite/include/Database.h b/src/hiberlite/include/Database.h
new file mode 100644 (file)
index 0000000..c8da03f
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef DATABASE_H
+#define DATABASE_H
+
+namespace hiberlite
+{
+
+       class ModelExtractor;
+       class UpdateBean;
+
+       class Database : noncopyable
+       {
+       protected:
+               friend class UpdateBean;
+               friend class KillChildren;
+               friend class LoadBean;
+
+               template<class C>
+               friend class real_bean;
+
+               ModelExtractor *mx;
+
+               template<class C>
+               static void dbDelete(bean_key key, C &bean);
+
+               template<class C>
+               static void dbUpdate(bean_key key, C &bean);
+
+               template<class C>
+               static C *dbLoad(bean_key key);
+
+               static sqlid_t allocId(shared_connection c, std::string table);
+               sqlid_t allocId(std::string table);
+
+               static void dbExecQuery(shared_connection con, std::string query);
+               void dbExecQuery(std::string query);
+
+               static std::vector<sqlid_t> dbSelectIds(shared_connection con, const std::string table,
+                                                                                               const std::string condition, const std::string orderBy);
+
+               static std::vector<sqlid_t> dbSelectChildIds(shared_connection con, std::string table, sqlid_t parent);
+               inline std::vector<sqlid_t> dbSelectChildIds(std::string table, sqlid_t parent);
+
+               shared_connection con;
+
+               template<class C>
+               static void dbDeleteRows(shared_connection con, std::string table, std::string column, C value);
+
+       public:
+               static const sqlid_t NULL_ID = -1;
+
+               template<class C>
+               static std::string getClassName();
+
+               Database();
+               Database(std::string fname);
+               virtual ~Database();
+
+               void open(std::string fname);
+               void close();
+
+               template<class C>
+               inline void registerBeanClass();
+
+               Model getModel();
+               inline shared_connection getConnection()
+               {
+                       return con;
+               }
+
+               std::vector<std::string> checkModel();
+               void dropModel();
+               void createModel();
+
+               template<class C>
+               bean_ptr<C> loadBean(sqlid_t objId);
+
+               template<class C>
+               std::vector<sqlid_t> getBeanIds();
+
+               template<class C>
+               std::vector< bean_ptr<C> > getAllBeans();
+
+               template<class C>
+               bean_ptr<C> copyBean(const C &c);
+
+               template<class C>
+               bean_ptr<C> createBean();
+
+               template<class C>
+               bean_ptr<C> manageBean(C *ptr);
+       };
+
+} //namespace hiberlite;
+
+
+#endif // DATABASE_H
diff --git a/src/hiberlite/include/Database_tmpl_impl.hpp b/src/hiberlite/include/Database_tmpl_impl.hpp
new file mode 100644 (file)
index 0000000..7428784
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef DATABASE_TMPL_IMPL_HPP_INCLUDED
+#define DATABASE_TMPL_IMPL_HPP_INCLUDED
+
+namespace hiberlite
+{
+
+       template<class C>
+       void Database::dbDelete(bean_key key, C &bean)
+       {
+               try {
+                       dbExecQuery(key.con, "ROLLBACK TRANSACTION;");
+               } catch (...) {}
+               dbExecQuery(key.con, "BEGIN TRANSACTION;");
+
+               ChildKiller ck;
+               ck.killChildren(key, bean);
+               dbDeleteRows(key.con, Database::getClassName<C>(), HIBERLITE_PRIMARY_KEY_COLUMN, key.id);
+
+               dbExecQuery(key.con, "COMMIT TRANSACTION;");
+       }
+
+       template<class C>
+       void Database::dbDeleteRows(shared_connection con, std::string table, std::string column, C value)
+       {
+               std::string query = "DELETE FROM " + table
+                                                       + " WHERE " + column + "=" + Transformer::toSQLiteValue(value) + ";";
+               dbExecQuery(con, query);
+       }
+
+
+       template<class C>
+       void Database::dbUpdate(bean_key key, C &bean)
+       {
+               try {
+                       dbExecQuery(key.con, "ROLLBACK TRANSACTION;");
+               } catch (...) {}
+               dbExecQuery(key.con, "BEGIN TRANSACTION;");
+
+               ChildKiller ck;
+               ck.killChildren(key, bean);
+               BeanUpdater u;
+               u.update(key, bean);
+
+               dbExecQuery(key.con, "COMMIT TRANSACTION;");
+       }
+
+       template<class C>
+       C *Database::dbLoad(bean_key key)
+       {
+               BeanLoader bl;
+               return bl.loadBean<C>(key);
+       }
+
+       template<class C>
+       inline bean_ptr<C> Database::createBean()
+       {
+               C *obj = new C();
+               return manageBean<C>(obj);
+       }
+
+       template<class C>
+       bean_ptr<C> Database::copyBean(const C &c)
+       {
+               return manageBean<C>(new C(c));
+       }
+
+       template<class C>
+       inline bean_ptr<C> Database::manageBean(C *ptr)
+       {
+               sqlid_t id = allocId(Database::getClassName<C>());
+               bean_key key(con, id);
+               dbUpdate(key, *ptr);
+               return Registry<C>::createBeanPtr(key, ptr);
+       }
+
+       template<class C>
+       inline bean_ptr<C> Database::loadBean(sqlid_t id)
+       {
+               return Registry<C>::get(bean_key(con, id));
+       }
+
+       template<class C>
+       std::vector<sqlid_t> Database::getBeanIds()
+       {
+               return dbSelectIds(con, getClassName<C>(), "", "");
+       }
+
+       template<class C>
+       std::vector< bean_ptr<C> > Database::getAllBeans()
+       {
+               std::vector<sqlid_t> ids = getBeanIds<C>();
+               size_t N = ids.size();
+               std::vector< bean_ptr<C> > ans;
+               ans.reserve(N);
+               for (size_t i = 0; i < N; i++)
+                       ans.push_back(loadBean<C>(ids[i]));
+               return ans;
+       }
+
+       template<class C>
+       inline void Database::registerBeanClass()
+       {
+               if (!mx)
+                       mx = new ModelExtractor();
+               std::string classname = Database::getClassName<C>();
+
+               mx->extractModel<C>(con);
+       }
+
+} //namespace hiberlite
+
+#endif // DATABASE_TMPL_IMPL_HPP_INCLUDED
diff --git a/src/hiberlite/include/ModelExtractor.h b/src/hiberlite/include/ModelExtractor.h
new file mode 100644 (file)
index 0000000..bb133b9
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef MODELEXTRACTOR_H
+#define MODELEXTRACTOR_H
+
+namespace hiberlite
+{
+
+       class ExtractModel
+       {
+       public:
+               Model getModel();
+
+               template<class AV>
+               inline void notifyInitWalk(AV &av)
+               {
+                       model[av.getScope().table()].name = av.getScope().table();
+               }
+
+               template<class AV>
+               inline void notifyDoneWalk(AV &av) {}
+
+               template<class AV, class X>
+               inline void act(AV &av, db_atom<X> atom)
+               {
+                       putColumn(av, atom.sqliteStorageClass());
+               }
+
+               template<class AV, class E, class S>
+               inline void act(AV &av, collection_nvp<E, S> nvp);
+
+       protected:
+               template<class AV>
+               inline void putColumn(AV &av, std::string storage)
+               {
+                       Scope scope = av.getScope();
+                       putNamedColumn(scope.table(), scope.prefix(), storage);
+               }
+
+               inline void putNamedColumn(std::string table, std::string colname, std::string storClass)
+               {
+                       model[ table ].name = table;
+                       if (model[table].contains(colname))
+                               throw std::logic_error(colname + ": column name is in use");
+                       model[ table ].add(Column(colname, storClass));
+               }
+
+               Model model;
+       };
+
+       class ModelExtractor : AVisitor<ExtractModel>
+       {
+       public:
+               ModelExtractor();
+               template<class C>
+               void extractModel(shared_connection _con);
+               Model getModel();
+
+       protected:
+               ExtractModel actor;
+       };
+
+} //namespace hiberlite
+
+#endif // MODELEXTRACTOR_H
diff --git a/src/hiberlite/include/ModelExtractor_impl.hpp b/src/hiberlite/include/ModelExtractor_impl.hpp
new file mode 100644 (file)
index 0000000..71e2d6c
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef MODELEXTRACTOR_IMPL_HPP_INCLUDED
+#define MODELEXTRACTOR_IMPL_HPP_INCLUDED
+
+namespace hiberlite
+{
+
+       template<class AV, class E, class S>
+       void ExtractModel::act(AV &av, collection_nvp<E, S> nvp)
+       {
+               E *entry;
+               construct(av, &entry, static_cast<unsigned int>(0));
+               av.diveTable(nvp.name);
+
+               putNamedColumn(av.getScope().table(), HIBERLITE_PARENTID_COLUMN, HIBERLITE_ID_STORAGE_CLASS);
+               putNamedColumn(av.getScope().table(), HIBERLITE_ENTRY_INDEX_COLUMN, HIBERLITE_ID_STORAGE_CLASS);
+
+               sql_nvp<E> el("item", *entry);
+               av &el;
+               av.pop();
+               destroy(*this, entry, static_cast<unsigned int>(0));
+       }
+
+       template<class C>
+       void ModelExtractor::extractModel(shared_connection _con)
+       {
+               C *bean;
+               construct(*this, &bean, static_cast<unsigned int>(0));
+               bean_key key(_con, Database::NULL_ID);
+               startWalk(*bean, key);
+               destroy(*this, bean, static_cast<unsigned int>(0));
+       }
+
+} //namespace hiberlite
+
+#endif // MODELEXTRACTOR_IMPL_HPP_INCLUDED
diff --git a/src/hiberlite/include/Registry.h b/src/hiberlite/include/Registry.h
new file mode 100644 (file)
index 0000000..27847c0
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef REGISTRY_H_INCLUDED
+#define REGISTRY_H_INCLUDED
+
+namespace hiberlite
+{
+
+       class Database;
+
+       template<class C> class bean_ptr;
+       template<class C> class Registry;
+       template<class C> class real_bean;
+
+       template<class C>
+       class rb_pair : public shared_cnt_obj_pair< real_bean<C> >
+       {
+       protected:
+               friend class Registry<C>;
+
+               inline rb_pair(real_bean<C> *rbean);
+
+       public:
+               inline bean_key get_key();
+               inline virtual ~rb_pair();
+       };
+
+
+       template<class C>
+       class Registry
+       {
+       protected:
+               friend class rb_pair<C>;
+
+               static std::map<bean_key, rb_pair<C>* > rbpairs;
+
+               static void notifyRBDies(rb_pair<C> *r);
+
+       public:
+               static bean_ptr<C> get(const bean_key key);
+               static bool has(const bean_key key);
+
+               static bean_ptr<C> createBeanPtr(bean_key key, C *obj);
+       };
+
+       template<class C>
+       std::map< bean_key, rb_pair<C>* > Registry<C>::rbpairs;
+
+} //namespace hiberlite
+
+#endif // REGISTRY_H_INCLUDED
diff --git a/src/hiberlite/include/Registry_impl.hpp b/src/hiberlite/include/Registry_impl.hpp
new file mode 100644 (file)
index 0000000..6a7bfc2
--- /dev/null
@@ -0,0 +1,62 @@
+namespace hiberlite
+{
+
+       template<class C>
+       rb_pair<C>::~rb_pair()
+       {
+               Registry<C>::notifyRBDies(this);
+       }
+
+       template<class C>
+       rb_pair<C>::rb_pair(real_bean<C> *rbean) : shared_cnt_obj_pair< real_bean<C> >(rbean)
+       {
+       }
+
+       template<class C>
+       bean_key rb_pair<C>::get_key()
+       {
+               return shared_cnt_obj_pair< real_bean<C> >::res->get_key();
+       }
+
+       template<class C>
+       bean_ptr<C> Registry<C>::createBeanPtr(bean_key key, C *obj)
+       {
+               if (key.id == Database::NULL_ID)
+                       return bean_ptr<C>(key, NULL);
+
+               real_bean<C> *rb = new real_bean<C>(key, obj);
+               rb_pair<C> *para = new rb_pair<C>(rb);
+
+               if (rbpairs.find(key) != rbpairs.end())
+                       throw std::logic_error("bean already exists");
+
+               rbpairs[key] = para;
+
+               bean_ptr<C> ans(key, para);
+               return ans;
+       }
+
+       template<class C>
+       bean_ptr<C> Registry<C>::get(const bean_key key)
+       {
+               typename std::map<bean_key, rb_pair<C>* >::iterator it;
+               it = rbpairs.find(key);
+               if (it == rbpairs.end())
+                       return createBeanPtr(key, NULL);
+               else
+                       return bean_ptr<C>(key, it->second);
+       }
+
+       template<class C>
+       bool Registry<C>::has(const bean_key key)
+       {
+               return rbpairs.find(key) != rbpairs.end();
+       }
+
+       template<class C>
+       void Registry<C>::notifyRBDies(rb_pair<C> *r)
+       {
+               rbpairs.erase(r->get_key());
+       }
+
+} // namespace hiberlite
diff --git a/src/hiberlite/include/SQLiteStmt.h b/src/hiberlite/include/SQLiteStmt.h
new file mode 100644 (file)
index 0000000..e6719c5
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef SQLITESTMT_H
+#define SQLITESTMT_H
+
+namespace hiberlite
+{
+
+       class statement_ptr
+       {
+       public:
+               inline statement_ptr(sqlite3_stmt *st) : obj(st) {}
+               inline ~statement_ptr()
+               {
+                       sqlite3_finalize(obj);
+               }
+
+               sqlite3_stmt *get_stmt()
+               {
+                       return obj;
+               }
+       private:
+               sqlite3_stmt *obj;
+
+               inline statement_ptr(const statement_ptr &st);
+               inline statement_ptr &operator=(const statement_ptr &st);
+       };
+
+       typedef shared_res<statement_ptr> shared_stmt;
+
+       class SQLiteSelect
+       {
+       public:
+               SQLiteSelect(shared_connection con, std::string query);
+
+               bool step();
+
+               virtual ~SQLiteSelect();
+
+               const void *get_blob(int iCol);
+               int get_bytes(int iCol);
+               double get_double(int iCol);
+               int get_int(int iCol);
+               sqlid_t get_int64(int iCol);
+               const unsigned char *get_text(int iCol);
+               int get_type(int iCol);
+               int column_count();
+               std::string get_name(int N);
+
+       protected:
+               bool active;
+               shared_stmt statement;
+               shared_connection con;
+       private:
+       };
+
+} //namespace hiberlite
+
+#endif // SQLITESTMT_H
diff --git a/src/hiberlite/include/UpdateVisitor_tmpl.hpp b/src/hiberlite/include/UpdateVisitor_tmpl.hpp
new file mode 100644 (file)
index 0000000..c3e67b1
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef INSERVISITOR_TMPL_HPP_INCLUDED
+#define INSERVISITOR_TMPL_HPP_INCLUDED
+
+namespace hiberlite
+{
+
+} //namespace hiberlite
+
+
+#endif // INSERVISITOR_TMPL_HPP_INCLUDED
diff --git a/src/hiberlite/include/Visitor.h b/src/hiberlite/include/Visitor.h
new file mode 100644 (file)
index 0000000..594dbd0
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef VISITOR_H
+#define VISITOR_H
+
+#include <stack>
+
+namespace hiberlite
+{
+
+       class access
+       {
+       public:
+               template<class A, class C>
+               static void hibernate(A &a, C &c)
+               {
+                       c.hibernate(a);
+               }
+
+               template<class A, class C>
+               static void construct(A & /*a*/, C **c)
+               {
+                       *c = new C();
+               }
+
+               template<class A, class C>
+               static void destroy(A & /*a*/, C *c)
+               {
+                       delete c;
+               }
+       };
+
+       template<class A, class C>
+       void hibernate(A &a, C &c, const long unsigned int bogus)
+       {
+               access::hibernate(a, c);
+       }
+
+       template<class A, class C>
+       void construct(A &a, C **c, const long unsigned int bogus)
+       {
+               access::construct(a, c);
+       }
+
+       template<class A, class C>
+       void destroy(A &a, C *c, const long unsigned int bogus)
+       {
+               access::destroy(a, c);
+       }
+
+       /*
+       class Actor{
+               public:
+                       template<class Vis, class E, class Stream>
+                       void act(Vis* vis, collection_nvp<C,Stream> nvp);
+
+                       template<class Vis, class C>
+                       void act(Vis* vis, db_atom<C> atom);
+
+                       template<class AV>
+                       void notifyInitWalk(AV& av);
+
+                       template<class AV>
+                       void notifyDoneWalk(AV& av);
+       };
+       */
+
+       template<class C>
+       class AVisitor
+       {
+       public:
+               bool is_loading();
+               bool is_saving();
+               bool is_model();
+               bool is_deleting();
+
+               AVisitor(C *_actor, int _purp);
+               ~AVisitor();
+               shared_connection getConnection();
+               sqlid_t getRootId();
+               inline Scope getScope()
+               {
+                       return scope;
+               }
+
+               template<class Y>
+               void startWalk(Y &obj, bean_key _k);
+
+               template<class Y>
+               void walk(Y &obj);
+
+               template<class X>
+               AVisitor<C> &operator&(sql_nvp<X> nvp);
+
+               template<class E, class S>
+               AVisitor<C> &operator&(collection_nvp<E, S> nvp);
+
+               template<class X>
+               AVisitor<C> &operator&(db_atom<X> atom);
+
+               void divePrefix(std::string name);
+
+               void diveTable(std::string name);
+
+               void pop();
+
+               static const int LOADING        = 1;
+               static const int SAVING         = 2;
+               static const int MODEL          = 3;
+               static const int DELETING       = 4;
+       protected:
+               C *actor;
+               int purpose;
+
+               void popScope();
+               void pushAndSubTable(std::string name);
+               void pushAndSubPrefix(std::string prefix);
+
+               std::stack<Scope> stack;
+               Scope scope;
+
+               bean_key rootKey;
+       };
+
+       class DropChildren;
+       class UpdateBean;
+       class BeanUpdater;
+
+       class ExtractModel;
+       class ModelExtractor;
+
+} //namespace hiberlite
+
+#endif // VISITOR_H
diff --git a/src/hiberlite/include/Visitor_tmpl_impl.hpp b/src/hiberlite/include/Visitor_tmpl_impl.hpp
new file mode 100644 (file)
index 0000000..ef0ac29
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef VISITOR_TMPL_IMPL_HPP_INCLUDED
+#define VISITOR_TMPL_IMPL_HPP_INCLUDED
+
+namespace hiberlite
+{
+
+       template<class C>
+       AVisitor<C>::AVisitor(C *_act, int _purp) : actor(_act)
+               , purpose(_purp)
+       {}
+
+       template<class C>
+       bool AVisitor<C>::is_loading()
+       {
+               return purpose == LOADING;
+       }
+
+       template<class C>
+       bool AVisitor<C>::is_saving()
+       {
+               return purpose == SAVING;
+       }
+
+       template<class C>
+       bool AVisitor<C>::is_model()
+       {
+               return purpose == MODEL;
+       }
+
+       template<class C>
+       bool AVisitor<C>::is_deleting()
+       {
+               return purpose == DELETING;
+       }
+
+       template<class C>
+       AVisitor<C>::~AVisitor() {}
+
+       template<class C>
+       shared_connection AVisitor<C>::getConnection()
+       {
+               return rootKey.con;
+       }
+
+       template<class C>
+       sqlid_t AVisitor<C>::getRootId()
+       {
+               return rootKey.id;
+       }
+
+       template<class C> template<class Y>
+       void AVisitor<C>::startWalk(Y &obj, bean_key key)
+       {
+               rootKey = key;
+               stack = std::stack<Scope>();
+               std::string ClassName = Database::getClassName<Y>();
+               scope = Scope(ClassName, "");
+
+               actor->notifyInitWalk(*this);
+               walk(obj);
+               actor->notifyDoneWalk(*this);
+       }
+
+       template<class C> template<class Y>
+       void AVisitor<C>::walk(Y &obj)
+       {
+               hibernate(*this, obj, static_cast<const unsigned int>(0));
+       }
+
+       template<class C> template<class X>
+       AVisitor<C> &AVisitor<C>::operator&(sql_nvp<X> nvp)
+       {
+               divePrefix(nvp.name);
+               walk(nvp.value);
+               pop();
+               return *this;
+       }
+
+       template<class C> template<class X>
+       AVisitor<C> &AVisitor<C>::operator&(db_atom<X> atom)
+       {
+               actor->act(*this, atom);
+               return *this;
+       }
+
+       template<class C> template<class E, class S>
+       AVisitor<C> &AVisitor<C>::operator&(collection_nvp<E, S> nvp)
+       {
+               actor->act(*this, nvp);
+               return *this;
+       }
+
+       template<class Vis>
+       void AVisitor<Vis>::divePrefix(std::string name)
+       {
+               pushAndSubPrefix(name);
+       }
+
+       template<class Vis>
+       void AVisitor<Vis>::diveTable(std::string name)
+       {
+               pushAndSubTable(name);
+       }
+
+       template<class Vis>
+       void AVisitor<Vis>::pop()
+       {
+               popScope();
+       }
+
+       template<class C>
+       void AVisitor<C>::popScope()
+       {
+               if (!stack.size())
+                       throw std::runtime_error("popScope with empty stack");
+               scope = stack.top();
+               stack.pop();
+       }
+
+       template<class C>
+       void AVisitor<C>::pushAndSubTable(std::string name)
+       {
+               stack.push(scope);
+               scope._table = scope.full() + "_" + name;
+               scope._prefix = "";
+               scope.prefix_depth = 0;
+       }
+
+       template<class C>
+       void AVisitor<C>::pushAndSubPrefix(std::string prefix)
+       {
+               stack.push(scope);
+               if (scope.prefix().size())
+                       scope._prefix += "_" + prefix;
+               else
+                       scope._prefix += prefix;
+               scope.prefix_depth++;
+       }
+
+} //namespace hiberlite
+
+#endif // VISITOR_TMPL_IMPL_HPP_INCLUDED
diff --git a/src/hiberlite/include/bean_ptr.h b/src/hiberlite/include/bean_ptr.h
new file mode 100644 (file)
index 0000000..138a923
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef BEAN_PTR_H_INCLUDED
+#define BEAN_PTR_H_INCLUDED
+
+namespace hiberlite
+{
+
+       class Database;
+       class access;
+
+       template<class C>
+       class Registry;
+
+       template<class C>
+       class shared_res;
+
+       template<class C>
+       class real_bean : noncopyable
+       {
+       public:
+               inline C *operator->();
+               inline C *get();
+
+               ~real_bean();
+
+               bean_key get_key() const
+               {
+                       return key;
+               }
+
+               void save();
+
+               void destroy();
+               bool destroyed() const
+               {
+                       return forgotten;
+               }
+
+       protected:
+               inline void loadLazy();
+
+               bean_key key;
+               C *obj;
+               bool forgotten;
+
+       private:
+               friend class Registry<C>;
+               real_bean(const bean_key _key, C *_obj); //only Registry can create the real_bean
+       };
+
+       template<class C>
+       class bean_ptr : public shared_res< real_bean<C> >
+       {
+               friend class hiberlite::access;
+               template<class Archive>
+               void hibernate(Archive &ar);
+
+               friend class Registry<C>;
+               bean_ptr(bean_key k, rb_pair<C> *rbpair);
+
+               sqlid_t tmp_id = {};
+
+       public:
+               bean_ptr(bean_key k);
+
+               bean_ptr();
+
+               explicit operator bool() const;
+
+               bean_ptr(const bean_ptr<C> &other);
+               bean_ptr<C> &operator=(const bean_ptr<C> &other);
+
+               void save();
+               void destroy();
+
+               bool destroyed()
+               {
+                       return shared_res< real_bean<C> >::get_object()->destroyed();
+               }
+
+               inline sqlid_t get_id() const;
+               inline C &operator*();
+               inline C *operator->();
+       };
+
+}//namespace hiberlite
+
+#endif // BEAN_PTR_H_INCLUDED
diff --git a/src/hiberlite/include/bean_ptr_impl.hpp b/src/hiberlite/include/bean_ptr_impl.hpp
new file mode 100644 (file)
index 0000000..4d0c8c5
--- /dev/null
@@ -0,0 +1,147 @@
+namespace hiberlite
+{
+
+       template<class C>
+       real_bean<C>::real_bean(const bean_key _key, C *_obj) : key(_key), obj(_obj), forgotten(false)
+       {}
+
+       template<class C>
+       real_bean<C>::~real_bean()
+       {
+               save();
+               delete obj;
+       }
+
+       template<class C>
+       void real_bean<C>::destroy()
+       {
+               if (forgotten)
+                       return;
+               Database::dbDelete(key, *obj);
+               delete obj;
+               forgotten = true;
+               obj = NULL;
+               key.id = Database::NULL_ID;
+       }
+
+       template<class C>
+       void real_bean<C>::save()
+       {
+               if (forgotten)
+                       return;
+               if (!obj)
+                       return;
+               Database::dbUpdate(key, *obj);
+       }
+
+       template<class C>
+       C *real_bean<C>::operator->()
+       {
+               if (forgotten)
+                       return NULL;
+               loadLazy();
+               if (!obj)
+                       throw std::runtime_error("NULL pointer exception!");
+               return obj;
+       }
+
+       template<class C>
+       C *real_bean<C>::get()
+       {
+               if (forgotten)
+                       return NULL;
+               loadLazy();
+               if (!obj)
+                       throw std::runtime_error("NULL pointer exception!");
+               return obj;
+       }
+
+       template<class C>
+       inline void real_bean<C>::loadLazy()
+       {
+               if (!obj && key.id != Database::NULL_ID)
+                       obj = Database::dbLoad<C>(key);
+       }
+
+       template<class C>
+       bean_ptr<C>::bean_ptr(bean_key k, rb_pair<C> *para)
+       {
+               this->takeRes(para);
+       }
+
+       template<class C>
+       bean_ptr<C>::bean_ptr(const bean_ptr<C> &other) : shared_res< real_bean<C> >(other)
+       {
+       }
+
+       template<class C>
+       bean_ptr<C> &bean_ptr<C>::operator=(const bean_ptr<C> &other)
+       {
+               shared_res< real_bean<C> >::operator=(other);
+               return *this;
+       }
+
+       template<class C>
+       bean_ptr<C>::bean_ptr(bean_key k)
+       {
+               *this = Registry<C>::get(k);
+       }
+
+       template<class C>
+       bean_ptr<C>::bean_ptr()
+       {
+       }
+
+       template<class C>
+       bean_ptr<C>::operator bool() const
+       {
+               return get_id() != Database::NULL_ID;
+       }
+
+       template<class C> template<class Archive>
+       void bean_ptr<C>::hibernate(Archive &ar)
+       {
+               tmp_id = get_id();
+
+               if (tmp_id != Database::NULL_ID
+                               && ar.getConnection() != shared_res< real_bean<C> >::get_object()->get_key().con)
+                       throw std::logic_error("saving the bean from different database");
+
+               ar &hiberlite::sql_nvp< sqlid_t > ("id", tmp_id);
+               if (ar.is_loading())
+                       *this = Registry<C>::get(bean_key(ar.getConnection(), tmp_id));
+       }
+
+       template<class C>
+       C &bean_ptr<C>::operator*()
+       {
+               return *(shared_res< real_bean<C> >::get_object()->get());
+       }
+
+       template<class C>
+       C *bean_ptr<C>::operator->()
+       {
+               return shared_res< real_bean<C> >::get_object()->get();
+       }
+
+       template<class C>
+       void bean_ptr<C>::destroy()
+       {
+               shared_res< real_bean<C> >::get_object()->destroy();
+       }
+
+       template<class C>
+       void bean_ptr<C>::save()
+       {
+               shared_res< real_bean<C> >::get_object()->save();
+       }
+
+       template<class C>
+       sqlid_t bean_ptr<C>::get_id() const
+       {
+               if (!shared_res< real_bean<C> >::get_object())
+                       return Database::NULL_ID;
+               return shared_res< real_bean<C> >::get_object()->get_key().id;
+       }
+
+} //namespace hiberlite
diff --git a/src/hiberlite/include/common.h b/src/hiberlite/include/common.h
new file mode 100644 (file)
index 0000000..b58e6cd
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include <list>
+
+#include <stdexcept>
+#include <iostream>
+#include <algorithm>
+
+#include <sqlite3.h>
+
+namespace hiberlite
+{
+
+       class noncopyable
+       {
+       protected:
+               noncopyable() {}
+               ~noncopyable() {}
+       private:
+               noncopyable(const noncopyable &);
+               const noncopyable operator=(const noncopyable &);
+
+       };
+
+       typedef sqlite_int64 sqlid_t;
+
+} //namespace hiberlite
+
+#define HIBERLITE_HL_DBG_DO(x) ;
+
+
+#endif
diff --git a/src/hiberlite/include/db_error.h b/src/hiberlite/include/db_error.h
new file mode 100644 (file)
index 0000000..c287332
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef DB_ERROR_H_INCLUDED
+#define DB_ERROR_H_INCLUDED
+
+namespace hiberlite
+{
+
+       class database_error : public std::runtime_error
+       {
+       public:
+               inline database_error(const char *msg) : std::runtime_error(msg) {}
+               inline database_error(std::string msg) : std::runtime_error(msg) {}
+               inline static void database_assert(int result, shared_connection con)
+               {
+                       if (result == SQLITE_OK)
+                               return;
+                       throw database_error(sqlite3_errmsg(con->getSQLite3Ptr()));
+               }
+       };
+
+} //namespace hiberlite
+
+#endif // DB_ERROR_H_INCLUDED
diff --git a/src/hiberlite/include/hiberdefs.h b/src/hiberlite/include/hiberdefs.h
new file mode 100644 (file)
index 0000000..3505390
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef HIBERDEFS_H_INCLUDED
+#define HIBERDEFS_H_INCLUDED
+
+#if (defined _MSC_VER && _MSC_VER< 1600)
+#include <boost/typeof/typeof.hpp>
+#define HIBERLITE_NVP(Field) hiberlite::sql_nvp< BOOST_TYPEOF(Field) >(#Field,Field)
+#else
+#define HIBERLITE_NVP(Field) hiberlite::sql_nvp< decltype(Field) >(#Field,Field)
+#endif
+#define HIBERLITE_BASE_CLASS(ClName) hiberlite::sql_nvp< ClName >(#ClName,*((ClName*)this) )
+
+#define HIBERLITE_EXPORT_CLASS(ClName)                         \
+       namespace hiberlite{                                                    \
+               template<>                                                                              \
+               std::string Database::getClassName<ClName>()    \
+               {       std::string temp(#ClName);std::replace(temp.begin(), temp.end(), ':', '_');return temp;}}
+
+//#define HIBERLITE_COLLECTION(Field) hiberlite::collection_nvp<typeof(Field),typeof(Field.begin())>(#Field, Field, Field.begin(), Field.end())
+//#define HIBERLITE_ARRAY(Field,N) hiberlite::collection_nvp<typeof(Field),typeof(Field[0])>(#Field,  *Field, *(Field+N))
+
+#define HIBERLITE_PRIMARY_KEY_COLUMN "hiberlite_id"
+#define HIBERLITE_PARENTID_COLUMN "hiberlite_parent_id"
+#define HIBERLITE_ENTRY_INDEX_COLUMN "hiberlite_entry_indx"
+#define HIBERLITE_ID_STORAGE_CLASS "INTEGER"
+
+#define HIBERLITE_PRIMARY_KEY_STORAGE_TYPE "PRIMARYKEY"
+
+#endif // HIBERDEFS_H_INCLUDED
diff --git a/src/hiberlite/include/hiberlite.h b/src/hiberlite/include/hiberlite.h
new file mode 100644 (file)
index 0000000..fe5fecf
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _HIBERLITE_H_
+#define _HIBERLITE_H_
+
+#include <sqlite3.h>
+
+#include "common.h"
+#include "shared_res.h"
+#include "hiberdefs.h"
+#include "nvp.h"
+
+#include "db_error.h"
+
+#include "SQLiteStmt.h"
+
+#include "CppModel.h"
+
+#include "Registry.h"
+#include "bean_ptr.h"
+
+#include "Visitor.h"
+#include "ModelExtractor.h"
+#include "BeanUpdater.h"
+#include "ChildKiller.h"
+#include "BeanLoader.h"
+
+#include "Database.h"
+
+
+#include "Registry_impl.hpp"
+#include "bean_ptr_impl.hpp"
+#include "Database_tmpl_impl.hpp"
+
+#include "Visitor_tmpl_impl.hpp"
+#include "ModelExtractor_impl.hpp"
+#include "BeanUpdater_impl.hpp"
+#include "ChildKiller_impl.hpp"
+#include "BeanLoader_impl.hpp"
+
+#include "some_types.h"
+
+#endif //_HIBERLITE_H_
diff --git a/src/hiberlite/include/nvp.h b/src/hiberlite/include/nvp.h
new file mode 100644 (file)
index 0000000..47d4f44
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef _NVP_H_
+#define _NVP_H_
+
+#include "common.h"
+
+namespace hiberlite
+{
+
+       template<class C>
+       class sql_nvp
+       {
+       public:
+               std::string name;
+               C &value;
+               std::string search_key;
+
+               sql_nvp(std::string _name, C &_value, std::string search = "") : name(_name), value(_value), search_key(search) {}
+       };
+
+       template<class E, class Stream>
+       class collection_nvp
+       {
+       public:
+               std::string name;
+               Stream stream;
+               collection_nvp(std::string _name, Stream _s) : name(_name), stream(_s) {}
+       };
+
+       class abstract_atom
+       {
+       public:
+               virtual void bindValue(sqlite3_stmt *stmt, int col) = 0;
+               inline virtual ~abstract_atom() {}
+       };
+
+       template<class C>
+       class db_atom : public abstract_atom
+       {
+       public:
+               C &val;
+               db_atom(C &x) : val(x) {}
+               inline virtual ~db_atom() {}
+
+               inline std::string sqliteStorageClass();
+
+               template<class Stmt, class Arg>
+               void loadValue(Stmt &res, Arg &arg);
+
+               inline virtual void bindValue(sqlite3_stmt *stmt, int col);
+       };
+
+} //namespace hiberlite
+
+#endif
diff --git a/src/hiberlite/include/shared_res.h b/src/hiberlite/include/shared_res.h
new file mode 100644 (file)
index 0000000..07d2f35
--- /dev/null
@@ -0,0 +1,177 @@
+
+namespace hiberlite
+{
+
+       template<class C>
+       class shared_res;
+
+       template<class C>
+       class shared_cnt_obj_pair : noncopyable
+       {
+       protected:
+               friend class shared_res<C>;
+
+               C *res;
+               int refCount;
+
+               explicit inline shared_cnt_obj_pair(C *r) : res(r), refCount(0) {}
+
+       public:
+
+               auto getRes()
+               {
+                       return res;
+               }
+               auto getRes() const
+               {
+                       return res;
+               }
+               virtual ~shared_cnt_obj_pair()
+               {
+                       if (refCount)
+                               // throw std::logic_error("resource is busy");
+                               --refCount;
+                       else
+                               delete res;
+               }
+               int getRefCount()
+               {
+                       return refCount;
+               }
+               void inc_pair_users()
+               {
+                       refCount++;
+               }
+               void dec_pair_users()
+               {
+                       refCount--;
+               }
+       };
+
+       template<class C>
+       class shared_res
+       {
+       protected:
+               shared_cnt_obj_pair<C> *res;
+
+               inline void freeRes()
+               {
+                       if (!res)
+                               return;
+                       res->dec_pair_users();
+                       if (res->getRefCount() == 0)
+                               delete res;
+               }
+               inline void takeRes(shared_cnt_obj_pair<C> *r)
+               {
+                       res = r;
+                       if (!res)
+                               return;
+                       res->inc_pair_users();
+               }
+
+       public:
+               inline explicit shared_res(C *tg) : res(NULL)
+               {
+                       if (!tg)
+                               throw std::logic_error("no reason to manage NULL object");
+                       shared_cnt_obj_pair<C> *share = new shared_cnt_obj_pair<C>(tg);
+                       takeRes(share);
+               }
+
+               inline shared_res() : res(NULL) {}
+
+               inline shared_res(const shared_res<C> &x) : res(NULL)
+               {
+                       takeRes(x.res);
+               }
+
+               inline virtual ~shared_res()
+               {
+                       freeRes();
+               }
+
+               inline shared_res<C> &operator=(const shared_res<C> &x)
+               {
+                       if (x.res != res) {
+                               freeRes();
+                               takeRes(x.res);
+                       }
+                       return *this;
+               }
+
+               inline auto get_object()
+               {
+                       return res ? res->getRes() : NULL;
+               }
+
+               inline auto get_object() const
+               {
+                       return res ? res->getRes() : NULL;
+               }
+
+               inline C *operator->()
+               {
+                       return get_object();
+               }
+
+               inline int get_ref_count()
+               {
+                       if (!res)
+                               return 0;
+                       return res->getRefCount();
+               }
+
+               inline bool operator==(const shared_res<C> &x) const
+               {
+                       return x.res == res;
+               }
+               inline bool operator<(const shared_res<C> &x) const
+               {
+                       return res < x.res;
+               }
+               inline operator bool() const
+               {
+                       return res != NULL;
+               }
+       };
+
+       class autoclosed_con
+       {
+       protected:
+               sqlite3 *con;
+
+       public:
+               inline autoclosed_con(sqlite3 *_con) : con(_con) {}
+               inline ~autoclosed_con()
+               {
+                       if (con)
+                               sqlite3_close(con);
+               }
+
+               inline sqlite3 *getSQLite3Ptr()
+               {
+                       return con;
+               }
+       };
+
+       typedef shared_res<autoclosed_con> shared_connection;
+
+       class bean_key
+       {
+       public:
+               sqlid_t id;
+               shared_connection con;
+
+               bean_key(sqlid_t _id, shared_connection _con) : id(_id), con(_con) {}
+               bean_key(shared_connection _con, sqlid_t _id) : id(_id), con(_con) {}
+               ~bean_key() {}
+               bean_key();
+
+               bool operator<(const bean_key &k) const
+               {
+                       return (id < k.id) || ((id == k.id) && (con < k.con));
+               }
+       };
+
+} //namespace hiberlite
diff --git a/src/hiberlite/include/some_types.h b/src/hiberlite/include/some_types.h
new file mode 100644 (file)
index 0000000..e475c28
--- /dev/null
@@ -0,0 +1,203 @@
+#ifndef SOM_TYPES_H_INCLUDED
+#define SOM_TYPES_H_INCLUDED
+
+namespace hiberlite
+{
+
+       template<class E, class C>
+       class stl_stream_adapter
+       {
+               C &ct;
+               typename C::iterator it;
+               E xx;
+       public:
+               void startLoadFromDb()
+               {
+                       ct.clear();
+                       it = ct.begin();
+               }
+               stl_stream_adapter(C &_ct) : ct(_ct)
+               {
+                       it = ct.begin();
+               }
+               void putNext(E &el)
+               {
+                       ct.insert(ct.end(), el);
+                       it = ct.end();
+               }
+               E &getNext()
+               {
+                       xx = *it++;
+                       return xx;
+               }
+               bool done()
+               {
+                       return it == ct.end();
+               }
+       };
+
+       template<class A, class E>
+       void hibernate(A &ar, std::vector<E> &v, const unsigned int)
+       {
+               collection_nvp<E, stl_stream_adapter<E, std::vector<E> > > body("items", stl_stream_adapter<E, std::vector<E> >(v));
+               ar &body;
+       }
+
+       template<class A, class First, class Second>
+       void hibernate(A &ar, std::pair<First, Second> &m, const unsigned int)
+       {
+               sql_nvp<First> f("first", m.first);
+               sql_nvp<Second> s("second", m.second);
+               ar &f;
+               ar &s;
+       }
+
+       template<class A, class Key>
+       void hibernate(A &ar, std::set<Key> &m, const unsigned int)
+       {
+               typedef Key ElType;
+               collection_nvp<ElType, stl_stream_adapter<ElType, std::set<Key> > >
+               body("items", stl_stream_adapter<ElType, std::set<Key> >(m));
+               ar &body;
+       }
+
+       template<class A, class Key>
+       void hibernate(A &ar, std::list<Key> &m, const unsigned int)
+       {
+               typedef Key ElType;
+               collection_nvp<ElType, stl_stream_adapter<ElType, std::list<Key> > >
+               body("items", stl_stream_adapter<ElType, std::list<Key> >(m));
+               ar &body;
+       }
+
+       template<class K, class D>
+       class stl_map_adapter
+       {
+               typedef std::pair<const K, D> RType;
+               typedef std::pair<K, D> WType;
+               typedef std::map<K, D> C;
+               C &ct;
+               typename C::iterator it;
+
+               WType xx;
+       public:
+               void startLoadFromDb()
+               {
+                       ct.clear();
+                       it = ct.begin();
+               }
+               stl_map_adapter(C &_ct) : ct(_ct)
+               {
+                       it = ct.begin();
+               }
+               void putNext(WType &el)
+               {
+                       ct.insert(el);
+                       it = ct.end();
+               }
+               WType &getNext()
+               {
+                       xx = *it++;
+                       return xx;
+               }
+               bool done()
+               {
+                       return it == ct.end();
+               }
+       };
+       template<class A, class Key, class Data>
+       void hibernate(A &ar, std::map<Key, Data> &m, const unsigned int)
+       {
+               typedef std::pair<Key, Data> ElType;
+               collection_nvp<ElType, stl_map_adapter<Key, Data> >
+               body("items", stl_map_adapter<Key, Data>(m));
+               ar &body;
+       }
+
+#define HIBERLITE_DEF_DB_ATOM(T, GetFromDB, PutToDB, StorClass) \
+       template<class A> void hibernate(A& ar, T& value, const unsigned int)   \
+       {       ar & db_atom<T>(value); }                                                                               \
+       template<> inline std::string db_atom<T>::sqliteStorageClass()                                  \
+       {       return StorClass;       }                                                                                       \
+       template<> template<class Stmt,class Arg> void db_atom<T>::loadValue(Stmt& res, Arg& arg)               \
+       {       val=res.GetFromDB(arg); }                                                                               \
+       template<> inline void db_atom<T>::bindValue(sqlite3_stmt* stmt, int col)               \
+       {       PutToDB(stmt,col,val);  }
+
+#define HIBERLITE_DEF_INT_ATOM(T) HIBERLITE_DEF_DB_ATOM(T, get_int, sqlite3_bind_int, "INTEGER")
+
+       HIBERLITE_DEF_INT_ATOM(int)
+       HIBERLITE_DEF_INT_ATOM(unsigned int)
+       HIBERLITE_DEF_INT_ATOM(char)
+       HIBERLITE_DEF_INT_ATOM(unsigned char)
+       HIBERLITE_DEF_INT_ATOM(short)
+       HIBERLITE_DEF_INT_ATOM(unsigned short)
+
+       HIBERLITE_DEF_DB_ATOM(long long, get_int64, sqlite3_bind_int64, "INTEGER")
+
+       HIBERLITE_DEF_DB_ATOM(long int, get_int64, sqlite3_bind_int64, "INTEGER")
+       HIBERLITE_DEF_DB_ATOM(unsigned long int, get_int64, sqlite3_bind_int64, "INTEGER")
+       HIBERLITE_DEF_DB_ATOM(unsigned long long, get_int64, sqlite3_bind_int64, "INTEGER")
+
+       HIBERLITE_DEF_DB_ATOM(float, get_double, sqlite3_bind_double, "REAL")
+       HIBERLITE_DEF_DB_ATOM(double, get_double, sqlite3_bind_double, "REAL")
+
+#undef HIBERLITE_DEF_INT_ATOM
+#undef HIBERLITE_DEF_DB_ATOM
+
+// std::string -> TEXT type
+
+       template<class A>
+       void hibernate(A &ar, std::string &value, const unsigned int)
+       {
+               ar &db_atom<std::string>(value);
+       }
+
+       template<> template<class Stmt, class Arg>
+       void db_atom<std::string>::loadValue(Stmt &res, Arg &arg)
+       {
+               val = std::string((const char *)(res.get_text(arg)));
+       }
+
+       template<>
+       inline std::string db_atom<std::string>::sqliteStorageClass()
+       {
+               return "TEXT";
+       }
+
+       template<>
+       inline void db_atom<std::string>::bindValue(sqlite3_stmt *stmt, int col)
+       {
+               sqlite3_bind_text(stmt, col, val.c_str(), -1, SQLITE_TRANSIENT);
+       }
+
+// std::vector<uint8_t> -> BLOB type
+
+       template<class A>
+       void hibernate(A &ar, std::vector<uint8_t> &value, const unsigned int)
+       {
+               ar &db_atom<std::vector<uint8_t>>(value);
+       }
+
+       template<> template<class Stmt, class Arg>
+       void db_atom<std::vector<uint8_t>>::loadValue(Stmt &res, Arg &arg)
+       {
+               const uint8_t *tmp = static_cast<const uint8_t *>(res.get_blob(arg));
+               val.assign(tmp, tmp + res.get_bytes(arg));
+       }
+
+       template<>
+       inline std::string db_atom<std::vector<uint8_t>>::sqliteStorageClass()
+       {
+               return "BLOB";
+       }
+
+       template<>
+       inline void db_atom<std::vector<uint8_t>>::bindValue(sqlite3_stmt *stmt, int col)
+       {
+               sqlite3_bind_blob(stmt, col, val.data(), val.size(), SQLITE_TRANSIENT);
+       }
+
+} //namespace hiberlite
+
+#endif // SOM_TYPES_H_INCLUDED
diff --git a/src/hiberlite/src/BeanLoader.cpp b/src/hiberlite/src/BeanLoader.cpp
new file mode 100644 (file)
index 0000000..6d5147e
--- /dev/null
@@ -0,0 +1,9 @@
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+       BeanLoader::BeanLoader() : AVisitor<LoadBean>(&actor, LOADING)
+       {}
+
+} //namespace hiberlite
diff --git a/src/hiberlite/src/BeanUpdater.cpp b/src/hiberlite/src/BeanUpdater.cpp
new file mode 100644 (file)
index 0000000..8772342
--- /dev/null
@@ -0,0 +1,77 @@
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+       RowScope::~RowScope()
+       {
+               for (size_t i = 0; i < atoms.size(); i++)
+                       delete atoms[i];
+       }
+
+       void RowScope::addSimpleAssign(const std::string name, std::string value)
+       {
+               if (needComma)
+                       query += ", ";
+               needComma = true;
+               query += name + "=" + value;
+       }
+
+       RowScope *UpdateBean::curRow()
+       {
+               return rowStack.top().get_object();
+       }
+
+       void UpdateBean::startRow(std::string table, sqlid_t rowid, sqlid_t parent_id, sqlid_t index)
+       {
+               shared_res<RowScope> rs(new RowScope);
+               rowStack.push(rs);
+               curRow()->query = "UPDATE " + table + " SET ";
+               curRow()->id = rowid;
+               curRow()->needComma = false;
+               if (parent_id != Database::NULL_ID) {
+                       curRow()->addSimpleAssign(HIBERLITE_PARENTID_COLUMN, Transformer::toSQLiteValue(parent_id));
+                       curRow()->addSimpleAssign(HIBERLITE_ENTRY_INDEX_COLUMN, Transformer::toSQLiteValue(index));
+               }
+       }
+
+       void UpdateBean::commitRow(shared_connection con, sqlid_t rowid)
+       {
+               if (!curRow()->needComma) {
+                       rowStack.pop();
+                       return;
+               }
+               if (rowid != curRow()->id)
+                       throw std::runtime_error("rowid mismatch");
+               curRow()->query += std::string(" WHERE ") + HIBERLITE_PRIMARY_KEY_COLUMN + "=" + Transformer::toSQLiteValue(rowid) + ";";
+
+               sqlite3_stmt *stmt_ptr = NULL;
+               {
+                       sqlite3 *db = con->getSQLite3Ptr();
+                       const char *foob;
+                       int rc = sqlite3_prepare_v2(db, curRow()->query.c_str(), -1, &stmt_ptr, &foob);
+                       database_error::database_assert(rc, con);
+               }
+               shared_stmt statement(new statement_ptr(stmt_ptr));
+
+               for (size_t i = 0; i < curRow()->atoms.size(); i++) {
+                       curRow()->atoms[i]->bindValue(statement->get_stmt(), static_cast<int>(i) + RowScope::FirstAtom);
+               }
+
+               {
+                       int rc = sqlite3_step(statement->get_stmt());
+                       if (rc != SQLITE_DONE)
+                               database_error::database_assert(rc, con);
+               }
+
+
+               if (!rowStack.size())
+                       throw std::logic_error("UpdateVisitor: commit row, but no row started");
+
+               rowStack.pop();
+       }
+
+       BeanUpdater::BeanUpdater() : AVisitor<UpdateBean>(&actor, SAVING)
+       {}
+
+} //namespace hiberlite
diff --git a/src/hiberlite/src/ChildKiller.cpp b/src/hiberlite/src/ChildKiller.cpp
new file mode 100644 (file)
index 0000000..596b4c3
--- /dev/null
@@ -0,0 +1,9 @@
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+       ChildKiller::ChildKiller() : AVisitor<KillChildren>(&actor, DELETING)
+       {}
+
+} //namespace hiberlite
diff --git a/src/hiberlite/src/CppModel.cpp b/src/hiberlite/src/CppModel.cpp
new file mode 100644 (file)
index 0000000..b1bacf6
--- /dev/null
@@ -0,0 +1,46 @@
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+       void Model::add(Table t)
+       {
+               if (find(t.name) != end())
+                       throw std::logic_error("table [" + t.name + "] already exists");
+               HIBERLITE_HL_DBG_DO(std::cout << "model add table " << t.name << std::endl;)
+               insert(std::pair<std::string, Table>(t.name, t));
+       }
+
+       Table::Table()
+       {
+               add(Column(HIBERLITE_PRIMARY_KEY_COLUMN, HIBERLITE_PRIMARY_KEY_STORAGE_TYPE));
+       }
+
+       void Table::add(Column c)
+       {
+               HIBERLITE_HL_DBG_DO(std::cout << "table " << name << " add column " << c.name << " : " << c.storage_type << std::endl;)
+               columns[c.name] = c;
+       }
+
+       bool Table::contains(std::string colname)
+       {
+               return columns.find(colname) != columns.end();
+       }
+
+       std::string Scope::name_column(std::string name)
+       {
+               if (prefix().size())
+                       return prefix() + "_" + name;
+               else
+                       return name;
+       }
+
+       std::string Scope::full()
+       {
+               if (prefix().size())
+                       return table() + "_" + prefix();
+               else
+                       return table();
+       }
+
+} //namespace hiberlite
diff --git a/src/hiberlite/src/Database.cpp b/src/hiberlite/src/Database.cpp
new file mode 100644 (file)
index 0000000..7561edb
--- /dev/null
@@ -0,0 +1,160 @@
+
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+       Database::Database() : mx(NULL)
+       {
+       }
+
+       Database::Database(std::string fname) : mx(NULL)
+       {
+               open(fname);
+       }
+
+       Database::~Database()
+       {
+               close();
+       }
+
+       void Database::open(std::string fname)
+       {
+               sqlite3 *db = NULL;
+
+               try {
+                       //TODO UTF-8 string
+                       int rc = sqlite3_open(fname.c_str(), &db);
+                       if (rc != SQLITE_OK)
+                               throw database_error(std::string("database error: ") + sqlite3_errmsg(db));
+                       con = shared_connection(new autoclosed_con(db));
+
+               } catch (std::runtime_error e) {
+                       if (db)
+                               sqlite3_close(db);
+                       throw e;
+               }
+       }
+
+       void Database::close()
+       {
+               if (mx) {
+                       delete mx;
+                       mx = NULL;
+               }
+       }
+
+       std::vector<std::string> Database::checkModel()
+       {
+               //TODO checkModel
+               std::vector<std::string> ans;
+               return ans;
+       }
+
+       void Database::dropModel()
+       {
+               if (!mx)
+                       throw std::logic_error("register bean classes first");
+               Model mdl = mx->getModel();
+               for (Model::iterator it = mdl.begin(); it != mdl.end(); it++) {
+                       Table &t = it->second;
+                       std::string query = "DROP TABLE IF EXISTS " + t.name + ";";
+                       dbExecQuery(query);
+               }
+       }
+
+       void Database::createModel()
+       {
+               if (!mx)
+                       throw std::logic_error("register bean classes first");
+               Model mdl = mx->getModel();
+               for (Model::iterator it = mdl.begin(); it != mdl.end(); it++) {
+                       Table &t = it->second;
+                       std::string query = "CREATE TABLE " + t.name + " (";
+                       bool needComma = false;
+                       for (std::map<std::string, Column>::iterator c = t.columns.begin(); c != t.columns.end(); c++) {
+                               if (needComma)
+                                       query += ", ";
+                               needComma = true;
+                               Column &col = c->second;
+                               query += col.name + " ";
+                               if (col.name == HIBERLITE_PRIMARY_KEY_COLUMN)
+                                       query += "INTEGER PRIMARY KEY AUTOINCREMENT";
+                               else
+                                       query += col.storage_type;
+                       }
+                       query += ");";
+                       dbExecQuery(query);
+               }
+       }
+
+       sqlid_t Database::allocId(shared_connection c, std::string table)
+       {
+               //THREAD critical call
+               char *err_msg = NULL;
+               std::string query = "INSERT INTO " + table + " (" + HIBERLITE_PRIMARY_KEY_COLUMN + ") VALUES (NULL);";
+               HIBERLITE_HL_DBG_DO(std::cout << "exec: " << query << std::endl;)
+               int rc = sqlite3_exec(c->getSQLite3Ptr(), query.c_str(), NULL, NULL, &err_msg);
+               if (err_msg)
+                       throw database_error(err_msg);
+               database_error::database_assert(rc, c);
+
+               return sqlite3_last_insert_rowid(c->getSQLite3Ptr());
+       }
+
+       void Database::dbExecQuery(shared_connection con, std::string query)
+       {
+               char *err_msg = NULL;
+               HIBERLITE_HL_DBG_DO(std::cout << "exec: " << query << std::endl;)
+               int rc = sqlite3_exec(con->getSQLite3Ptr(), query.c_str(), NULL, NULL, &err_msg);
+               if (err_msg) {
+                       std::string msg = err_msg;
+                       sqlite3_free(err_msg);
+                       throw database_error(msg);
+               }
+               database_error::database_assert(rc, con);
+       }
+
+       sqlid_t Database::allocId(std::string table)
+       {
+               return allocId(con, table);
+       }
+
+       void Database::dbExecQuery(std::string query)
+       {
+               return dbExecQuery(con, query);
+       }
+
+       std::vector<sqlid_t> Database::dbSelectIds(shared_connection con, const std::string table, const std::string condition, const std::string orderBy)
+       {
+               std::string where;
+               if (condition.size())
+                       where = " WHERE " + condition;
+               std::string order;
+               if (orderBy.size())
+                       order = " ORDER BY " + orderBy;
+               std::string query = "SELECT " + std::string(HIBERLITE_PRIMARY_KEY_COLUMN)
+                                                       + " FROM " + table
+                                                       + where
+                                                       + order
+                                                       + ";";
+               SQLiteSelect sel(con, query);
+               std::vector<sqlid_t> ans;
+               while (sel.step())
+                       ans.push_back(sel.get_int64(0));
+               return ans;
+       }
+
+       std::vector<sqlid_t> Database::dbSelectChildIds(shared_connection con, std::string table, sqlid_t parent)
+       {
+               return dbSelectIds(con, table, std::string(HIBERLITE_PARENTID_COLUMN) + "=" + Transformer::toSQLiteValue(parent)
+                                                  , HIBERLITE_ENTRY_INDEX_COLUMN);
+       }
+
+       std::vector<sqlid_t> Database::dbSelectChildIds(std::string table, sqlid_t parent)
+       {
+               return dbSelectChildIds(con, table, parent);
+       }
+
+
+} //namespace hiberlite;
diff --git a/src/hiberlite/src/ModelExtractor.cpp b/src/hiberlite/src/ModelExtractor.cpp
new file mode 100644 (file)
index 0000000..5763d90
--- /dev/null
@@ -0,0 +1,19 @@
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+       ModelExtractor::ModelExtractor() : AVisitor<ExtractModel>(&actor, MODEL)
+       {}
+
+       Model ExtractModel::getModel()
+       {
+               return model;
+       }
+
+       Model ModelExtractor::getModel()
+       {
+               return actor.getModel();
+       }
+
+} //namespace hiberlite
diff --git a/src/hiberlite/src/Registry.cpp b/src/hiberlite/src/Registry.cpp
new file mode 100644 (file)
index 0000000..71ae7a2
--- /dev/null
@@ -0,0 +1,10 @@
+
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+//template<class C>
+//std::map< bean_key, bean_ptr<C> > Registry<C>::beans=std::map< bean_key, bean_ptr<C> >();
+
+} //namespace hiberlite
diff --git a/src/hiberlite/src/SQLiteStmt.cpp b/src/hiberlite/src/SQLiteStmt.cpp
new file mode 100644 (file)
index 0000000..3a3cdd8
--- /dev/null
@@ -0,0 +1,101 @@
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+       SQLiteSelect::SQLiteSelect(shared_connection _con, std::string query) : con(_con)
+       {
+               HIBERLITE_HL_DBG_DO(std::cout << "query: " << query << std::endl;)
+               active = false;
+               sqlite3_stmt *stmt_ptr = NULL;
+               sqlite3 *db = con->getSQLite3Ptr();
+               const char *foob;
+               int rc = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt_ptr, &foob);
+               database_error::database_assert(rc, con);
+               statement = shared_stmt(new statement_ptr(stmt_ptr));
+       }
+
+       SQLiteSelect::~SQLiteSelect()
+       {
+       }
+
+       bool SQLiteSelect::step()
+       {
+               int rc = sqlite3_step(statement->get_stmt());
+               if (rc == SQLITE_DONE)
+                       return false;
+               if (rc == SQLITE_ROW) {
+                       active = true;
+                       return true;
+               }
+               database_error::database_assert(rc, con);
+               throw database_error("really strange - sqlite3_step returns SQLITE_OK");
+       }
+
+       const void *SQLiteSelect::get_blob(int iCol)
+       {
+               if (!active)
+                       throw std::runtime_error("step() was not called before column access");
+               return sqlite3_column_blob(statement->get_stmt(), iCol);
+       }
+
+       int SQLiteSelect::get_bytes(int iCol)
+       {
+               if (!active)
+                       throw std::runtime_error("step() was not called before column access");
+               return sqlite3_column_bytes(statement->get_stmt(), iCol);
+       }
+
+       double SQLiteSelect::get_double(int iCol)
+       {
+               if (!active)
+                       throw std::runtime_error("step() was not called before column access");
+               return sqlite3_column_double(statement->get_stmt(), iCol);
+       }
+
+       int SQLiteSelect::get_int(int iCol)
+       {
+               if (!active)
+                       throw std::runtime_error("step() was not called before column access");
+               return sqlite3_column_int(statement->get_stmt(), iCol);
+       }
+
+       sqlid_t SQLiteSelect::get_int64(int iCol)
+       {
+               if (!active)
+                       throw std::runtime_error("step() was not called before column access");
+               return sqlite3_column_int64(statement->get_stmt(), iCol);
+       }
+
+       const unsigned char *SQLiteSelect::get_text(int iCol)
+       {
+               if (!active)
+                       throw std::runtime_error("step() was not called before column access");
+               return sqlite3_column_text(statement->get_stmt(), iCol);
+       }
+
+       int SQLiteSelect::get_type(int iCol)
+       {
+               if (!active)
+                       throw std::runtime_error("step() was not called before column access");
+               return sqlite3_column_type(statement->get_stmt(), iCol);
+       }
+
+       std::string SQLiteSelect::get_name(int N)
+       {
+               if (!active)
+                       throw std::runtime_error("step() was not called before column access");
+               return sqlite3_column_name(statement->get_stmt(), N);
+       }
+
+       int SQLiteSelect::column_count()
+       {
+               if (!active)
+                       throw std::runtime_error("step() was not called before column access");
+               return sqlite3_column_count(statement->get_stmt());
+       }
+
+
+}
+
+//namespace hiberlite
diff --git a/src/hiberlite/src/Visitor.cpp b/src/hiberlite/src/Visitor.cpp
new file mode 100644 (file)
index 0000000..5baa1fe
--- /dev/null
@@ -0,0 +1,6 @@
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+} //namespace hiberlite
diff --git a/src/hiberlite/src/shared_res.cpp b/src/hiberlite/src/shared_res.cpp
new file mode 100644 (file)
index 0000000..c3c3ccb
--- /dev/null
@@ -0,0 +1,12 @@
+
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+       bean_key::bean_key()
+       {
+               id = Database::NULL_ID;
+       }
+
+} //namespace hiberlite
index 946f04d..c6fb0bb 100644 (file)
@@ -21,7 +21,6 @@
 #include "DBusInterface.hpp"
 #include "ScreenScannerManager.hpp"
 #include "ScreenSwitchProvider.hpp"
-#include "SQLiteConfiguration.hpp"
 #include "SwitchConfigurationItem.hpp"
 #include "SwitchManager.hpp"
 #include "UniversalSwitch.hpp"
index 9e9f7bd..32163ce 100644 (file)
@@ -1,5 +1,5 @@
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/)
-INCLUDE_DIRECTORIES(${pkgs_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(${pkgs_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/src/hiberlite/include)
 
 INSTALL(PROGRAMS VConf_init.sh DESTINATION ${CMAKE_TESTS_INSTALL_PREFIX}/scripts/)
 INSTALL(FILES org.tizen.universal-switch-tests.xml DESTINATION ${TZ_SYS_RO_PACKAGES})
index 73ea39a..f42ce50 100644 (file)
@@ -59,7 +59,7 @@ TEST_F(ConfigurationTestsFixture, MappingAddedAndRemoved_BeNotUpdatedOnEvent)
 {
        configuration_->add(item_);
        auto switchManager = SwitchManager::create<SwitchManager_ConfigurationTests>(switchProvider_, configuration_, activityFactory_);
-       configuration_->remove(switchId_);
+       configuration_->remove(item_);
        simulateKeyPress(key_);
 
        EXPECT_EQ(switchManager->updatedWithSwitch, 0);
index 61d43a0..d7bb100 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <gtest/gtest.h>
 
-#include "SQLiteConfiguration.hpp"
+#include "HiberliteConfiguration.hpp"
 #include "AccessoriesSwitchProvider.hpp"
 #include "ScreenSwitchProvider.hpp"
 #include "CompositeSwitchProvider.hpp"
@@ -64,9 +64,8 @@ public:
 
        void SetUp()
        {
-               auto SQLiteConfig = std::make_shared<SQLiteConfiguration>(true);
-               SQLiteConfig->clearTable();
-               configuration_ = SQLiteConfig;
+               auto HiberliteConfig = std::make_shared<HiberliteConfiguration>(true);
+               configuration_ = HiberliteConfig;
                switchProvider_ = std::make_shared<CompositeSwitchProvider>();
 
                auto screenSP = std::make_shared<ScreenSwitchProvider>();