-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})
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;
};
#include "DBusInterface.hpp"
-#include "SQLiteConfiguration.hpp"
+#include "Configuration.hpp"
#include "ActivityFactory.hpp"
#include "UniversalSwitch.hpp"
#include "localization.hpp"
}
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>
--- /dev/null
+/*
+ * 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
* 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
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 ||
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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 <<<");
-}
#include <dlog.h>
+HIBERLITE_EXPORT_CLASS(SwitchConfigurationItem)
+
SwitchConfigurationItem::SwitchConfigurationItem(const std::string &switchId, const std::string &activityType)
: switchId(switchId), activityType(activityType)
{}
#include <string>
+#include "hiberlite.h"
#include "UniversalSwitchLog.hpp"
enum ChangeType {
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;
#include "ScreenScannerManager.hpp"
#include "ScreenSwitchProvider.hpp"
#include "SoundFeedback.hpp"
-#include "SQLiteConfiguration.hpp"
+#include "HiberliteConfiguration.hpp"
#include "SwitchConfigurationItem.hpp"
#include "SwitchManager.hpp"
#include "TextToSpeech.hpp"
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);
--- /dev/null
+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.
--- /dev/null
+#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
--- /dev/null
+#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 ⪙
+
+ 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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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 ⪙
+ 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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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 ⪙
+ 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
--- /dev/null
+#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
--- /dev/null
+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
--- /dev/null
+#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
--- /dev/null
+#ifndef INSERVISITOR_TMPL_HPP_INCLUDED
+#define INSERVISITOR_TMPL_HPP_INCLUDED
+
+namespace hiberlite
+{
+
+} //namespace hiberlite
+
+
+#endif // INSERVISITOR_TMPL_HPP_INCLUDED
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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_
--- /dev/null
+#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
--- /dev/null
+
+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
--- /dev/null
+#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
--- /dev/null
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+ BeanLoader::BeanLoader() : AVisitor<LoadBean>(&actor, LOADING)
+ {}
+
+} //namespace hiberlite
--- /dev/null
+#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
--- /dev/null
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+ ChildKiller::ChildKiller() : AVisitor<KillChildren>(&actor, DELETING)
+ {}
+
+} //namespace hiberlite
--- /dev/null
+#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
--- /dev/null
+
+#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;
--- /dev/null
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+ ModelExtractor::ModelExtractor() : AVisitor<ExtractModel>(&actor, MODEL)
+ {}
+
+ Model ExtractModel::getModel()
+ {
+ return model;
+ }
+
+ Model ModelExtractor::getModel()
+ {
+ return actor.getModel();
+ }
+
+} //namespace hiberlite
--- /dev/null
+
+#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
--- /dev/null
+#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
--- /dev/null
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+} //namespace hiberlite
--- /dev/null
+
+#include "hiberlite.h"
+
+namespace hiberlite
+{
+
+ bean_key::bean_key()
+ {
+ id = Database::NULL_ID;
+ }
+
+} //namespace hiberlite
#include "DBusInterface.hpp"
#include "ScreenScannerManager.hpp"
#include "ScreenSwitchProvider.hpp"
-#include "SQLiteConfiguration.hpp"
#include "SwitchConfigurationItem.hpp"
#include "SwitchManager.hpp"
#include "UniversalSwitch.hpp"
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})
{
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);
#include <gtest/gtest.h>
-#include "SQLiteConfiguration.hpp"
+#include "HiberliteConfiguration.hpp"
#include "AccessoriesSwitchProvider.hpp"
#include "ScreenSwitchProvider.hpp"
#include "CompositeSwitchProvider.hpp"
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>();