summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/client.pro2
-rw-r--r--client/macro.cc6
-rw-r--r--client/macro.h5
-rw-r--r--client/macrowindow.cc13
-rw-r--r--client/macrowindow.h6
-rw-r--r--client/mainwindow.cc72
-rw-r--r--client/mainwindow.h8
-rw-r--r--client/netcom.cc82
-rw-r--r--client/netcom.h7
-rw-r--r--client/pracro.cc25
-rw-r--r--client/template.cc103
-rw-r--r--client/template.h57
-rw-r--r--server/src/Makefile.am4
-rw-r--r--server/src/client_connection.cc49
-rw-r--r--server/src/client_connection.h5
-rw-r--r--server/src/courselist.cc76
-rw-r--r--server/src/courselist.h41
-rw-r--r--server/src/courseparser.cc178
-rw-r--r--server/src/courseparser.h68
-rw-r--r--server/src/database.h2
-rw-r--r--server/src/environment.cc3
-rw-r--r--server/src/environment.h2
-rw-r--r--server/src/httpd.cc2
-rw-r--r--server/src/httpd.h8
-rw-r--r--server/src/journal.cc4
-rw-r--r--server/src/luaquerymapper.cc2
-rw-r--r--server/src/pracrodaopgsql.cc6
-rw-r--r--server/src/pracrodaotest.cc6
-rw-r--r--server/src/server.cc2
-rw-r--r--server/src/session.cc14
-rw-r--r--server/src/transaction.h6
-rw-r--r--server/src/transactionhandler.cc364
-rw-r--r--server/src/transactionhandler.h5
-rw-r--r--server/src/transactionparser.cc9
-rw-r--r--server/xml/courses/test.xml1
-rw-r--r--server/xml/macros/test_lineedit.xml2
36 files changed, 969 insertions, 276 deletions
diff --git a/client/client.pro b/client/client.pro
index 852a212..44fc02c 100644
--- a/client/client.pro
+++ b/client/client.pro
@@ -62,6 +62,7 @@ HEADERS += \
messagebox.h \
netcom.h \
resumewidget.h \
+ template.h \
widgets.h \
widgets/common.h \
widgets/widget.h \
@@ -100,6 +101,7 @@ SOURCES += \
messagebox.cc \
netcom.cc \
resumewidget.cc \
+ template.cc \
widgets/common.cc \
widgets/widget.cc \
widgets/label.cc \
diff --git a/client/macro.cc b/client/macro.cc
index dfe464d..320faa3 100644
--- a/client/macro.cc
+++ b/client/macro.cc
@@ -35,8 +35,8 @@
#include "macrodrawer.h"
#include "macrowindow.h"
-Macro::Macro(Entities &e, NetCom &n, QString t, QScrollArea *s)
- : entities(e), netcom(n), templ(t)
+Macro::Macro(Entities &e, NetCom &n, QString c, QString t, QScrollArea *s)
+ : entities(e), netcom(n), course(c), templ(t)
{
window = NULL;
drawer = NULL;
@@ -69,7 +69,7 @@ void Macro::update(QDomNode &node)
drawer = new MacroDrawer(this, elem.attribute("caption", name));
if(window == NULL) {
- window = new MacroWindow(netcom, templ, isstatic, iscompact,
+ window = new MacroWindow(netcom, course, templ, isstatic, iscompact,
scrollarea, drawer);
QFont f = window->font();
diff --git a/client/macro.h b/client/macro.h
index b24b809..0fd6c51 100644
--- a/client/macro.h
+++ b/client/macro.h
@@ -44,7 +44,8 @@ class MacroDrawer;
class Macro : public Entity {
public:
- Macro(Entities &entities, NetCom &netcom, QString templ,
+ Macro(Entities &entities, NetCom &netcom,
+ QString course, QString templ,
QScrollArea *scrollarea);
virtual ~Macro() {}
@@ -77,6 +78,8 @@ private:
QScrollArea *scrollarea;
Entities &entities;
NetCom &netcom;
+
+ QString course;
QString templ;
};
diff --git a/client/macrowindow.cc b/client/macrowindow.cc
index bbfab8e..44f2797 100644
--- a/client/macrowindow.cc
+++ b/client/macrowindow.cc
@@ -46,7 +46,7 @@ extern MainWindow *gmainwindow;
extern QString cpr;
extern QString user;
-MacroWindow::MacroWindow(NetCom &n, QString templ,
+MacroWindow::MacroWindow(NetCom &n, QString course, QString templ,
bool is_static, bool compact,
QScrollArea *scrollarea,
MacroDrawer *d)
@@ -62,8 +62,9 @@ MacroWindow::MacroWindow(NetCom &n, QString templ,
waschanged = false;
+ this->course = course;
this->templ = templ;
-
+
resumewidget = new ResumeWidget(compact);
active = true;
@@ -172,7 +173,7 @@ bool MacroWindow::doCommit()
QVector< Widget* > wlist;
if(mainwidget) wlist = mainwidget->widgetList();
- netcom.send(wlist, templ, macro, version);
+ netcom.send(wlist, course, templ, macro, version);
return true;
} else {
@@ -198,7 +199,7 @@ void MacroWindow::cancel()
void MacroWindow::expandWrapper()
{
if(currentWidget() != resumewidget) return;
- netcom.send(templ, macro);
+ netcom.send(course, templ, macro);
}
void MacroWindow::collapseWrapper()
@@ -206,7 +207,7 @@ void MacroWindow::collapseWrapper()
if(currentWidget() == resumewidget) return;
if(waschanged == false) {
- netcom.send(templ);
+ netcom.send(course, templ);
return;
}
@@ -224,7 +225,7 @@ void MacroWindow::collapseWrapper()
doCommit();
break;
case MessageBox::Close:
- netcom.send(templ);
+ netcom.send(course, templ);
break;
case MessageBox::Cancel:
default:
diff --git a/client/macrowindow.h b/client/macrowindow.h
index f92b4c0..afc144d 100644
--- a/client/macrowindow.h
+++ b/client/macrowindow.h
@@ -41,7 +41,7 @@ class MacroWindow : public Collapser
{
Q_OBJECT
public:
- MacroWindow(NetCom &netcom, QString templ,
+ MacroWindow(NetCom &netcom, QString course, QString templ,
bool is_static, bool compact,
QScrollArea *scrollarea,
MacroDrawer *drawer);
@@ -77,8 +77,10 @@ private:
bool doCommit();
- QString macro;
+ QString course;
QString templ;
+ QString macro;
+
QString version;
Widget *mainwidget;
diff --git a/client/mainwindow.cc b/client/mainwindow.cc
index dfe112f..6bf0543 100644
--- a/client/mainwindow.cc
+++ b/client/mainwindow.cc
@@ -48,6 +48,7 @@
#include "macro.h"
#include "header.h"
+#include "template.h"
#include "debug.h"
@@ -65,8 +66,8 @@ public:
MainWindow *gmainwindow = NULL;
-MainWindow::MainWindow(QString patientid, QString templ, QString host,
- quint16 port, QString user)
+MainWindow::MainWindow(QString patientid, QString course, QString templ,
+ QString host, quint16 port, QString user)
: QMainWindow(0), // Qt::WindowContextHelpButtonHint
netcom(host, port)
{
@@ -94,6 +95,7 @@ MainWindow::MainWindow(QString patientid, QString templ, QString host,
this->patientid = patientid;
this->user = user;
+ this->course = course;
this->templ = templ;
setWindowTitle("Pracro - " + patientid);
@@ -238,6 +240,7 @@ void MainWindow::init()
netcom.patientid = patientid;
netcom.templ = templ;
+ netcom.course = course;
netcom.user = user;
netcom.initConnection();
@@ -285,7 +288,7 @@ void MainWindow::updateMacros(QDomNodeList &nodes)
if(entities.find(j) == entities.end()) {
Entity *e = NULL;
if(elem.tagName() == "macro") {
- e = new Macro(entities, netcom, templ, scrollarea);
+ e = new Macro(entities, netcom, course, templ, scrollarea);
}
if(elem.tagName() == "header") {
e = new Header();
@@ -306,6 +309,49 @@ void MainWindow::updateMacros(QDomNodeList &nodes)
}
}
+void MainWindow::updateTemplates(QDomNodeList &nodes)
+{
+ for(int j = 0; j < nodes.count(); j++) {
+ QDomNode node = nodes.at(j);
+ QDomElement elem = node.toElement();
+
+ if(elem.tagName() == "template") {
+ QString name = elem.attribute("name");
+
+ if(entities.find(j) == entities.end()) {
+ Template *e = new Template(netcom);
+ connect(e, SIGNAL(setTemplate(QString)),
+ this, SLOT(setTemplate(QString)));
+ entities[j] = e;
+ entities[j]->update(node);
+ w->layout()->addWidget(e->widget());
+ } else {
+ entities[j]->update(node);
+ }
+ continue;
+ }
+
+ showError("XML Error", "Expected template tag. Got '" +
+ elem.tagName() + "' tag.");
+ continue;
+
+ }
+}
+
+void MainWindow::setTemplate(QString name)
+{
+ templ = name;
+
+ Entities::iterator i = entities.begin();
+ while(i != entities.end()) {
+ delete i.value()->widget();
+ // delete i.value();
+ i++;
+ }
+
+ entities.clear();
+}
+
void MainWindow::handle(QDomDocument &doc)
{
if(closing) close();
@@ -323,12 +369,12 @@ void MainWindow::handle(QDomDocument &doc)
continue;
}
- if(element.tagName() != "template") {
- showError("XML error", "Outer tag not a template.");
+ if(element.tagName() != "template" && element.tagName() != "course") {
+ showError("XML error", "Outer tag not a template or course.");
continue;
}
- if(element.attribute("name") != templ) {
+ if(element.tagName() == "template" && element.attribute("name") != templ) {
showError("XML error",
"Got template name that didn't match current session.");
continue;
@@ -337,9 +383,17 @@ void MainWindow::handle(QDomDocument &doc)
// Set headers. titles, etc...
updateTemplateHeaders(node);
- // Update macros, header and resumes.
- QDomNodeList macronodes = node.childNodes();
- updateMacros(macronodes);
+ if(element.tagName() == "course") {
+ // Update macros, header and resumes.
+ QDomNodeList templatenodes = node.childNodes();
+ updateTemplates(templatenodes);
+ }
+
+ if(element.tagName() == "template") {
+ // Update macros, header and resumes.
+ QDomNodeList macronodes = node.childNodes();
+ updateMacros(macronodes);
+ }
}
}
diff --git a/client/mainwindow.h b/client/mainwindow.h
index 8449467..c52db58 100644
--- a/client/mainwindow.h
+++ b/client/mainwindow.h
@@ -42,8 +42,8 @@
class MainWindow : public QMainWindow {
Q_OBJECT
public:
- MainWindow(QString patientid, QString templ, QString host, quint16 port,
- QString user);
+ MainWindow(QString patientid, QString course, QString templ,
+ QString host, quint16 port, QString user);
~MainWindow();
void closeEvent(QCloseEvent *event);
@@ -58,12 +58,16 @@ public slots:
void showError(QString title, QString text);
bool hasOpen(void *me);
+ void setTemplate(QString name);
private:
+ void updateTemplates(QDomNodeList &nodes);
void updateMacros(QDomNodeList &nodes);
void updateTemplateHeaders(QDomNode &templatenode);
+ QString course;
QString templ;
+
NetCom netcom;
QString patientid;
diff --git a/client/netcom.cc b/client/netcom.cc
index 7873c2b..9c755b5 100644
--- a/client/netcom.cc
+++ b/client/netcom.cc
@@ -87,85 +87,116 @@ void NetCom::replyFinished(QNetworkReply *reply)
}
}
-void NetCom::makeTransfer(QDomDocument &doc, session_state_t state)
+void NetCom::makeTransfer(QByteArray body, session_state_t state, QString uri)
{
- DEBUG(netcom, "Making transfer:\n%s", doc.toString().toStdString().c_str());
+ // Use '/course/template/' uri if empty.
+ if(uri == "") {
+ uri = "/";
+ if(course != "") {
+ uri += course + "/";
+ if(templ != "") {
+ uri += templ + "/";
+ }
+ }
+ }
+
+ DEBUG(netcom, "Making transfer:\n%s", QString(body).toStdString().c_str());
LOG(netcom, "SESSION ID: %s\n", sessionid.toStdString().c_str());
request.setRawHeader("User-Agent", "Pracro Client v"VERSION);
-
+ /*
if(sessionid != "") {
request.setRawHeader("SessionID", sessionid.toStdString().c_str());
} else {
request.setRawHeader("SessionPatientID", patientid.toStdString().c_str());
request.setRawHeader("SessionTemplate", templ.toStdString().c_str());
}
+ */
+
+ QUrl url;
+ url.setHost(request.url().host());
+ url.setPort(request.url().port());
+ url.setScheme(request.url().scheme());
switch(state) {
case ::commit:
- request.setRawHeader("SessionCommit", "yes");
+ // request.setRawHeader("SessionCommit", "yes");
+ url.addQueryItem("statechange", "commit");
break;
case ::discard:
- request.setRawHeader("SessionDiscard", "yes");
+ // request.setRawHeader("SessionDiscard", "yes");
+ url.addQueryItem("statechange", "discard");
break;
case ::nocommit:
- request.setRawHeader("SessionNoCommit", "yes");
+ // request.setRawHeader("SessionNoCommit", "yes");
+ url.addQueryItem("statechange", "nocommit");
break;
default:
case ::none:
break;
}
- manager->post(request, doc.toByteArray());
+ url.setPath(uri);
+ if(sessionid != "") url.addQueryItem("sessionid", sessionid);
+ if(patientid != "") url.addQueryItem("patientid", patientid);
+ request.setUrl(url);
+
+ manager->post(request, body);
}
void NetCom::initConnection()
{
- send(templ); // Initialise by sending a template-only request.
+ send(course, templ); // Initialise by sending a template-only request.
}
void NetCom::commit()
{
- QDomDocument doc;
- makeTransfer(doc, ::commit);
+ makeTransfer("", ::commit);
}
void NetCom::nocommit()
{
- QDomDocument doc;
- makeTransfer(doc, ::nocommit);
+ makeTransfer("", ::nocommit);
}
void NetCom::discard()
{
- QDomDocument doc;
- makeTransfer(doc, ::discard);
+ makeTransfer("", ::discard);
}
-void NetCom::send(QString templ, QString macro)
+void NetCom::send(QString course, QString templ, QString macro)
{
- QDomDocument doc;
-
+ /*
QDomProcessingInstruction header =
doc.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
doc.appendChild(header);
QDomElement pracro_elem = doc.createElement("pracro");
pracro_elem.setAttribute("version", "1.0");
- pracro_elem.setAttribute("cpr", patientid);
+ pracro_elem.setAttribute("patientid", patientid);
pracro_elem.setAttribute("user", user);
doc.appendChild(pracro_elem);
QDomElement request_elem = doc.createElement("request");
- request_elem.setAttribute("template", templ);
+ request_elem.setAttribute("course", course);
+ if(templ != "") request_elem.setAttribute("template", templ);
if(macro != "") request_elem.setAttribute("macro", macro);
pracro_elem.appendChild(request_elem);
+ */
+ QString uri = "/";
+ if(course != "") {
+ uri += course + "/";
+ if(templ != "") {
+ uri += templ + "/";
+ if(macro != "") uri += macro + "/";
+ }
+ }
- makeTransfer(doc);
+ makeTransfer("", ::none, uri);
}
-void NetCom::send(QVector< Widget* > widgets, QString templ,
+void NetCom::send(QVector< Widget* > widgets, QString course, QString templ,
QString macro, QString version)
{
QDomDocument doc;
@@ -176,11 +207,12 @@ void NetCom::send(QVector< Widget* > widgets, QString templ,
QDomElement pracro_elem = doc.createElement("pracro");
pracro_elem.setAttribute("version", "1.0");
- pracro_elem.setAttribute("cpr", patientid);
+ pracro_elem.setAttribute("patientid", patientid);
pracro_elem.setAttribute("user", user);
doc.appendChild(pracro_elem);
QDomElement commit_elem = doc.createElement("commit");
+ commit_elem.setAttribute("course", course);
commit_elem.setAttribute("template", templ);
commit_elem.setAttribute("macro", macro);
commit_elem.setAttribute("version", version);
@@ -204,10 +236,10 @@ void NetCom::send(QVector< Widget* > widgets, QString templ,
}
i++;
}
-
+ /*
QDomElement request_elem = doc.createElement("request");
request_elem.setAttribute("template", templ);
pracro_elem.appendChild(request_elem);
-
- makeTransfer(doc);
+ */
+ makeTransfer(doc.toByteArray(), ::none, "");
}
diff --git a/client/netcom.h b/client/netcom.h
index 46d40d0..332f4bd 100644
--- a/client/netcom.h
+++ b/client/netcom.h
@@ -54,8 +54,8 @@ public:
NetCom(QString host, quint16 port);
~NetCom();
- void send(QString templ, QString macro = "");
- void send(QVector< Widget* > widgets, QString templ,
+ void send(QString course, QString templ = "", QString macro = "");
+ void send(QVector< Widget* > widgets, QString course, QString templ,
QString macro, QString version);
void initConnection();
@@ -66,6 +66,7 @@ public:
QString sessionid;
QString user;
QString patientid;
+ QString course;
QString templ;
signals:
@@ -84,7 +85,7 @@ private:
QMap<QNetworkReply *, bool> finished;
- void makeTransfer(QDomDocument &dom, session_state_t state = none);
+ void makeTransfer(QByteArray body, session_state_t state, QString uri = "");
};
#endif/*__PRACRO_NETCOM_H__*/
diff --git a/client/pracro.cc b/client/pracro.cc
index d281347..57a8da7 100644
--- a/client/pracro.cc
+++ b/client/pracro.cc
@@ -41,19 +41,15 @@
#include "debug.h"
-#define CPR_DEFAULT ""
-#define MACRO_DEFAULT ""
-#define TEMPLATE_DEFAULT ""
#define USER_DEFAULT "testuser"
#define CONFIG_DEFAULT "pracro.ini"
-QString cpr = CPR_DEFAULT;
+QString cpr;
QString user = USER_DEFAULT;
QString config = CONFIG_DEFAULT;
QString host;
quint16 port;
-QWidget *viewer = NULL;
QFont *fixedfont = NULL;
#ifndef TESTING
@@ -65,10 +61,9 @@ static void print_usage()
printf("\n");
printf(" -h, --help Displays this help text.\n");
printf(" -t, --template TEMPLATE Requests template TEMPLATE from the Pracro \n"
- " Server, defaults to \""TEMPLATE_DEFAULT"\".\n");
+ " Server.\n");
printf(" -C --course COURSE Lists templates in COURSE.\n");
- printf(" -P, --patient PATIENTID Defines the patientid for use with the macro,\n"
- " defaults to \""CPR_DEFAULT"\".\n");
+ printf(" -P, --patient PATIENTID Defines the patientid for use with the macro.\n");
printf(" -c, --config FILE The configfile to use. Default is \""CONFIG_DEFAULT"\"\n");
printf(" -u, -U, --user USER Defines the requesting user(not the patient),\n"
" defaults to \""USER_DEFAULT"\"\n");
@@ -96,8 +91,8 @@ int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- QString macro = MACRO_DEFAULT;
- QString templ = TEMPLATE_DEFAULT;
+ QString macro;
+ QString templ;
QString course;
QString templs;
@@ -168,7 +163,8 @@ int main(int argc, char *argv[])
QFont f = fontdb.font("Bitstream Vera Sans Mono", "", 8);
fixedfont = &f;
- if(cpr == CPR_DEFAULT || templ == TEMPLATE_DEFAULT) {
+ /*
+ if(cpr == "" || templ == "") {
LauncherWindow lwnd(argv[0], cpr, templ);
if(lwnd.exec() == QDialog::Accepted && lwnd.getCpr() != "") {
cpr = lwnd.getCpr();
@@ -177,13 +173,12 @@ int main(int argc, char *argv[])
return 1;
}
}
-
- MainWindow mainwindow(cpr, templ, host, port, user);
+ */
+
+ MainWindow mainwindow(cpr, course, templ, host, port, user);
mainwindow.show();
return app.exec();
}
-
-
#endif/*TESTING*/
diff --git a/client/template.cc b/client/template.cc
new file mode 100644
index 0000000..4ffd4ac
--- /dev/null
+++ b/client/template.cc
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * template.cc
+ *
+ * Fri Jul 1 14:43:46 CEST 2011
+ * Copyright 2011 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 "template.h"
+
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QGroupBox>
+
+Template::Template(NetCom &n)
+ : netcom(n)
+{
+ wdg = new QGroupBox();
+
+ QVBoxLayout *l = new QVBoxLayout();
+ wdg->setLayout(l);
+ wdg->setContentsMargins(50, 50, 50, 50);
+
+ l->addStretch();
+
+ templ = new QLabel();
+ templ->setAlignment(Qt::AlignHCenter);
+ QFont font = templ->font();
+ font.setBold(true);
+ font.setPointSize(font.pointSize() * 1.5);
+ templ->setFont(font);
+ l->addWidget(templ);
+
+ l->addStretch();
+
+ QPushButton *btn = new QPushButton("Open");
+ l->addWidget(btn);
+ connect(btn, SIGNAL(clicked()), this, SLOT(open()));
+
+ l->addStretch();
+
+}
+
+const char *Template::type()
+{
+ return "template";
+}
+
+void Template::update(QDomNode &node)
+{
+ QDomElement elem = node.toElement();
+ templ->setText(elem.attribute("title") + " (" + elem.attribute("name") + ")");
+ name = elem.attribute("name");
+}
+
+void Template::open()
+{
+ emit setTemplate(name);
+ netcom.templ = name;
+ netcom.send(netcom.course, name, "");
+}
+
+QWidget *Template::widget()
+{
+ return wdg;
+}
+
+#ifdef TEST_TEMPLATE
+//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_TEMPLATE*/
diff --git a/client/template.h b/client/template.h
new file mode 100644
index 0000000..31b635b
--- /dev/null
+++ b/client/template.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * template.h
+ *
+ * Fri Jul 1 14:43:46 CEST 2011
+ * Copyright 2011 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_TEMPLATE_H__
+#define __PRACRO_TEMPLATE_H__
+
+#include <QLabel>
+
+#include "entity.h"
+#include "netcom.h"
+
+class Template : public QObject, public Entity {
+Q_OBJECT
+public:
+ Template(NetCom &netcom);
+ const char *type();
+ void update(QDomNode &node);
+ QWidget *widget();
+
+public slots:
+ void open();
+
+signals:
+ void setTemplate(QString name);
+
+private:
+ QString name;
+ QLabel *templ;
+ QWidget *wdg;
+ NetCom &netcom;
+};
+
+#endif/*__PRACRO_TEMPLATE_H__*/
diff --git a/server/src/Makefile.am b/server/src/Makefile.am
index 2697fed..0bdfddb 100644
--- a/server/src/Makefile.am
+++ b/server/src/Makefile.am
@@ -21,6 +21,8 @@ pracrod_SOURCES = \
configurationparser.cc \
connection.cc \
connectionpool.cc \
+ courseparser.cc \
+ courselist.cc \
daemon.cc \
database.cc \
debug.cc \
@@ -79,6 +81,8 @@ EXTRA_DIST = \
configurationparser.h \
connection.h \
connectionpool.h \
+ courseparser.h \
+ courselist.h \
daemon.h \
database.h \
dbtypes.h \
diff --git a/server/src/client_connection.cc b/server/src/client_connection.cc
index 9a1ac0f..1ec7e7c 100644
--- a/server/src/client_connection.cc
+++ b/server/src/client_connection.cc
@@ -44,21 +44,42 @@ static std::string error_box(std::string message)
static bool did_commit = false;
#endif
-ClientConnection::ClientConnection(Environment &e, headers_t &headers)
+ClientConnection::ClientConnection(Environment &e, headers_t &headers,
+ headers_t args, std::string uri)
: env(e), parser(&transaction)
{
DEBUG(connection, "[%p] CREATE\n", this);
- if(headers.contains("SessionID"))
- sessionid = headers["SessionID"];
- if(headers.contains("SessionPatientID"))
- patientid = headers["SessionPatientID"];
- if(headers.contains("SessionTemplate"))
- templ = headers["SessionTemplate"];
-
- docommit = headers.contains("SessionCommit");
- donocommit = headers.contains("SessionNoCommit");
- dodiscard = headers.contains("SessionDiscard");
+ size_t i = 0;
+ std::string *tar[3];
+ tar[0] = &request.course;
+ tar[1] = &request.templ;
+ tar[2] = &request.macro;
+ int p = -1;
+ while(i < uri.size() && p < 3) {
+ if(uri[i] == '/') {
+ p++;
+ } else if(p > -1) {
+ *(tar[p]) += uri[i];
+ } else {
+ ERR(connection, "Malformed URI. Missing beginning '/'!");
+ }
+ i++;
+ }
+
+ DEBUG(connection, "Course: %s, Template: %s, Macro: %s\n",
+ request.course.c_str(),
+ request.templ.c_str(),
+ request.macro.c_str());
+
+ templ = request.templ;
+
+ request.patientid = patientid = args.lookup("patientid");
+ sessionid = args.lookup("sessionid");
+
+ docommit = args.lookup("statechange") == "commit";
+ donocommit = args.lookup("statechange") == "nocommit";
+ dodiscard = args.lookup("statechange") == "discard";
#ifdef TEST_CLIENT_CONNECTION
did_commit = false;
@@ -151,7 +172,7 @@ bool ClientConnection::handle(const char *data, size_t size)
try {
- if(!data || !size) {
+ if((!data || !size) && (docommit || donocommit || dodiscard)) {
parser_complete = true;
commit(session);
nocommit(session);
@@ -159,12 +180,12 @@ bool ClientConnection::handle(const char *data, size_t size)
return true;
}
- if(parser.parse(data, size)) {
+ if(size == 0 || parser.parse(data, size)) {
parser_complete = true;
{
SessionAutolock lock(*session);
- response = handleTransaction(transaction, env, *session);
+ response = handleTransaction(request, transaction, env, *session);
}
commit(session);
diff --git a/server/src/client_connection.h b/server/src/client_connection.h
index a509221..b811b7f 100644
--- a/server/src/client_connection.h
+++ b/server/src/client_connection.h
@@ -40,7 +40,8 @@ class Session;
class ClientConnection : public Connection {
public:
- ClientConnection(Environment &e, headers_t &headers);
+ ClientConnection(Environment &e, headers_t &headers,
+ headers_t args, std::string uri);
~ClientConnection();
bool handle(const char *data, size_t size);
@@ -67,6 +68,8 @@ private:
bool docommit;
bool dodiscard;
bool donocommit;
+
+ Request request;
};
#endif/*__PRACRO_CLIENT_CONNECTION_H__*/
diff --git a/server/src/courselist.cc b/server/src/courselist.cc
new file mode 100644
index 0000000..b6d2b29
--- /dev/null
+++ b/server/src/courselist.cc
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * courselist.cc
+ *
+ * Thu Jul 7 10:25:06 CEST 2011
+ * Copyright 2011 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 "courselist.h"
+
+#include "courseparser.h"
+
+#include "debug.h"
+
+CourseList::CourseList(std::string path)
+ : EntityList(path, "course")
+{
+ rescan();
+}
+
+void CourseList::addFile(std::string file)
+{
+ if(file.substr(file.size() - 4) != ".xml") {
+ DEBUG(courselist, "Skipping file: %s\n", file.c_str());
+ return;
+ }
+
+ DEBUG(courselist, "Adding file: %s\n", file.c_str());
+ CourseParser parser(file);
+ try {
+ parser.parse();
+ Course *templ = parser.getCourse();
+ insertEntity(templ->name,
+ templ->version,
+ file);
+ } catch(Exception &e) {
+ WARN(courselist, "Skipping %s: %s\n", file.c_str(), e.what());
+ }
+}
+
+#ifdef TEST_COURSELIST
+//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_COURSELIST*/
diff --git a/server/src/courselist.h b/server/src/courselist.h
new file mode 100644
index 0000000..12e5fba
--- /dev/null
+++ b/server/src/courselist.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * courselist.h
+ *
+ * Thu Jul 7 10:25:06 CEST 2011
+ * Copyright 2011 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_COURSELIST_H__
+#define __PRACRO_COURSELIST_H__
+
+#include "entitylist.h"
+
+class CourseList : public EntityList {
+public:
+ CourseList(std::string path);
+
+private:
+ void addFile(std::string file);
+};
+
+#endif/*__PRACRO_COURSELIST_H__*/
diff --git a/server/src/courseparser.cc b/server/src/courseparser.cc
new file mode 100644
index 0000000..af78ca1
--- /dev/null
+++ b/server/src/courseparser.cc
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * courseparser.cc
+ *
+ * Tue Jun 28 10:52:41 CEST 2011
+ * Copyright 2011 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 "courseparser.h"
+
+// For assert
+#include <assert.h>
+
+// For open and friends
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+// For vprintf and friends
+#include <stdarg.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <stdio.h>
+
+#include "configuration.h"
+#include "debug.h"
+#include "exception.h"
+
+void CourseParser::error(const char* fmt, ...)
+{
+ va_list argp;
+ char *p;
+ va_start(argp, fmt);
+ vasprintf(&p, fmt, argp);
+ va_end(argp);
+ ERR_LOG(course, "Error in CourseParser: %s\n", p);
+ throw Exception(std::string("Error in CourseParser: ") + p);
+ free(p);
+}
+
+CourseParser::CourseParser(std::string coursefile)
+{
+ state = C_UNDEFINED;
+ c = new Course();
+
+ file = coursefile;
+
+ DEBUG(course, "Using course file: %s\n", file.c_str());
+
+ fd = open(file.c_str(), O_RDONLY);
+ if(fd == -1) error("Could not open file %s", file.c_str());
+}
+
+CourseParser::~CourseParser()
+{
+ if(fd != -1) close(fd);
+ delete c;
+}
+
+void CourseParser::characterData(std::string &data)
+{
+}
+
+void CourseParser::startTag(std::string name, attributes_t &attr)
+{
+ if(name == "course") {
+ if(state != C_UNDEFINED) error("Course found not a root node.");
+ state = C_COURSE;
+
+ assert(c); // A Course has not yet been allocated, cannot create course!
+
+ if(attr.find("name") != attr.end()) c->name = attr["name"];
+ if(attr.find("title") != attr.end()) c->title = attr["title"];
+ if(attr.find("version") != attr.end()) c->version = attr["version"];
+
+ return;
+ }
+
+ if(name == "template") {
+ if(state != C_COURSE) error("template found outside course.");
+ state = C_TEMPLATE;
+
+ assert(c); // A Course has not yet been allocated, cannot create template!
+
+ Template t;
+
+ if(attr.find("name") != attr.end()) t.name = attr["name"];
+ if(attr.find("title") != attr.end()) t.title = attr["title"];
+
+ c->templates.push_back(t);
+
+ return;
+ }
+
+ error("Unknown/illegal tag: %s", name.c_str());
+}
+
+void CourseParser::endTag(std::string name)
+{
+ if(name == "course") state = C_UNDEFINED;
+ if(name == "template") state = C_COURSE;
+}
+
+int CourseParser::readData(char *data, size_t size)
+{
+ if(fd == -1) {
+ ERR_LOG(course, "Invalid file descriptor.\n");
+ return 0;
+ }
+ ssize_t r = read(fd, data, size);
+ if(r == -1) {
+ ERR_LOG(course, "Could not read...%s\n", strerror(errno));
+ return 0;
+ }
+ return r;
+}
+
+void CourseParser::parseError(const char *buf, size_t len, std::string error,
+ int lineno)
+{
+ fprintf(stderr, "CourseParser[%s] error at line %d: %s\n",
+ file.c_str(), lineno, error.c_str());
+ fprintf(stderr, "\tBuffer %u bytes: [", len);
+ if(fwrite(buf, len, 1, stderr) != len) {}
+ fprintf(stderr, "]\n");
+ fflush(stderr);
+
+ char *slineno;
+ if(asprintf(&slineno, " at line %d\n", lineno) != -1) {
+ throw Exception(error + slineno);
+ free(slineno);
+ }
+}
+
+Course *CourseParser::getCourse()
+{
+ return c;
+}
+
+#ifdef TEST_COURSEPARSER
+//deps: saxparser.cc debug.cc log.cc exception.cc
+//cflags: -I.. $(EXPAT_CFLAGS)
+//libs: $(EXPAT_LIBS)
+#include "test.h"
+
+TEST_BEGIN;
+
+CourseParser p("../xml/courses/test.xml");
+p.parse();
+
+Course *c = p.getCourse();
+TEST_NOTEQUAL(c, NULL, "Got one?");
+
+TEST_END;
+
+#endif/*TEST_COURSEPARSER*/
diff --git a/server/src/courseparser.h b/server/src/courseparser.h
new file mode 100644
index 0000000..7ab4c05
--- /dev/null
+++ b/server/src/courseparser.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * courseparser.h
+ *
+ * Tue Jun 28 10:52:41 CEST 2011
+ * Copyright 2011 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_COURSEPARSER_H__
+#define __PRACRO_COURSEPARSER_H__
+
+#include "saxparser.h"
+#include "template.h"
+
+typedef enum {
+ C_UNDEFINED,
+ C_TEMPLATE,
+ C_COURSE
+} CourseParserState;
+
+class CourseParser : public SAXParser {
+public:
+ CourseParser(std::string course);
+ ~CourseParser();
+
+ void characterData(std::string &data);
+ void startTag(std::string name, attributes_t &attr);
+ void endTag(std::string name);
+ void parseError(const char *buf, size_t len, std::string error, int lineno);
+
+ Course *getCourse();
+
+protected:
+ int readData(char *data, size_t size);
+
+private:
+ int fd;
+
+ std::string file;
+
+ // Parser state data
+ CourseParserState state;
+ Course *c;
+
+ // Error callback function.
+ void error(const char* fmt, ...);
+};
+
+#endif/*__PRACRO_COURSEPARSER_H__*/
diff --git a/server/src/database.h b/server/src/database.h
index 27169fe..0c28e60 100644
--- a/server/src/database.h
+++ b/server/src/database.h
@@ -66,7 +66,7 @@ public:
mutex.lock();
DEBUG(db, "%s, %s, %s,...\n",
- transaction.user.c_str(), transaction.cpr.c_str(),
+ transaction.user.c_str(), transaction.patientid.c_str(),
macro.name.c_str());
dao->commitTransaction(sessionid, transaction, commit, macro, now);
mutex.unlock();
diff --git a/server/src/environment.cc b/server/src/environment.cc
index da475ce..d232174 100644
--- a/server/src/environment.cc
+++ b/server/src/environment.cc
@@ -33,7 +33,8 @@
Environment::Environment()
: sessions(this),
macrolist(Conf::xml_basedir + "/macros"),
- templatelist(Conf::xml_basedir + "/templates")
+ templatelist(Conf::xml_basedir + "/templates"),
+ courselist(Conf::xml_basedir + "/courses")
{
for(int i = 0; i < Conf::database_poolsize; i++) {
diff --git a/server/src/environment.h b/server/src/environment.h
index a7b9677..7f34230 100644
--- a/server/src/environment.h
+++ b/server/src/environment.h
@@ -32,6 +32,7 @@
#include "artefact.h"
#include "connectionpool.h"
#include "session.h"
+#include "courselist.h"
#include "templatelist.h"
#include "macrolist.h"
@@ -45,6 +46,7 @@ public:
Sessions sessions;
MacroList macrolist;
TemplateList templatelist;
+ CourseList courselist;
};
#endif/*__PRACRO_ENVIRONMENT_H__*/
diff --git a/server/src/httpd.cc b/server/src/httpd.cc
index 1d121b5..f7ad7f4 100644
--- a/server/src/httpd.cc
+++ b/server/src/httpd.cc
@@ -76,6 +76,8 @@ static int request_handler(void *cls,
headers_t headers;
headers_t getargs;
+ DEBUG(httpd, "URI: %s\n", url);
+
MHD_get_connection_values(con, MHD_HEADER_KIND, &hdit, &headers);
int n = MHD_get_connection_values(con, MHD_GET_ARGUMENT_KIND, &hdit, &getargs);
DEBUG(httpd, "Num args: %d\n", n);
diff --git a/server/src/httpd.h b/server/src/httpd.h
index 455fa35..24646fa 100644
--- a/server/src/httpd.h
+++ b/server/src/httpd.h
@@ -35,7 +35,13 @@ class headers_t : public std::map< std::string, std::string > {
public:
bool contains(std::string name) {
return find(name) != end();
- }
+ }
+
+ std::string lookup(std::string key, std::string defval = "")
+ {
+ if(contains(key)) return (*this)[key];
+ return defval;
+ }
};
struct MHD_Daemon;
diff --git a/server/src/journal.cc b/server/src/journal.cc
index c38246f..fc4203c 100644
--- a/server/src/journal.cc
+++ b/server/src/journal.cc
@@ -55,7 +55,7 @@ void Journal::addEntry(Transaction &transaction, Commit &commit,
if(entrylist.size() == 0) {
//if(user() == "") setUser(transaction.user);
- if(patientID() == "")setPatientID(transaction.cpr);
+ if(patientID() == "") setPatientID(transaction.patientid);
}
DEBUG(journal, "addEntry: template(%s)\n",
@@ -64,7 +64,7 @@ void Journal::addEntry(Transaction &transaction, Commit &commit,
// Test if the username or the cpr has changed...
// if so, commit and clear the list.
#if 0 // no - it breaks things...
- if(user() != transaction.user || patientID() != transaction.cpr) {
+ if(user() != transaction.user || patientID() != transaction.patientid) {
this->commit();
entrylist.clear();
}
diff --git a/server/src/luaquerymapper.cc b/server/src/luaquerymapper.cc
index 56b7c1b..27dc21f 100644
--- a/server/src/luaquerymapper.cc
+++ b/server/src/luaquerymapper.cc
@@ -78,7 +78,7 @@ static void loadResult(lua_State *L, QueryResult &res,
while(lua_gettop(L)) lua_pop(L, 1);
- printf("< %d\n", lua_gettop(L)); fflush(stdout);
+ // printf("< %d\n", lua_gettop(L)); fflush(stdout);
std::map< std::string, QueryResult >::iterator g = res.groups.begin();
while(g != res.groups.end()) {
diff --git a/server/src/pracrodaopgsql.cc b/server/src/pracrodaopgsql.cc
index c1a0c93..f9a773f 100644
--- a/server/src/pracrodaopgsql.cc
+++ b/server/src/pracrodaopgsql.cc
@@ -107,7 +107,7 @@ void PracroDAOPgsql::commitTransaction(std::string sessionid,
time_t now)
{
DEBUG(db, "commitTransaction (%s, %s, %s, <%u fields>, %ld)\n",
- transaction.user.c_str(), transaction.cpr.c_str(),
+ transaction.user.c_str(), transaction.patientid.c_str(),
_macro.name.c_str(),
commit.fields.size(), now);
@@ -132,7 +132,7 @@ void PracroDAOPgsql::commitTransaction(std::string sessionid,
if(!R.size()) {
ts = "INSERT INTO commits (patientid, template, version,"
" \"timestamp\", uid, status) VALUES ("
- " '" + W.esc(transaction.cpr) + "', "
+ " '" + W.esc(transaction.patientid) + "', "
" '" + W.esc(commit.templ) + "', "
" '" + "1.0" + "', "
" '" + W.esc(timestamp.str()) + "', "
@@ -606,7 +606,7 @@ std::string sid2 = db.newSessionId();
TEST_NOTEQUAL_STR(sid1, sid2, "Do not produce the same uid each time.");
Transaction transaction;
-transaction.cpr = PATIENTID;
+transaction.patientid = PATIENTID;
transaction.user = "me";
Commit commit;
diff --git a/server/src/pracrodaotest.cc b/server/src/pracrodaotest.cc
index 532877b..705d4b8 100644
--- a/server/src/pracrodaotest.cc
+++ b/server/src/pracrodaotest.cc
@@ -71,7 +71,7 @@ void PracroDAOTest::commitTransaction(std::string sessionid,
{
DEBUG(db, "(%s, %s, %s, <%u fields>, %ld)\n",
transaction.user.c_str(),
- transaction.cpr.c_str(),
+ transaction.patientid.c_str(),
_macro.name.c_str(),
commit.fields.size(),
now);
@@ -86,7 +86,7 @@ void PracroDAOTest::commitTransaction(std::string sessionid,
if(ci == data.commits.end()) {
DEBUG(db, "Create new commit: %s\n", sessionid.c_str());
dbrow_t c;
- c["patientid"] = transaction.cpr;
+ c["patientid"] = transaction.patientid;
c["template"] = commit.templ;
c["version"] = "1.0";
c["timestamp"] = timestamp.str();
@@ -378,7 +378,7 @@ std::string sid2 = db.newSessionId();
TEST_NOTEQUAL_STR(sid1, sid2, "Do not produce the same uid each time.");
Transaction transaction;
-transaction.cpr = PATIENTID;
+transaction.patientid = PATIENTID;
transaction.user = "me";
Commit commit;
diff --git a/server/src/server.cc b/server/src/server.cc
index 9046594..e4d6474 100644
--- a/server/src/server.cc
+++ b/server/src/server.cc
@@ -63,7 +63,7 @@ public:
headers["User-Agent"].find("Pracro") == std::string::npos) { // Admin
connection = new AdminConnection(env, getargs, url);
} else { // Pracro client
- connection = new ClientConnection(env, headers);
+ connection = new ClientConnection(env, headers, getargs, url);
}
return connection;
diff --git a/server/src/session.cc b/server/src/session.cc
index 31c9fe8..e236416 100644
--- a/server/src/session.cc
+++ b/server/src/session.cc
@@ -55,11 +55,16 @@ Session::Session(Environment *e,
patientid = pid;
templ = t;
+ DEBUG(session, "[%p] new Session(sessionid: '%s', patientid: '%s',"
+ " template: '%s')\n", this, sid.c_str(), pid.c_str(), t.c_str());
+
isreadonly = true;
}
Session::~Session()
{
+ DEBUG(session, "[%p] delete Session(sessionid: '%s')\n", this,
+ sessionid.c_str());
if(_journal) delete _journal;
}
@@ -87,6 +92,9 @@ void Session::unlock()
void Session::commitMacro(Transaction &transaction, Commit &commit,
Macro &macro)
{
+ DEBUG(session, "[%p] commitMacro(sessionid: '%s')\n", this,
+ sessionid.c_str());
+
AutoBorrower<Database*> borrower(env->dbpool);
Database *db = borrower.get();
db->commitTransaction(transaction, commit, macro, id());
@@ -115,6 +123,8 @@ void Session::setIdle(bool idle)
void Session::commit()
{
+ DEBUG(session, "[%p] commit(sessionid: '%s')\n", this, sessionid.c_str());
+
if(_journal != NULL) {
_journal->commit();
delete _journal;
@@ -129,6 +139,8 @@ void Session::commit()
void Session::nocommit()
{
+ DEBUG(session, "[%p] nocommit(sessionid: '%s')\n", this, sessionid.c_str());
+
if(isreadonly == false) {
AutoBorrower<Database*> borrower(env->dbpool);
Database *db = borrower.get();
@@ -138,6 +150,8 @@ void Session::nocommit()
void Session::discard()
{
+ DEBUG(session, "[%p] discard(sessionid: '%s')\n", this, sessionid.c_str());
+
if(_journal) {
delete _journal;
_journal = NULL;
diff --git a/server/src/transaction.h b/server/src/transaction.h
index 2cca49c..54e283b 100644
--- a/server/src/transaction.h
+++ b/server/src/transaction.h
@@ -35,6 +35,9 @@ class Request {
public:
std::string macro;
std::string templ;
+ std::string course;
+
+ std::string patientid;
};
typedef std::vector< Request > Requests;
@@ -52,10 +55,9 @@ typedef std::vector< Commit > Commits;
class Transaction {
public:
std::string user;
- std::string cpr;
+ std::string patientid;
std::string version;
- Requests requests;
Commits commits;
};
diff --git a/server/src/transactionhandler.cc b/server/src/transactionhandler.cc
index 4b4e7ca..0821cef 100644
--- a/server/src/transactionhandler.cc
+++ b/server/src/transactionhandler.cc
@@ -30,6 +30,8 @@
#include "macroparser.h"
#include "resumeparser.h"
#include "templateparser.h"
+#include "templateheaderparser.h"
+#include "courseparser.h"
#include "configuration.h"
#include "luaquerymapper.h"
#include "queryhandlerpentominos.h"
@@ -83,206 +85,228 @@ static std::string handleCommits(Transaction &transaction, Environment &env,
return answer;
}
-static std::string handleRequest(Transaction &transaction, Environment &env,
+static std::string handleRequest(Request &request, Environment &env,
Session &session)
{
std::string answer;
- if(transaction.requests.size() > 0) {
+ if(request.course == "" && request.templ == "" && request.macro == "")
+ return "";
- AutoBorrower<Database*> borrower(env.dbpool);
- Database *db = borrower.get();
- // Database *db = session.database();
+ if(request.course != "" && request.templ == "" && request.macro == "") {
+ CourseParser cp(env.courselist.getLatestVersion(request.course));
+ cp.parse();
+ Course *course = cp.getCourse();
+ answer += " <course name=\"" + course->name + "\" title=\"" +
+ course->title + "\">\n";
- Requests::iterator i = transaction.requests.begin();
- while(i != transaction.requests.end()) {
- Request &request = *i;
+ std::vector< Template >::iterator ti = course->templates.begin();
+ while(ti != course->templates.end()) {
+ std::string tname = ti->name;
- DEBUG(server, "Handling request - macro: %s, template: %s\n",
- request.macro.c_str(), request.templ.c_str());
-
- // Read and parse the template file.
- TemplateParser tp(env.templatelist.getLatestVersion(request.templ));
+ TemplateHeaderParser tp(env.templatelist.getLatestVersion(tname));
tp.parse();
-
Template *templ = tp.getTemplate();
-
- answer += " <template name=\"" + templ->name + "\" title=\"" +
- templ->title + "\">\n";
-
- bool foundmacro = false;
-
- // Generate the macro and return it to the client
- std::vector< Macro >::iterator mi2 = templ->macros.begin();
- while(mi2 != templ->macros.end()) {
- Macro &macro = (*mi2);
- if(macro.isHeader) {
- answer += " <header caption=\"" + macro.caption + "\"/>\n";
- mi2++;
- continue;
- }
-
- size_t oldest = time(NULL) - Conf::db_max_ttl;
- if(macro.ttl != "") oldest = time(NULL) - atoi(macro.ttl.c_str());
-
- bool completed =
- db->checkMacro(transaction.cpr, macro.name, session.id(), oldest);
+ answer += " <template name=\"" + templ->name + "\" title=\"" +
+ templ->title + "\"/>\n";
- answer += " <macro uid=\"42\" completed=";
- if(completed) answer += "\"true\"";
- else answer += "\"false\"";
+ ti++;
+ }
+
+ answer += " </course>\n";
- attributes_t attr;
- attr["name"] = macro.name;
- attr["version"] = macro.version;
- if(macro.caption != "") attr["caption"] = macro.caption;
- if(macro.requires != "") attr["requires"] = macro.requires;
- attr["static"] = macro.isStatic?"true":"false";
- attr["compact"] = macro.isCompact?"true":"false";
- attr["important"] = macro.isImportant?"true":"false";
+ return answer;
+ }
- attributes_t::iterator ai = attr.begin();
- while(ai != attr.end()) {
- std::string name = ai->first;
- std::string value = ai->second;
- answer += " "+name+"=\"" + value + "\"";
- ai++;
+ AutoBorrower<Database*> borrower(env.dbpool);
+ Database *db = borrower.get();
+ // Database *db = session.database();
+
+ DEBUG(server, "Handling request - macro: %s, template: %s\n",
+ request.macro.c_str(), request.templ.c_str());
+
+ // Read and parse the template file.
+ TemplateParser tp(env.templatelist.getLatestVersion(request.templ));
+ tp.parse();
+
+ Template *templ = tp.getTemplate();
+
+ answer += " <template name=\"" + templ->name + "\" title=\"" +
+ templ->title + "\">\n";
+
+ bool foundmacro = false;
+
+ // Generate the macro and return it to the client
+ std::vector< Macro >::iterator mi2 = templ->macros.begin();
+ while(mi2 != templ->macros.end()) {
+ Macro &macro = (*mi2);
+
+ if(macro.isHeader) {
+ answer += " <header caption=\"" + macro.caption + "\"/>\n";
+ mi2++;
+ continue;
+ }
+
+ size_t oldest = time(NULL) - Conf::db_max_ttl;
+ if(macro.ttl != "") oldest = time(NULL) - atoi(macro.ttl.c_str());
+
+ bool completed =
+ db->checkMacro(request.patientid, macro.name, session.id(),
+ oldest);
+
+ answer += " <macro uid=\"42\" completed=";
+ if(completed) answer += "\"true\"";
+ else answer += "\"false\"";
+
+ attributes_t attr;
+ attr["name"] = macro.name;
+ attr["version"] = macro.version;
+ if(macro.caption != "") attr["caption"] = macro.caption;
+ if(macro.requires != "") attr["requires"] = macro.requires;
+ attr["static"] = macro.isStatic?"true":"false";
+ attr["compact"] = macro.isCompact?"true":"false";
+ attr["important"] = macro.isImportant?"true":"false";
+
+ attributes_t::iterator ai = attr.begin();
+ while(ai != attr.end()) {
+ std::string name = ai->first;
+ std::string value = ai->second;
+ answer += " "+name+"=\"" + value + "\"";
+ ai++;
+ }
+
+ if(macro.name == request.macro || macro.isStatic) {
+ foundmacro = true;
+
+ MacroParser mp(env.macrolist.getLatestVersion(macro.name));
+ mp.parse();
+ Macro *m = mp.getMacro();
+ answer += " caption=\"" + m->widgets.attributes["caption"] + "\"";
+ answer += ">\n";
+
+ AutoBorrower<Artefact*> borrower(env.atfpool);
+ Artefact *atf = borrower.get();
+
+ LUAQueryMapper lqm;
+
+ ////////////////////////
+ std::vector< Query >::iterator qi = m->queries.begin();
+ while(qi != m->queries.end()) {
+
+ Query &query = *qi;
+ std::string service = query.attributes["service"];
+
+ if(service == "pentominos") {
+ // Send the queries to Pentominos (if any)
+ QueryHandlerPentominos qh(*atf, request.patientid,
+ "pracrod"/*user*/);
+
+ QueryResult queryresult = qh.exec(*qi);
+ lqm.addQueryResult(queryresult);
}
-
- if(macro.name == request.macro || macro.isStatic) {
- foundmacro = true;
-
- MacroParser mp(env.macrolist.getLatestVersion(macro.name));
- mp.parse();
- Macro *m = mp.getMacro();
- answer += " caption=\"" + m->widgets.attributes["caption"] + "\"";
- answer += ">\n";
-
- AutoBorrower<Artefact*> borrower(env.atfpool);
- Artefact *atf = borrower.get();
-
- LUAQueryMapper lqm;
-
- ////////////////////////
- std::vector< Query >::iterator qi = m->queries.begin();
- while(qi != m->queries.end()) {
-
- Query &query = *qi;
- std::string service = query.attributes["service"];
-
- if(service == "pentominos") {
- // Send the queries to Pentominos (if any)
- QueryHandlerPentominos qh(*atf, transaction.cpr,
- "pracrod"/*user*/);
-
- QueryResult queryresult = qh.exec(*qi);
- lqm.addQueryResult(queryresult);
- }
-
- if(service == "pracro") {
- // Send the queries to Pentominos (if any)
- QueryHandlerPracro qh(*db, transaction.cpr);
-
- QueryResult queryresult = qh.exec(*qi);
- lqm.addQueryResult(queryresult);
- }
-
- qi++;
- }
-
- // Handle scripts
- if(m->scripts.size()) {
- answer += " <scripts>\n";
-
- std::vector< Script >::iterator spi = m->scripts.begin();
- while(spi != m->scripts.end()) {
- // answer += " <script language=\"" +
- // spi->attributes["language"] + "\">";
- answer += " <script>";
-
- if(spi->attributes.find("src") != spi->attributes.end()) {
- std::string file =
+
+ if(service == "pracro") {
+ // Send the queries to Pentominos (if any)
+ QueryHandlerPracro qh(*db, request.patientid);
+
+ QueryResult queryresult = qh.exec(*qi);
+ lqm.addQueryResult(queryresult);
+ }
+
+ qi++;
+ }
+
+ // Handle scripts
+ if(m->scripts.size()) {
+ answer += " <scripts>\n";
+
+ std::vector< Script >::iterator spi = m->scripts.begin();
+ while(spi != m->scripts.end()) {
+ // answer += " <script language=\"" +
+ // spi->attributes["language"] + "\">";
+ answer += " <script>";
+
+ if(spi->attributes.find("src") != spi->attributes.end()) {
+ std::string file =
Conf::xml_basedir + "/include/" + spi->attributes["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);
- answer += "\n-- BEGIN INCLUDE: '" + spi->attributes["src"] + "'\n";
- answer += xml_encode(inc);
- answer += "\n-- END INCLUDE: '" + spi->attributes["src"] + "'\n";
- }
- } else {
- answer += xml_encode(spi->attributes["code"]);
+ 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);
}
- answer += "</script>\n";
- spi++;
+ fclose(fp);
+ answer +="\n-- BEGIN INCLUDE: '"+spi->attributes["src"]+"'\n";
+ answer += xml_encode(inc);
+ answer +="\n-- END INCLUDE: '"+spi->attributes["src"]+"'\n";
}
-
- answer += " </scripts>\n";
+ } else {
+ answer += xml_encode(spi->attributes["code"]);
}
-
- answer += widgetgenerator(transaction.cpr, session.id(), *m, lqm,
- *db, oldest);
- } else {
- // only find macro title
- MacroParser mp(env.macrolist.getLatestVersion(macro.name));
- mp.parse();
- Macro *m = mp.getMacro();
- answer += " caption=\"" + m->widgets.attributes["caption"] + "\"";
- answer += ">\n";
-
+ answer += "</script>\n";
+ spi++;
}
-
- if(completed) {
- std::string jresume = session.journal()->getEntry(macro.name);
-
- std::string state = "old";
- std::string resume = db->getResume(transaction.cpr, macro, oldest,
- session.id());
- if(session.journal()->dirty(macro.name)) {
+
+ answer += " </scripts>\n";
+ }
+
+ answer += widgetgenerator(request.patientid, session.id(), *m,
+ lqm, *db, oldest);
+ } else {
+ // only find macro title
+ MacroParser mp(env.macrolist.getLatestVersion(macro.name));
+ mp.parse();
+ Macro *m = mp.getMacro();
+ answer += " caption=\"" + m->widgets.attributes["caption"] + "\"";
+ answer += ">\n";
+
+ }
+
+ if(completed) {
+ std::string jresume = session.journal()->getEntry(macro.name);
+
+ std::string state = "old";
+ std::string resume = db->getResume(request.patientid, macro,
+ oldest, session.id());
+ if(session.journal()->dirty(macro.name)) {
+ state = "dirty";
+ } else {
+ if(resume == jresume) {
+ state = "new";
+ } else {
+ if(jresume != "") {
state = "dirty";
+ session.journal()->setDirty(macro.name);
} else {
- if(resume == jresume) {
- state = "new";
- } else {
- if(jresume != "") {
- state = "dirty";
- session.journal()->setDirty(macro.name);
- } else {
- state = "old";
- }
- }
+ state = "old";
}
-
- answer += " <resume state=\""+state+"\">";
- answer += xml_encode(resume);
- answer += "</resume>\n";
}
-
- answer += " </macro>\n";
- mi2++;
-
}
- if(foundmacro == false && request.macro != "")
- throw NotFoundException(request);
-
- answer += " </template>\n";
-
- i++;
+ answer += " <resume state=\""+state+"\">";
+ answer += xml_encode(resume);
+ answer += "</resume>\n";
}
+
+ answer += " </macro>\n";
+ mi2++;
+
}
+
+ if(foundmacro == false && request.macro != "")
+ throw NotFoundException(request);
+
+ answer += " </template>\n";
return answer;
}
-std::string handleTransaction(Transaction &transaction, Environment &env,
+std::string handleTransaction(Request &request,
+ Transaction &transaction,
+ Environment &env,
Session &session)
{
std::string answer;
@@ -298,7 +322,7 @@ std::string handleTransaction(Transaction &transaction, Environment &env,
}
try {
- answer += handleRequest(transaction, env, session);
+ answer += handleRequest(request, env, session);
} catch( std::exception &e ) {
ERR(server, "Request error: %s\n", e.what());
return error_box(xml_encode(e.what()));
diff --git a/server/src/transactionhandler.h b/server/src/transactionhandler.h
index ae1857c..43ecf0b 100644
--- a/server/src/transactionhandler.h
+++ b/server/src/transactionhandler.h
@@ -40,6 +40,9 @@ public:
: Exception("Macro " + r.macro + " not found in template " + r.templ) {}
};
-std::string handleTransaction(Transaction &transaction, Environment &env, Session &session);
+std::string handleTransaction(Request &resuest,
+ Transaction &transaction,
+ Environment &env,
+ Session &session);
#endif/*__PRACRO_TRANSACTIONHANDLER_H__*/
diff --git a/server/src/transactionparser.cc b/server/src/transactionparser.cc
index 142b95f..a52d797 100644
--- a/server/src/transactionparser.cc
+++ b/server/src/transactionparser.cc
@@ -49,17 +49,10 @@ void TransactionParser::startTag(std::string name, attributes_t &attr)
if(name == "pracro") {
transaction->user = attr["user"];
- transaction->cpr = attr["cpr"];
+ transaction->patientid = attr["patientid"];
transaction->version = attr["version"];
}
- if(name == "request") {
- Request r;
- r.templ = attr["template"];
- r.macro = attr["macro"];
- transaction->requests.push_back(r);
- }
-
if(name == "commit") {
Commit c;
c.templ = attr["template"];
diff --git a/server/xml/courses/test.xml b/server/xml/courses/test.xml
index 9dabdb9..4594409 100644
--- a/server/xml/courses/test.xml
+++ b/server/xml/courses/test.xml
@@ -1,4 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
<course name="test" title="Test Course" version="1.0">
<template name="test"/>
+ <template name="test2"/>
</course>
diff --git a/server/xml/macros/test_lineedit.xml b/server/xml/macros/test_lineedit.xml
index d706b50..a9b510a 100644
--- a/server/xml/macros/test_lineedit.xml
+++ b/server/xml/macros/test_lineedit.xml
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?>
<macro name="test_lineedit" version="1.0">
- <resume></resume>
+ <resume><script>return 'hello'..value('dims')</script></resume>
<queries>
<query service="pentominos" class="test" ttl="1000000"/>
</queries>