summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2012-01-26 12:08:39 +0100
committerBent Bisballe Nyeng <deva@aasimon.org>2012-01-26 12:08:39 +0100
commit4edae3f518353bb21a02fcda2dfcff83c5a72fc3 (patch)
tree7902e2b6af1dabdb5c49b906b8592874bfce407d
parente9ff9842e9a8c178f5e17c0cf5dde16db1a0d8fc (diff)
New onCommit scripting system.
-rw-r--r--server/src/Makefile.am6
-rw-r--r--server/src/client_connection.cc19
-rw-r--r--server/src/client_connection.h4
-rw-r--r--server/src/journal.cc24
-rw-r--r--server/src/journal.h16
-rw-r--r--server/src/journal_commit.cc1
-rw-r--r--server/src/journal_uploadserver.cc26
-rw-r--r--server/src/journal_uploadserver.h2
-rw-r--r--server/src/luaoncommit.cc70
-rw-r--r--server/src/luaoncommit.h (renamed from server/src/resumeparser.h)26
-rw-r--r--server/src/luaresume.cc121
-rw-r--r--server/src/luaresume.h18
-rw-r--r--server/src/luascript.cc303
-rw-r--r--server/src/luascript.h92
-rw-r--r--server/src/macroparser.cc35
-rw-r--r--server/src/macroparser.h5
-rw-r--r--server/src/pracrodaopgsql.cc66
-rw-r--r--server/src/resumeparser.cc81
-rw-r--r--server/src/session.cc13
-rw-r--r--server/src/session.h5
-rw-r--r--server/src/sessionparser.cc71
-rw-r--r--server/src/sessionparser.h10
-rw-r--r--server/src/sessionserialiser.cc47
-rw-r--r--server/src/template.h1
-rw-r--r--server/src/templateparser.cc4
-rw-r--r--server/src/transactionhandler.cc40
26 files changed, 852 insertions, 254 deletions
diff --git a/server/src/Makefile.am b/server/src/Makefile.am
index 167f4e4..bb172bd 100644
--- a/server/src/Makefile.am
+++ b/server/src/Makefile.am
@@ -36,6 +36,8 @@ pracrod_SOURCES = \
journal.cc \
journal_uploadserver.cc \
log.cc \
+ luascript.cc \
+ luaoncommit.cc \
luapraxisd.cc \
luaquerymapper.cc \
luaresume.cc \
@@ -51,7 +53,6 @@ pracrod_SOURCES = \
queryhandlerpentominos.cc \
queryhandlerpracro.cc \
queryparser.cc \
- resumeparser.cc \
saxparser.cc \
semaphore.cc \
server.cc \
@@ -97,6 +98,8 @@ EXTRA_DIST = \
journal.h \
journal_uploadserver.h \
log.h \
+ luascript.h \
+ luaoncommit.h \
luapraxisd.h \
luaquerymapper.h \
luaresume.h \
@@ -114,7 +117,6 @@ EXTRA_DIST = \
queryhandlerpracro.h \
queryparser.h \
queryresult.h \
- resumeparser.h \
saxparser.h \
semaphore.h \
server.h \
diff --git a/server/src/client_connection.cc b/server/src/client_connection.cc
index b9d17b9..c3de7b0 100644
--- a/server/src/client_connection.cc
+++ b/server/src/client_connection.cc
@@ -108,6 +108,7 @@ void ClientConnection::nocommit(Session *session)
}
void ClientConnection::commit(Session *session)
+ throw(LUAScript::Exception, Journal::Exception)
{
if(docommit) {
if(session->isReadonly()) { // Commit of an empty session discards it.
@@ -117,7 +118,13 @@ void ClientConnection::commit(Session *session)
DEBUG(connection, "Commit (%s)\n", session->id().c_str());
std::string sid = session->id();
- session->commit();
+ try {
+ session->commit();
+ } catch(LUAScript::Exception &e) {
+ throw e;
+ } catch(Journal::Exception &e) {
+ throw e;
+ }
env.sessions.deleteSession(sid);
sessionid = "";
docommit = false;
@@ -208,7 +215,15 @@ bool ClientConnection::handle()
response = handleTransaction(request, transaction, env, *session);
}
- commit(session);
+ try {
+ commit(session);
+ } catch(LUAScript::Exception &e) {
+ response = error_box(xml_encode(e.msg));
+ return true;
+ } catch(Journal::Exception &e) {
+ response = error_box(xml_encode(e.msg));
+ return true;
+ }
nocommit(session);
discard(session);
diff --git a/server/src/client_connection.h b/server/src/client_connection.h
index b8f7836..0bfa2e4 100644
--- a/server/src/client_connection.h
+++ b/server/src/client_connection.h
@@ -36,6 +36,8 @@
#include "transaction.h"
#include "transactionparser.h"
+#include "luascript.h"
+
class Session;
class ClientConnection : public Connection {
@@ -55,7 +57,7 @@ public:
void getReply(Httpd::Reply &reply);
private:
- void commit(Session *session);
+ void commit(Session *session) throw(LUAScript::Exception, Journal::Exception);
void nocommit(Session *session);
void discard(Session *session);
diff --git a/server/src/journal.cc b/server/src/journal.cc
index fc4203c..04b1459 100644
--- a/server/src/journal.cc
+++ b/server/src/journal.cc
@@ -32,7 +32,8 @@
Journal::Journal() {}
void Journal::addEntry(Transaction &transaction, Commit &commit,
- std::string resume, Template *templ)
+ std::string resume, Template *templ,
+ LUAOnCommit *oncommit)
{
size_t index = 0;
std::vector< Macro >::iterator i = templ->macros.begin();
@@ -70,16 +71,17 @@ void Journal::addEntry(Transaction &transaction, Commit &commit,
}
#endif
- addEntry(resume, commit.macro, transaction.user, index);
+ addEntry(resume, commit.macro, transaction.user, index, oncommit);
}
void Journal::addEntry(std::string resume, std::string macro,
- std::string user, int index)
+ std::string user, int index, LUAOnCommit *oncommit)
{
DEBUG(journal, "Add: %p %s %s - %s\n", this, macro.c_str(),
user.c_str(), resume.c_str());
ResumeEntry re;
+ re.oncommit = oncommit;
re.resume = resume;
re.macro = macro;
re.user = user;
@@ -148,6 +150,22 @@ std::string Journal::patientID()
return _patientid;
}
+void Journal::runOnCommitScripts() throw(LUAScript::Exception)
+{
+ std::map< int, ResumeEntry >::iterator i = entrylist.begin();
+ while(i != entrylist.end()) {
+ if(i->second.oncommit != NULL) {
+ try {
+ i->second.oncommit->run();
+ } catch(LUAScript::Exception &e) {
+ throw e;
+ }
+ }
+ i++;
+ }
+}
+
+
#ifdef TEST_JOURNAL
//deps: debug.cc log.cc journal_uploadserver.cc journal_commit.cc
//cflags: -I..
diff --git a/server/src/journal.h b/server/src/journal.h
index 573f252..d098756 100644
--- a/server/src/journal.h
+++ b/server/src/journal.h
@@ -33,22 +33,31 @@
#include "transaction.h"
#include "template.h"
+#include "luaoncommit.h"
class SessionSerialiser;
class Journal {
friend class SessionSerialiser;
public:
+ class Exception {
+ public:
+ Exception(std::string m) : msg(m) {}
+ std::string msg;
+ };
+
Journal();
virtual ~Journal() {}
void addEntry(Transaction &transaction, Commit &commit,
- std::string resume, Template *templ);
+ std::string resume, Template *templ, LUAOnCommit *oncommit);
void addEntry(std::string resume, std::string macro,
- std::string user, int index);
+ std::string user, int index, LUAOnCommit *oncommit);
+
+ void runOnCommitScripts() throw(LUAScript::Exception);
- virtual void commit() = 0;
+ virtual void commit() throw(Exception) = 0;
std::string getEntry(std::string macro);
void removeEntry(std::string macro);
@@ -65,6 +74,7 @@ protected:
std::string resume;
std::string macro;
std::string user;
+ LUAOnCommit *oncommit;
bool dirty;
};
diff --git a/server/src/journal_commit.cc b/server/src/journal_commit.cc
index 0c1a93d..d765ebb 100644
--- a/server/src/journal_commit.cc
+++ b/server/src/journal_commit.cc
@@ -132,6 +132,7 @@ int journal_commit(const char *cpr, const char *user,
// send body
if(sock != -1 && write(sock, resume.c_str(), resume.size()) != (ssize_t)resume.size()) {
ERR_LOG(journal, "write did not write all the bytes in the buffer.\n");
+ return -1;
}
DEBUG(journal, "%s\n", buf);
diff --git a/server/src/journal_uploadserver.cc b/server/src/journal_uploadserver.cc
index a1299ec..eac6cd5 100644
--- a/server/src/journal_uploadserver.cc
+++ b/server/src/journal_uploadserver.cc
@@ -163,7 +163,10 @@ JournalUploadServer::JournalUploadServer(std::string host,
}
void JournalUploadServer::commit()
+ throw(Journal::Exception)
{
+ int ret = 0;
+
#ifdef USE_MULTIPLE_USERS
std::string resume;
std::string olduser;
@@ -177,9 +180,12 @@ void JournalUploadServer::commit()
}
if(i->second.user != olduser && olduser != "" && resume != "") {
- journal_commit(patientID().c_str(), olduser.c_str(),
- host.c_str(), port,
- resume.c_str(), resume.size());
+ ret = journal_commit(patientID().c_str(), olduser.c_str(),
+ host.c_str(), port,
+ resume.c_str(), resume.size());
+
+ if(ret == -1) throw Journal::Exception("Journal Commit error.");
+
// FIXME - UGLY HACK: Avoid upload server spooling in the wrong order.
usleep(200000);
resume = "";
@@ -195,9 +201,9 @@ void JournalUploadServer::commit()
if(resume == "") return;
- journal_commit(patientID().c_str(), olduser.c_str(),
- host.c_str(), port,
- resume.c_str(), resume.size());
+ ret = journal_commit(patientID().c_str(), olduser.c_str(),
+ host.c_str(), port,
+ resume.c_str(), resume.size());
#else
std::string resume;
std::string user;
@@ -222,10 +228,12 @@ void JournalUploadServer::commit()
if(resume == "") return;
// Connect to praxisuploadserver and commit all resumes in one bulk.
- journal_commit(patientID().c_str(), user.c_str(),
- host.c_str(), port,
- resume.c_str(), resume.size());
+ ret = journal_commit(patientID().c_str(), user.c_str(),
+ host.c_str(), port,
+ resume.c_str(), resume.size());
#endif/*USE_MULTIPLE_USERS*/
+
+ if(ret == -1) throw Journal::Exception("Journal Commit error.");
}
diff --git a/server/src/journal_uploadserver.h b/server/src/journal_uploadserver.h
index 2393709..3e2fab3 100644
--- a/server/src/journal_uploadserver.h
+++ b/server/src/journal_uploadserver.h
@@ -33,7 +33,7 @@
class JournalUploadServer : public Journal {
public:
JournalUploadServer(std::string host, unsigned short int port);
- void commit();
+ void commit() throw(Journal::Exception);
private:
std::string host;
diff --git a/server/src/luaoncommit.cc b/server/src/luaoncommit.cc
new file mode 100644
index 0000000..8e96066
--- /dev/null
+++ b/server/src/luaoncommit.cc
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * luaoncommit.cc
+ *
+ * Thu Jan 12 08:38:02 CET 2012
+ * Copyright 2012 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pracro is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "luaoncommit.h"
+
+#include <lua.hpp>
+#include <lauxlib.h>
+
+#include "luautil.h"
+#include "luapraxisd.h"
+
+#include "debug.h"
+
+#include <stdio.h>
+
+LUAOnCommit::LUAOnCommit(Transaction &t, Commit &c) : LUAScript()
+{
+ setEnv(LUAScript::ENV_PATIENTID, t.patientid);
+ setEnv(LUAScript::ENV_TEMPLATE, c.templ);
+ setEnv(LUAScript::ENV_MACRO, c.macro);
+ setEnv(LUAScript::ENV_USER, t.user);
+
+ std::map<std::string, std::string>::iterator i = c.fields.begin();
+ while(i != c.fields.end()) {
+ addValue(i->first, i->second);
+ i++;
+ }
+}
+
+#ifdef TEST_LUAONCOMMIT
+//Additional dependency files
+//deps:
+//Required cflags (autoconf vars may be used)
+//cflags:
+//Required link options (autoconf vars may be used)
+//libs:
+#include "test.h"
+
+TEST_BEGIN;
+
+// TODO: Put some testcode here (see test.h for usable macros).
+TEST_TRUE(false, "No tests yet!");
+
+TEST_END;
+
+#endif/*TEST_LUAONCOMMIT*/
diff --git a/server/src/resumeparser.h b/server/src/luaoncommit.h
index 381e7c6..b64e744 100644
--- a/server/src/resumeparser.h
+++ b/server/src/luaoncommit.h
@@ -1,9 +1,10 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
/***************************************************************************
- * resumeparser.h
+ * luaoncommit.h
*
- * Mon Oct 1 11:17:35 CEST 2007
- * Copyright 2007 Bent Bisballe Nyeng
+ * Thu Jan 12 08:38:02 CET 2012
+ * Copyright 2012 Bent Bisballe Nyeng
* deva@aasimon.org
****************************************************************************/
@@ -24,13 +25,20 @@
* along with Pracro; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __PRACRO_RESUMEPARSER_H__
-#define __PRACRO_RESUMEPARSER_H__
+#ifndef __PRACRO_LUAONCOMMIT_H__
+#define __PRACRO_LUAONCOMMIT_H__
+
+#include "luascript.h"
-#include <string>
#include "transaction.h"
-#include "template.h"
+#include <string>
+
+class LUAOnCommit : public LUAScript {
+public:
+ LUAOnCommit() {}
+ LUAOnCommit(Transaction &transaction, Commit &commit);
-std::string resume_parser(Macro &macro, Commit &commit);
+ const char *name() { return "lua on commit"; }
+};
-#endif/*__PRACRO_RESUMEPARSER_H__*/
+#endif/*__PRACRO_LUAONCOMMIT_H__*/
diff --git a/server/src/luaresume.cc b/server/src/luaresume.cc
index 49de8be..1db4fb3 100644
--- a/server/src/luaresume.cc
+++ b/server/src/luaresume.cc
@@ -26,122 +26,27 @@
*/
#include "luaresume.h"
+#include <lua.hpp>
+#include <lauxlib.h>
+
#include "luautil.h"
-#include "luapraxisd.h"
#include "debug.h"
#include <stdio.h>
-#define GLOBAL_POINTER "_pracroGlobalLUAObjectPointerThisShouldBeANameThatIsNotAccidentallyOverwritten"
-
-static int _value(lua_State *L)
-{
- Pracro::checkParameters(L,
- Pracro::T_STRING,
- Pracro::T_END);
-
- std::string name = lua_tostring(L, lua_gettop(L));
-
- lua_getglobal(L, GLOBAL_POINTER);
- LUAResume *lua = (LUAResume*)lua_touserdata(L, lua_gettop(L));
-
- if(!lua) {
- lua_pushstring(L, "No LUA pointer!");
- lua_error(L);
- return 1;
- }
-
- std::string value = lua->value(name);
- lua_pushstring(L, value.c_str());
-
- return 1;
-}
-
-LUAResume::LUAResume(Commit &c)
- : commit(c)
-{
- L = luaL_newstate();
- if(L == NULL) {
- ERR(luaresume, "Could not create LUA state.\n");
- return;
- }
-
- luaL_openlibs(L);
-
- lua_pushlightuserdata(L, this); // Push the pointer to 'this' instance
- lua_setglobal(L, GLOBAL_POINTER); // Assign it to a global lua var.
-
- lua_register(L, "value", _value);
-
- register_praxisd(L);
-}
-
-LUAResume::~LUAResume()
-{
- lua_close(L);
-}
-
-std::string LUAResume::value(std::string name)
+LUAResume::LUAResume(Transaction &t, Commit &c) : LUAScript()
{
- if(commit.fields.find(name) == commit.fields.end()) {
- ERR(luaresume, "LUAResume: No such field '%s'\n", name.c_str());
- return "";
+ setEnv(LUAScript::ENV_PATIENTID, t.patientid);
+ setEnv(LUAScript::ENV_TEMPLATE, c.templ);
+ setEnv(LUAScript::ENV_MACRO, c.macro);
+ setEnv(LUAScript::ENV_USER, t.user);
+
+ std::map<std::string, std::string>::iterator i = c.fields.begin();
+ while(i != c.fields.end()) {
+ addValue(i->first, i->second);
+ i++;
}
-
- return commit.fields[name];
-}
-
-std::string LUAResume::run(std::string program)
-{
- if(L == NULL) {
- ERR(luaresume, "LUA state not initialized!");
- return "";
- }
-
- DEBUG(luaresume, "Running %s\n", program.c_str());
-
- /*
- lua_pushstring(L, value.toStdString().c_str());
- lua_setglobal(L, "value");
-
- lua_pushstring(L, name.toStdString().c_str());
- lua_setglobal(L, "name");
- */
-
- int top = lua_gettop(L);
-
- if(luaL_loadbuffer(L, program.c_str(), program.size(),
- "lua resume generator")) {
- ERR(luaresume, "loadbufer: %s\n", lua_tostring(L, lua_gettop(L)));
- return "";
- }
-
- // Run the loaded code
- if(lua_pcall(L, 0, LUA_MULTRET, 0)) {
- ERR(luaresume, "pcall: %s\n" , lua_tostring(L, lua_gettop(L)));
- return "";
- }
-
- if(top != lua_gettop(L) - 1) {
- ERR(luaresume, "Program did not return a single value.\n");
- return "";
- }
-
- if(lua_isstring(L, lua_gettop(L)) == false) {
- ERR(luaresume, "Program did not return a string value.\n");
- return "";
- }
-
- std::string res = lua_tostring(L, lua_gettop(L));
- lua_pop(L, 1);
-
- return res;
-}
-
-void LUAResume::error(std::string message)
-{
- ERR(luaresume, "LUA ERROR: %s\n", message.c_str());
}
#ifdef TEST_LUARESUME
diff --git a/server/src/luaresume.h b/server/src/luaresume.h
index 1132f26..47a7652 100644
--- a/server/src/luaresume.h
+++ b/server/src/luaresume.h
@@ -27,26 +27,16 @@
#ifndef __PRACRO_LUARESUME_H__
#define __PRACRO_LUARESUME_H__
-#include <lua.hpp>
-#include <lauxlib.h>
+#include "luascript.h"
#include "transaction.h"
#include <string>
-class LUAResume {
+class LUAResume : public LUAScript {
public:
- LUAResume(Commit &commit);
- ~LUAResume();
-
- std::string run(std::string program);
+ LUAResume(Transaction &transaction, Commit &commit);
- std::string value(std::string name);
-
- void error(std::string message);
-
-private:
- lua_State *L;
- Commit &commit;
+ const char *name() { return "lua resume generator"; }
};
#endif/*__PRACRO_LUARESUME_H__*/
diff --git a/server/src/luascript.cc b/server/src/luascript.cc
new file mode 100644
index 0000000..f4aef40
--- /dev/null
+++ b/server/src/luascript.cc
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * luascript.cc
+ *
+ * Tue Jan 10 14:43:39 CET 2012
+ * Copyright 2012 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pracro is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "luascript.h"
+
+#include "configuration.h"
+#include "debug.h"
+
+#include "luautil.h"
+#include "luapraxisd.h"
+
+#define GLOBAL_POINTER "_pracroGlobalLUAObjectPointerThisShouldBeANameThatIsNotAccidentallyOverwritten"
+
+static int _value(lua_State *L)
+{
+ Pracro::checkParameters(L,
+ Pracro::T_STRING,
+ Pracro::T_END);
+
+ std::string name = lua_tostring(L, lua_gettop(L));
+
+ lua_getglobal(L, GLOBAL_POINTER);
+ LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L));
+
+ if(!lua) {
+ lua_pushstring(L, "No LUA pointer!");
+ lua_error(L);
+ return 1;
+ }
+
+ if(lua->hasValue(name)) {
+ lua_pushstring(L, lua->value(name).c_str());
+ } else {
+ lua_pushnil(L);
+ }
+
+ return 1;
+}
+
+static int _patientid(lua_State *L)
+{
+ Pracro::checkParameters(L, Pracro::T_END);
+
+ lua_getglobal(L, GLOBAL_POINTER);
+ LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L));
+
+ if(!lua) {
+ lua_pushstring(L, "No LUA pointer!");
+ lua_error(L);
+ return 1;
+ }
+
+ lua_pushstring(L, lua->env(LUAScript::ENV_PATIENTID).c_str());
+
+ return 1;
+}
+
+static int _template(lua_State *L)
+{
+ Pracro::checkParameters(L, Pracro::T_END);
+
+ lua_getglobal(L, GLOBAL_POINTER);
+ LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L));
+
+ if(!lua) {
+ lua_pushstring(L, "No LUA pointer!");
+ lua_error(L);
+ return 1;
+ }
+
+ lua_pushstring(L, lua->env(LUAScript::ENV_TEMPLATE).c_str());
+
+ return 1;
+}
+
+static int _macro(lua_State *L)
+{
+ Pracro::checkParameters(L, Pracro::T_END);
+
+ lua_getglobal(L, GLOBAL_POINTER);
+ LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L));
+
+ if(!lua) {
+ lua_pushstring(L, "No LUA pointer!");
+ lua_error(L);
+ return 1;
+ }
+
+ lua_pushstring(L, lua->env(LUAScript::ENV_MACRO).c_str());
+
+ return 1;
+}
+
+static int _user(lua_State *L)
+{
+ Pracro::checkParameters(L, Pracro::T_END);
+
+ lua_getglobal(L, GLOBAL_POINTER);
+ LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L));
+
+ if(!lua) {
+ lua_pushstring(L, "No LUA pointer!");
+ lua_error(L);
+ return 1;
+ }
+
+ lua_pushstring(L, lua->env(LUAScript::ENV_USER).c_str());
+
+ return 1;
+}
+
+LUAScript::LUAScript()
+{
+ L = NULL;
+}
+
+void LUAScript::init()
+ throw(Exception)
+{
+ if(L) return;
+
+ L = luaL_newstate();
+ if(L == NULL) {
+ ERR(luaresume, "Could not create LUA state.\n");
+ throw Exception("Could not create LUA state.");
+ }
+
+ luaL_openlibs(L);
+
+ lua_pushlightuserdata(L, this); // Push the pointer to 'this' instance
+ lua_setglobal(L, GLOBAL_POINTER); // Assign it to a global lua var.
+
+ lua_register(L, "value", _value);
+ lua_register(L, "patientid", _patientid);
+ lua_register(L, "template", _template);
+ lua_register(L, "macro", _macro);
+ lua_register(L, "user", _user);
+
+ register_praxisd(L);
+}
+
+void LUAScript::addFile(std::string src)
+{
+ std::string file =
+ Conf::xml_basedir + "/include/" + src;
+ FILE *fp = fopen(file.c_str(), "r");
+ if(fp) {
+ char buf[64];
+ size_t sz;
+ std::string inc;
+ while((sz = fread(buf, 1, sizeof(buf), fp)) != 0) {
+ inc.append(buf, sz);
+ }
+ fclose(fp);
+ addCode(inc, file);
+ }
+}
+
+void LUAScript::addCode(std::string c, std::string name)
+{
+ scripts.push_back(std::make_pair(c, name));
+}
+
+void LUAScript::addValue(std::string name, const std::string &value)
+{
+ values[name] = value;
+}
+
+void LUAScript::addScripts(std::vector< Script > &scripts)
+{
+ std::vector< Script >::iterator spi = scripts.begin();
+ while(spi != scripts.end()) {
+ if(spi->attributes.find("src") != spi->attributes.end()) {
+ std::string src = spi->attributes["src"];
+ addFile(src);
+ } else {
+ addCode(spi->code);
+ }
+ spi++;
+ }
+}
+
+void LUAScript::run()
+ throw(Exception)
+{
+ try {
+ init();
+ } catch(Exception &e) {
+ throw Exception(e.msg);
+ }
+
+ if(L == NULL) {
+ ERR(luaresume, "LUA state not initialized!");
+ return;
+ }
+
+ top = lua_gettop(L);
+
+ std::vector<std::pair<std::string, std::string> >::iterator i =
+ scripts.begin();
+ while(i != scripts.end()) {
+ std::string program = i->first;
+ std::string codename = name();
+ if(i->second != "") codename += ": " + i->second;
+
+ DEBUG(luaresume, "Running %s: %s\n", codename.c_str(), program.c_str());
+
+ if(luaL_loadbuffer(L, program.c_str(), program.size(), codename.c_str())) {
+ ERR(luaresume, "loadbufer: %s\n", lua_tostring(L, lua_gettop(L)));
+ throw Exception(lua_tostring(L, lua_gettop(L)));
+ }
+
+ // Run the loaded code
+ if(lua_pcall(L, 0, LUA_MULTRET, 0)) {
+ ERR(luaresume, "pcall: %s\n" , lua_tostring(L, lua_gettop(L)));
+ throw Exception(lua_tostring(L, lua_gettop(L)));
+ }
+
+ i++;
+ }
+}
+
+std::string LUAScript::resultString() throw(Exception)
+{
+ if(top != lua_gettop(L) - 1) {
+ ERR(luaresume, "Program did not return a single value.\n");
+ throw Exception("Program did not return a single value.");
+ }
+
+ if(lua_isstring(L, lua_gettop(L)) == false) {
+ ERR(luaresume, "Program did not return a string value.\n");
+ throw Exception("Program did not return a string value.");
+ }
+
+ std::string res = lua_tostring(L, lua_gettop(L));
+ lua_pop(L, 1);
+
+ return res;
+}
+
+bool LUAScript::hasValue(std::string name)
+{
+ return values.find(name) != values.end();
+}
+
+std::string LUAScript::value(std::string name)
+{
+ if(values.find(name) != values.end()) return values[name];
+ return "";
+}
+
+std::string LUAScript::env(LUAScript::env_t id)
+{
+ if(_env.find(id) == _env.end()) return "";
+ return _env[id];
+}
+
+void LUAScript::setEnv(LUAScript::env_t id, std::string value)
+{
+ _env[id] = value;
+}
+
+#ifdef TEST_LUASCRIPT
+//Additional dependency files
+//deps:
+//Required cflags (autoconf vars may be used)
+//cflags:
+//Required link options (autoconf vars may be used)
+//libs:
+#include "test.h"
+
+TEST_BEGIN;
+
+// TODO: Put some testcode here (see test.h for usable macros).
+TEST_TRUE(false, "No tests yet!");
+
+TEST_END;
+
+#endif/*TEST_LUASCRIPT*/
diff --git a/server/src/luascript.h b/server/src/luascript.h
new file mode 100644
index 0000000..ec6c95f
--- /dev/null
+++ b/server/src/luascript.h
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * luascript.h
+ *
+ * Tue Jan 10 14:43:39 CET 2012
+ * Copyright 2012 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pracro is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __PRACRO_LUASCRIPT_H__
+#define __PRACRO_LUASCRIPT_H__
+
+#include <lua.hpp>
+#include <lauxlib.h>
+
+#include <string>
+#include <map>
+#include <vector>
+
+#include "template.h"
+
+class LUAScript {
+ friend class SessionSerialiser;
+ friend class SessionParser;
+public:
+ typedef enum {
+ ENV_PATIENTID,
+ ENV_TEMPLATE,
+ ENV_MACRO,
+ ENV_USER
+ } env_t;
+
+ class Exception {
+ public:
+ Exception(std::string m) : msg(m) {}
+ std::string msg;
+ };
+
+ LUAScript();
+
+ virtual const char *name() { return ""; }
+
+ void init() throw(Exception);
+
+ void addFile(std::string file);
+ void addCode(std::string code, std::string codename = "");
+ void addScripts(std::vector< Script > &scripts);
+
+ void addValue(std::string name, const std::string &value);
+
+ void run() throw(Exception);
+
+ bool hasValue(std::string name);
+ std::string value(std::string value);
+
+ std::string env(env_t id);
+ void setEnv(env_t id, std::string value);
+
+ std::string resultString() throw(Exception);
+
+protected:
+ lua_State *L;
+
+ std::map<env_t, std::string> _env;
+
+private:
+ std::vector<std::pair<std::string, std::string> > scripts;
+ std::map<std::string, std::string> values;
+
+ int top;
+};
+
+
+#endif/*__PRACRO_LUASCRIPT_H__*/
diff --git a/server/src/macroparser.cc b/server/src/macroparser.cc
index 7d3f367..be781aa 100644
--- a/server/src/macroparser.cc
+++ b/server/src/macroparser.cc
@@ -116,6 +116,11 @@ void MacroParser::characterData(std::string &data)
assert(current_script); // No script present!
current_script->code.append(data);
}
+
+ if(state == COMMIT_SCRIPT) {
+ assert(current_commit_script); // No script present!
+ current_commit_script->code.append(data);
+ }
}
void MacroParser::startTag(std::string name, attributes_t &attr)
@@ -147,6 +152,18 @@ void MacroParser::startTag(std::string name, attributes_t &attr)
return;
}
+ // Enable oncommit parsing
+ if(name == "oncommit") {
+ if(state != MACRO) error("oncommit found outside macro.");
+ state = COMMIT_SCRIPTS;
+
+ m->resume.attributes = attr;
+
+ assert(m); // No macro is currently available, cannot create resume!
+
+ return;
+ }
+
// Enable Query parsing
if(name == "queries") {
if(state != MACRO) error("queries found outside macro.");
@@ -232,8 +249,18 @@ void MacroParser::startTag(std::string name, attributes_t &attr)
current_resume_script = &(m->resume_scripts.back());
}
break;
+ case COMMIT_SCRIPTS:
+ {
+ state = COMMIT_SCRIPT;
+
+ Script s;
+ s.attributes = attr;
+ m->commit_scripts.push_back(s);
+ current_commit_script = &(m->commit_scripts.back());
+ }
+ break;
default:
- error("<script> tag found outside <scripts> or <resume> tags.");
+ error("<script> tag found outside <scripts>, <commitscripts> or <resume> tags.");
break;
}
return;
@@ -290,6 +317,7 @@ void MacroParser::endTag(std::string name)
state = UNDEFINED;
}
if(name == "resume") state = MACRO;
+ if(name == "oncommit") state = MACRO;
if(name == "queries") state = MACRO;
if(name == "query") state = QUERIES;
if(name == "maps") state = MACRO;
@@ -310,6 +338,11 @@ void MacroParser::endTag(std::string name)
state = RESUME;
break;
+ case COMMIT_SCRIPT:
+ current_commit_script = NULL;
+ state = COMMIT_SCRIPTS;
+ break;
+
default:
// tag mismatch?
break;
diff --git a/server/src/macroparser.h b/server/src/macroparser.h
index 71ef911..ab6fda5 100644
--- a/server/src/macroparser.h
+++ b/server/src/macroparser.h
@@ -42,7 +42,9 @@ class MacroParser : public SAXParser {
MAP,
WIDGETS,
SCRIPTS,
- SCRIPT
+ SCRIPT,
+ COMMIT_SCRIPTS,
+ COMMIT_SCRIPT
} ParserState;
public:
@@ -76,6 +78,7 @@ private:
Map *current_map;
Script *current_script;
Script *current_resume_script;
+ Script *current_commit_script;
std::vector< Widget* > widgetstack;
// Error callback function.
diff --git a/server/src/pracrodaopgsql.cc b/server/src/pracrodaopgsql.cc
index f9a773f..db0a9aa 100644
--- a/server/src/pracrodaopgsql.cc
+++ b/server/src/pracrodaopgsql.cc
@@ -228,6 +228,7 @@ void PracroDAOPgsql::commitTransaction(std::string sessionid,
}
+//#define NEW
Values PracroDAOPgsql::getLatestValues(std::string sessionid,
std::string patientid,
Macro *macro,
@@ -261,6 +262,70 @@ Values PracroDAOPgsql::getLatestValues(std::string sessionid,
}
pqxx::work W(*conn);
+
+#ifdef NEW
+
+ // Do not search for nothing...
+ if(fieldnames.size() == 0) return values;
+
+ std::string names;
+ std::vector< std::string >::iterator fni = fieldnames.begin();
+ while(fni != fieldnames.end()) {
+ if(names != "") names += " OR ";
+ names += "name='" + W.esc(*fni) + "'";
+ fni++;
+ }
+
+ std::string macros;
+ if(macro) {
+ macros += " AND macro='" + macro->name + "'";
+ if(macro->version != "")
+ macros += " AND t.version='" + macro->version + "'";
+ }
+
+ uncom = uncom;
+ query = "SELECT uid FROM commits WHERE patientid='"+patientid+"' AND"
+ " \"timestamp\">="+soldest.str()+" AND"
+ " (status='committed' OR uid="+sessionid+");";
+ DEBUG(sql, "Query: %s\n", query.c_str());
+ pqxx::result commits = W.exec(query);
+ pqxx::result::const_iterator ci = commits.begin();
+ while(ci != commits.end()) {
+ std::string cid = (*ci)[0].c_str();
+
+ query = "SELECT uid, \"timestamp\" FROM transactions WHERE cid="+cid+
+ macros+";";
+ DEBUG(sql, "Query: %s\n", query.c_str());
+ pqxx::result transactions = W.exec(query);
+ pqxx::result::const_iterator ti = transactions.begin();
+ while(ti != transactions.end()) {
+ std::string tid = (*ti)[0].c_str();
+ time_t timestamp = atol((*ti)[1].c_str());
+
+ query = "SELECT name, value FROM fields WHERE"
+ " transaction="+tid+" AND ("+ names +");";
+ DEBUG(sql, "Query: %s\n", query.c_str());
+ pqxx::result fields = W.exec(query);
+ DEBUG(sql, "Results: %lu\n", fields.size());
+ pqxx::result::const_iterator fi = fields.begin();
+ while(fi != fields.end()) {
+ std::string name = (*fi)[0].c_str();
+ if(values.find(name) == values.end() ||
+ values[name].timestamp <= timestamp) {
+ Value v;
+ v.value = (*fi)[1].c_str();
+ v.timestamp = timestamp;
+ values[name] = v;
+ }
+ fi++;
+ }
+
+ ti++;
+ }
+
+ ci++;
+ }
+#else/*NEW*/
std::string namecond;
if(fieldnames.size() > 0) {
@@ -318,6 +383,7 @@ Values PracroDAOPgsql::getLatestValues(std::string sessionid,
values[(*ri)[0].c_str()] = v;
ri++;
}
+#endif/*NEW*/
} catch (std::exception &e) {
ERR_LOG(db, "Query failed: %s: %s\n", e.what(), query.c_str());
}
diff --git a/server/src/resumeparser.cc b/server/src/resumeparser.cc
deleted file mode 100644
index 1c5335a..0000000
--- a/server/src/resumeparser.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/***************************************************************************
- * resumeparser.cc
- *
- * Mon Oct 1 11:17:35 CEST 2007
- * Copyright 2007 Bent Bisballe Nyeng
- * deva@aasimon.org
- ****************************************************************************/
-
-/*
- * This file is part of Pracro.
- *
- * Pracro is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Pracro is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Pracro; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-#include "resumeparser.h"
-
-#include <string.h>
-
-#include "luaresume.h"
-#include "configuration.h"
-
-std::string resume_parser(Macro &macro, Commit &commit)
-{
- LUAResume luaresume(commit);
-
- std::string code;
-
- std::vector< Script >::iterator spi = macro.resume_scripts.begin();
- while(spi != macro.resume_scripts.end()) {
- if(spi->attributes.find("src") != spi->attributes.end()) {
- std::string src = spi->attributes["src"];
- std::string file =
- Conf::xml_basedir + "/include/" + src;
- FILE *fp = fopen(file.c_str(), "r");
- if(fp) {
- char buf[64];
- size_t sz;
- std::string inc;
- while((sz = fread(buf, 1, sizeof(buf), fp)) != 0) {
- inc.append(buf, sz);
- }
- fclose(fp);
- code += "\n-- BEGIN INCLUDE: '" + src + "'\n";
- code += inc;
- code += "\n-- END INCLUDE: '" + src + "'\n";
- }
- } else {
- code += spi->code;
- }
- spi++;
- }
-
- return luaresume.run(code);
-}
-
-#ifdef TEST_RESUMEPARSER
-//deps: luaresume.cc configuration.cc debug.cc log.cc luautil.cc
-//cflags: -I.. $(LUA_CFLAGS)
-//libs: $(LUA_LIBS)
-#include <test.h>
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-TEST_TRUE(false, "No tests yet!");
-
-TEST_END;
-
-#endif/*TEST_RESUMEPARSER*/
diff --git a/server/src/session.cc b/server/src/session.cc
index fcd138a..234f004 100644
--- a/server/src/session.cc
+++ b/server/src/session.cc
@@ -121,12 +121,21 @@ void Session::setIdle(bool idle)
}
}
-void Session::commit()
+void Session::commit() throw(LUAScript::Exception, Journal::Exception)
{
DEBUG(session, "[%p] commit(sessionid: '%s')\n", this, sessionid.c_str());
if(_journal != NULL) {
- _journal->commit();
+ try {
+ _journal->runOnCommitScripts();
+ } catch(LUAScript::Exception &e) {
+ throw e;
+ }
+ try {
+ _journal->commit();
+ } catch(Journal::Exception &e) {
+ throw e;
+ }
delete _journal;
_journal = NULL;
}
diff --git a/server/src/session.h b/server/src/session.h
index 4d1ed12..85382f5 100644
--- a/server/src/session.h
+++ b/server/src/session.h
@@ -37,6 +37,9 @@
#include "transaction.h"
#include "template.h"
+#include "luascript.h"
+#include "journal.h"
+
class Environment;
class Journal;
@@ -52,7 +55,7 @@ public:
void lock();
void unlock();
- void commit();
+ void commit() throw(LUAScript::Exception, Journal::Exception);
void nocommit();
void discard();
diff --git a/server/src/sessionparser.cc b/server/src/sessionparser.cc
index 6b3653e..8913e3c 100644
--- a/server/src/sessionparser.cc
+++ b/server/src/sessionparser.cc
@@ -37,6 +37,9 @@ SessionParser::SessionParser()
totalbytes = 0;
inresume = false;
indatabase = false;
+ invalue = false;
+ inscript = false;
+ inenv = false;
}
SessionParser::~SessionParser()
@@ -49,6 +52,26 @@ void SessionParser::characterData(std::string &data)
entries[entries.size()-1].resume += data;
}
+ if(inscript) {
+ Entry &e = entries[entries.size() - 1];
+ LUAOnCommit *oncommit = e.oncommit;
+ std::pair<std::string, std::string> &val =
+ oncommit->scripts[oncommit->scripts.size() - 1];
+ val.first += data;
+ }
+
+ if(invalue) {
+ Entry &e = entries[entries.size() - 1];
+ LUAOnCommit *oncommit = e.oncommit;
+ oncommit->values[valuename] += data;
+ }
+
+ if(inenv) {
+ Entry &e = entries[entries.size() - 1];
+ LUAOnCommit *oncommit = e.oncommit;
+ oncommit->_env[envid] += data;
+ }
+
if(indatabase) {
database += data;
}
@@ -80,12 +103,51 @@ void SessionParser::startTag(std::string name, attributes_t &attr)
e.index = atoi(attr["index"].c_str());
e.macro = attr["macro"];
e.user = attr["user"];
+ e.oncommit = NULL;
entries.push_back(e);
}
if(name == "resume") {
inresume = true;
}
+
+ if(name == "oncommit") {
+ Entry &e = entries[entries.size() - 1];
+ if(e.oncommit != NULL) {
+ ERR(sessionparser, "Multiple oncommit tags in journal!\n");
+ return;
+ }
+ e.oncommit = new LUAOnCommit();
+ }
+ if(name == "envs") { }
+
+ if(name == "env") {
+ if(attr["id"] == "ENV_PATIENTID") envid = LUAScript::ENV_PATIENTID;
+ else if(attr["id"] == "ENV_TEMPLATE") envid = LUAScript::ENV_TEMPLATE;
+ else if(attr["id"] == "ENV_MACRO") envid = LUAScript::ENV_MACRO;
+ else if(attr["id"] == "ENV_USER") envid = LUAScript::ENV_USER;
+ else {
+ // Unknown env id
+ return;
+ }
+ inenv = true;
+ }
+
+ if(name == "values") { }
+
+ if(name == "value") {
+ valuename = attr["name"];
+ invalue = true;
+ }
+
+ if(name == "scripts") {}
+
+ if(name == "script") {
+ Entry &e = entries[entries.size() - 1];
+ LUAOnCommit *oncommit = e.oncommit;
+ oncommit->addCode("", attr["name"]);
+ inscript = true;
+ }
}
void SessionParser::endTag(std::string name)
@@ -96,6 +158,15 @@ void SessionParser::endTag(std::string name)
if(name == "database") {
indatabase = false;
}
+ if(name == "env") {
+ inenv = false;
+ }
+ if(name == "value") {
+ invalue = false;
+ }
+ if(name == "script") {
+ inscript = false;
+ }
}
void SessionParser::parseError(const char *buf, size_t len,
diff --git a/server/src/sessionparser.h b/server/src/sessionparser.h
index df32b06..8734fbd 100644
--- a/server/src/sessionparser.h
+++ b/server/src/sessionparser.h
@@ -30,6 +30,8 @@
#include "saxparser.h"
+#include "luaoncommit.h"
+
#include <string>
#include <vector>
@@ -50,10 +52,11 @@ public:
std::string userid;
std::string database;
std::string dbtype;
-
+
class Entry {
public:
int index;
+ LUAOnCommit *oncommit;
std::string macro;
std::string resume;
std::string user;
@@ -63,7 +66,12 @@ public:
private:
bool inresume;
+ bool inscript;
+ bool invalue;
+ bool inenv;
+ std::string valuename;
bool indatabase;
+ LUAScript::env_t envid;
};
#endif/*__PRACRO_SESSIONPARSER_H__*/
diff --git a/server/src/sessionserialiser.cc b/server/src/sessionserialiser.cc
index 36d0a0d..386a115 100644
--- a/server/src/sessionserialiser.cc
+++ b/server/src/sessionserialiser.cc
@@ -88,7 +88,8 @@ Session *SessionSerialiser::loadStr(const std::string &xml)
j->setPatientID(XDEC(parser.patientid));
std::vector<SessionParser::Entry>::iterator i = parser.entries.begin();
while(i != parser.entries.end()) {
- j->addEntry(XDEC(i->resume), XDEC(i->macro), XDEC(i->user), i->index);
+ j->addEntry(XDEC(i->resume), XDEC(i->macro), XDEC(i->user), i->index,
+ i->oncommit);
i++;
}
@@ -122,6 +123,50 @@ std::string SessionSerialiser::saveStr(Session *session)
" macro=\"" + XENC(i->second.macro) + "\""
" user=\"" + XENC(i->second.user) + "\">\n";
xml += " <resume>" + XENC(i->second.resume) + "</resume>\n";
+ LUAOnCommit *oncommit = i->second.oncommit;
+ if(oncommit != NULL) {
+ xml += " <oncommit>\n";
+
+ xml += " <envs>\n";
+ std::map<LUAScript::env_t, std::string>::iterator ei =
+ oncommit->_env.begin();
+ while(ei != oncommit->_env.end()) {
+ std::string id;
+ switch(ei->first) {
+ case LUAScript::ENV_PATIENTID: id = "ENV_PATIENTID"; break;
+ case LUAScript::ENV_TEMPLATE: id = "ENV_TEMPLATE"; break;
+ case LUAScript::ENV_MACRO: id = "ENV_MACRO"; break;
+ case LUAScript::ENV_USER: id = "ENV_USER"; break;
+ }
+
+ xml += " <env id=\"" + XENC(id) + "\">"+
+ XENC(ei->second) + "</env>\n";
+ ei++;
+ }
+ xml += " </envs>\n";
+
+ xml += " <values>\n";
+ std::map<std::string, std::string>::iterator vi =
+ oncommit->values.begin();
+ while(vi != oncommit->values.end()) {
+ xml += " <value name=\"" + XENC(vi->first) + "\">"+
+ XENC(vi->second) + "</value>\n";
+ vi++;
+ }
+ xml += " </values>\n";
+
+ xml += " <scripts>\n";
+ std::vector<std::pair<std::string, std::string> >::iterator si =
+ oncommit->scripts.begin();
+ while(si != oncommit->scripts.end()) {
+ xml += " <script name=\"" + XENC(si->second) + "\">"+
+ XENC(si->first) + "</script>\n";
+ si++;
+ }
+ xml += " </scripts>\n";
+
+ xml += " </oncommit>\n";
+ }
xml += " </entry>\n";
i++;
diff --git a/server/src/template.h b/server/src/template.h
index e549ef3..853db3d 100644
--- a/server/src/template.h
+++ b/server/src/template.h
@@ -67,6 +67,7 @@ public:
maps_t maps;
std::vector< Script > scripts;
std::vector< Script > resume_scripts;
+ std::vector< Script > commit_scripts;
Widget widgets;
Resume resume;
diff --git a/server/src/templateparser.cc b/server/src/templateparser.cc
index 704b215..8fc3eff 100644
--- a/server/src/templateparser.cc
+++ b/server/src/templateparser.cc
@@ -133,7 +133,7 @@ void TemplateParser::startTag(std::string name, attributes_t &attr)
// Enable script parsing
if(name == "scripts") {
- if(state != MACRO) error("scripts found outside macro.");
+ if(state != TEMPLATE) error("scripts found outside template.");
state = SCRIPTS;
assert(t); // No template is currently available, cannot create maps!
@@ -158,7 +158,7 @@ void TemplateParser::startTag(std::string name, attributes_t &attr)
}
break;
default:
- error("<script> tag found outside <scripts> or <resume> tags.");
+ error("<script> tag found outside <scripts> tag.");
break;
}
return;
diff --git a/server/src/transactionhandler.cc b/server/src/transactionhandler.cc
index 7ec38f8..a52dd50 100644
--- a/server/src/transactionhandler.cc
+++ b/server/src/transactionhandler.cc
@@ -28,12 +28,13 @@
#include "transactionhandler.h"
#include "macroparser.h"
-#include "resumeparser.h"
#include "templateparser.h"
#include "templateheaderparser.h"
#include "courseparser.h"
#include "configuration.h"
#include "luaquerymapper.h"
+#include "luaresume.h"
+#include "luaoncommit.h"
#include "queryhandlerpentominos.h"
#include "queryhandlerpracro.h"
#include "xml_encode_decode.h"
@@ -60,6 +61,7 @@ static std::string error_box(std::string message)
static std::string handleCommits(Transaction &transaction, Environment &env,
Session &session)
+ throw(LUAScript::Exception)
{
std::string answer;
@@ -71,19 +73,32 @@ static std::string handleCommits(Transaction &transaction, Environment &env,
mp.parse();
Macro *macro = mp.getMacro();
- std::string resume = resume_parser(*macro, commit);
- commit.fields["journal.resume"] = resume;
- session.commitMacro(transaction, commit, *macro);
+ std::string resume;
+ try {
+ LUAResume luaresume(transaction, commit);
+ luaresume.addScripts(macro->resume_scripts);
+ luaresume.run();
+ resume = luaresume.resultString();
+ commit.fields["journal.resume"] = resume;
+ session.commitMacro(transaction, commit, *macro);
+ } catch(LUAScript::Exception &e) {
+ throw e;
+ }
- if(resume != "") {
-
+ LUAOnCommit *oncommit = NULL;
+ if(macro->commit_scripts.size() != 0) {
+ oncommit = new LUAOnCommit(transaction, commit);
+ oncommit->addScripts(macro->commit_scripts);
+ }
+
+ if(resume != "" || oncommit != NULL) {
TemplateParser tp(env.templatelist.getLatestVersion(commit.templ));
tp.parse();
Template *templ = tp.getTemplate();
-
- session.journal()->addEntry(transaction, commit, resume, templ);
- }
+ session.journal()->addEntry(transaction, commit, resume, templ, oncommit);
+ }
+
i++;
}
@@ -92,6 +107,7 @@ static std::string handleCommits(Transaction &transaction, Environment &env,
static std::string handleRequest(Request &request, Environment &env,
Session &session)
+ throw(NotFoundException)
{
std::string answer;
@@ -321,9 +337,9 @@ std::string handleTransaction(Request &request,
try {
answer += handleCommits(transaction, env, session);
- } catch( std::exception &e ) {
- ERR(server, "Commit error: %s\n", e.what());
- return error_box(xml_encode(e.what()));
+ } catch( LUAScript::Exception &e ) {
+ ERR(server, "Commit error: %s\n", e.msg.c_str());
+ return error_box(xml_encode(e.msg));
}
try {