summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/src/Makefile.am3
-rw-r--r--server/src/database.cc20
-rw-r--r--server/src/macro.h58
-rw-r--r--server/src/macro_parser.cc170
-rw-r--r--server/src/macro_parser.h36
-rw-r--r--server/src/server.cc76
-rw-r--r--server/src/transaction.h2
-rw-r--r--server/src/xmlparser.cc8
-rw-r--r--server/xml/Makefile.am6
-rw-r--r--server/xml/example.xml56
-rw-r--r--server/xml/patient.xml10
11 files changed, 354 insertions, 91 deletions
diff --git a/server/src/Makefile.am b/server/src/Makefile.am
index ac5ed0a..43fa560 100644
--- a/server/src/Makefile.am
+++ b/server/src/Makefile.am
@@ -11,6 +11,7 @@ pracrod_SOURCES = \
configuration.cc \
exception.cc \
log.cc \
+ macro_parser.cc \
server.cc \
tcpsocket.cc \
tostring.cc \
@@ -23,6 +24,8 @@ EXTRA_DIST = \
debug.h \
exception.h \
log.h \
+ macro.h \
+ macro_parser.h \
server.h \
tcpsocket.h \
tostring.h \
diff --git a/server/src/database.cc b/server/src/database.cc
index 1d4915e..1a48925 100644
--- a/server/src/database.cc
+++ b/server/src/database.cc
@@ -62,7 +62,7 @@ int Database::post(Transaction &transaction)
commit.macro + "', '" +
commit.version + "', '" +
now + "', '" +
- commit.user + "')";
+ transaction.user + "')";
W.exec(sql);
// Insert field entries
@@ -124,21 +124,21 @@ CREATE DATABASE pracro
CREATE TABLE transactions
(
- "cpr" varchar(255),
- "transaction" varchar(255),
- "makro" varchar(255),
- "version" varchar(255),
- "timestamp" varchar(255),
- "user" varchar(255)
+ "cpr" varchar(11),
+ "transaction" text,
+ "makro" text,
+ "version" text,
+ "timestamp" bigint,
+ "user" text
)
WITH OIDS;
ALTER TABLE transactions OWNER TO pracro;
CREATE TABLE fields
(
- "transaction" varchar(255),
- "name" varchar(255),
- "value" varchar(255)
+ "transaction" text,
+ "name" text,
+ "value" text
)
WITH OIDS;
ALTER TABLE fields OWNER TO pracro;
diff --git a/server/src/macro.h b/server/src/macro.h
new file mode 100644
index 0000000..af9749d
--- /dev/null
+++ b/server/src/macro.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * macro.h
+ *
+ * Mon Sep 24 10:51:43 CEST 2007
+ * Copyright 2007 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup
+ * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk
+ ****************************************************************************/
+
+/*
+ * 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_MACRO_H__
+#define __PRACRO_MACRO_H__
+
+#include <string>
+#include <vector>
+
+class WidgetProperty {
+public:
+ std::string name;
+ std::string value;
+};
+typedef std::vector< WidgetProperty > WidgetPropertyList;
+
+class Widget;
+typedef std::vector< Widget > WidgetList;
+
+class Widget {
+public:
+ std::string type;
+ WidgetPropertyList properties;
+ WidgetList widgets;
+};
+
+class Macro {
+public:
+ std::string name;
+ std::string version;
+
+ WidgetList widgets;
+};
+
+#endif/*__PRACRO_MACRO_H__*/
diff --git a/server/src/macro_parser.cc b/server/src/macro_parser.cc
new file mode 100644
index 0000000..c317482
--- /dev/null
+++ b/server/src/macro_parser.cc
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * macro_parser.cc
+ *
+ * Mon Sep 24 10:49:55 CEST 2007
+ * Copyright 2007 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup
+ * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk
+ ****************************************************************************/
+
+/*
+ * 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 "macro_parser.h"
+
+// For XML
+#include <config.h>
+
+// For open, read and close
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <expat.h>
+
+#include <string>
+#include <map>
+
+class MacroParser {
+public:
+ Macro *macro;
+ std::vector< Widget* > stack;
+ bool done;
+};
+
+static void start_hndl(void *p, const char *el, const char **attr)
+{
+ MacroParser *parser = (MacroParser*)XML_GetUserData(p);
+
+ printf("Start tag [%s]\n", el);
+
+ // Convert to comfy C++ values...
+ std::string name = el;
+ std::map< std::string, std::string > attributes;
+
+ while(*attr) {
+ std::string at_name = *attr;
+ attr++;
+ std::string at_value = *attr;
+ attr++;
+
+ attributes.insert(make_pair(at_name, at_value));
+ }
+
+ // Do something reasonable with them...
+
+ if(name == "include") {
+
+ Macro inc;
+ parse_macro(attributes["name"], inc);
+
+ WidgetList::iterator w = inc.widgets.front().widgets.begin();
+ while(w != inc.widgets.front().widgets.end()) {
+ parser->stack.back()->widgets.push_back(*w);
+ w++;
+ }
+
+ return; // Don't do further parsing of this tag.
+ }
+
+ Widget widget;
+ widget.type = name;
+
+ Widget *wp;
+
+ if(parser->stack.size() > 0) {// We only pushback the child if there is a parent.
+ parser->stack.back()->widgets.push_back(widget);
+ wp = &parser->stack.back()->widgets.back();
+ } else {
+ parser->macro->widgets.push_back(widget);
+ wp = &parser->macro->widgets.back();
+ }
+ parser->stack.push_back(wp);
+
+ std::map< std::string, std::string >::iterator i = attributes.begin();
+ while(i != attributes.end()) {
+ WidgetProperty prop;
+ prop.name = i->first;
+ prop.value = i->second;
+
+ wp->properties.push_back(prop);
+
+ i++;
+ }
+}
+
+static void end_hndl(void *p, const char *el)
+{
+ MacroParser *parser = (MacroParser*)XML_GetUserData(p);
+
+ printf("End tag [%s]\n", el);
+
+ if(std::string("include") != el) parser->stack.pop_back();
+
+ if(!strcmp(el, "macro")) parser->done = true;
+}
+
+void parse_macro(std::string name, Macro &macro)
+{
+
+ XML_Parser p = XML_ParserCreate(NULL);
+ if (! p) {
+ fprintf(stderr, "Couldn't allocate memory for parser\n");
+ // throw Exception(...);
+ return;
+ }
+
+ MacroParser parser;
+ parser.macro = &macro;
+ parser.done = false;
+
+ XML_SetUserData(p, &parser);
+ XML_UseParserAsHandlerArg(p);
+ XML_SetElementHandler(p, start_hndl, end_hndl);
+
+ std::string macrofile = std::string(XML) + "/" + name + ".xml";
+ int fd = open(macrofile.c_str(), O_RDONLY);
+
+ if(fd == -1) {
+ printf("Cannot open file \"%s\"...", macrofile.c_str());
+ printf("failed!\n");
+ return;
+ }
+
+ while(!parser.done) {
+ char buf[32];
+ int len;
+
+ memset(buf, 0, sizeof(buf));
+ len = read(fd, buf, sizeof(buf) - 1);
+
+ parser.done = len == 0;
+
+ if (! XML_Parse(p, buf, len, parser.done)) {
+ fprintf(stderr, "Parse error at line %d:\n%s\n",
+ XML_GetCurrentLineNumber(p),
+ XML_ErrorString(XML_GetErrorCode(p)));
+ // throw Exception(...);
+ return;
+ }
+ }
+
+ // printf("%d requests\n", transaction.requests.size());
+}
diff --git a/server/src/macro_parser.h b/server/src/macro_parser.h
new file mode 100644
index 0000000..9f701d4
--- /dev/null
+++ b/server/src/macro_parser.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * macro_parser.h
+ *
+ * Mon Sep 24 10:49:55 CEST 2007
+ * Copyright 2007 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup
+ * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk
+ ****************************************************************************/
+
+/*
+ * 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_MACRO_PARSER_H__
+#define __PRACRO_MACRO_PARSER_H__
+
+#include <string>
+
+#include "macro.h"
+
+void parse_macro(std::string name, Macro &macro);
+
+#endif/*__PRACRO_MACRO_PARSER_H__*/
diff --git a/server/src/server.cc b/server/src/server.cc
index 24f55ef..064d8b9 100644
--- a/server/src/server.cc
+++ b/server/src/server.cc
@@ -26,9 +26,6 @@
*/
#include "server.h"
-// For XML
-#include <config.h>
-
#include "tcpsocket.h"
#include <errno.h>
@@ -40,40 +37,33 @@
#include "configuration.h"
-// For open, read and close
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
#include "transaction.h"
#include "xmlparser.h"
#include "database.h"
-/**
-\section{Data transmission}
-En transmission består af en række deltransmissioner som afhænger af
-brugerens handling.
-\begin{itemize}
-\item Klienten beder om en XMLMakro by-name.
-\item Serveren genererer makroen og sender den til klienten i en XML
- stream. Forbindelsen lukkes efter end overførsel.
-\item Brugeren udfylder input felterne og trykker på ``commit'' eller
- ``abort'' knappen.
-\item Hvis der blev trykket ``abort'' lukkes vinduet.
-\item Hvis der blev trykket ``commit'' genereres et XML dokument på
- klienten indeholdene alle input felternes navne og deres tilhørende
- værdier.
-\item Dette XML dokument sendes til serveren via en nyoprettet forbindelse.
-\item Serveren producerer en plaintext klump som repræsenterer
-\item Teksten sendes til klienten som appender til den PC-Praxis
- journalfilen.
-\item Klienten svarer til serveren at alt gik godt (eller det modsatte) og
- makrovinduet lukkes.
-\item Serveren lagrer dataene i en database hvis det gik godt.
-\end{itemize}
-*/
+#include "macro.h"
+#include "macro_parser.h"
+
+static void send_macro_widget(Widget &widget, TCPSocket &socket, std::string tabs)
+{
+ socket.write(tabs + "<" + widget.type);
+ WidgetPropertyList::iterator p = widget.properties.begin();
+ while(p != widget.properties.end()) {
+ WidgetProperty &property = *p;
+ socket.write(" " + property.name + "=\"" + property.value + "\"");
+ p++;
+ }
+ socket.write(">\n");
+
+ WidgetList::iterator w = widget.widgets.begin();
+ while(w != widget.widgets.end()) {
+ send_macro_widget(*w, socket, tabs + " ");
+ w++;
+ }
+ socket.write(tabs + "</" + widget.type + ">\n");
+}
+
static void connection(TCPSocket &socket)
{
printf("Got connection...\n");
@@ -91,24 +81,14 @@ static void connection(TCPSocket &socket)
printf("Handling request for \"%s\"...", request.macro.c_str());
- // Now handle the request.
- char outbuf[3];
- int bytes;
-
- std::string macro = std::string(XML) + "/" + request.macro + ".xml";
-
- int fd = open(macro.c_str(), O_RDONLY);
- if(fd == -1) {
- printf("Cannot open file \"%s\"...", macro.c_str());
- printf("failed!\n");
- i++;
- continue;
- }
+ Macro macro;
+ parse_macro(request.macro, macro);
- while((bytes = read(fd, outbuf, sizeof(outbuf))) ) {
- socket.write(outbuf, bytes);
+ WidgetList::iterator w = macro.widgets.begin();
+ while(w != macro.widgets.end()) {
+ send_macro_widget(*w, socket, " ");
+ w++;
}
- close(fd);
printf("done.\n");
diff --git a/server/src/transaction.h b/server/src/transaction.h
index 04d83b3..97bb556 100644
--- a/server/src/transaction.h
+++ b/server/src/transaction.h
@@ -48,7 +48,6 @@ typedef std::vector< Field > Fields;
class Commit {
public:
- std::string user;
std::string macro;
std::string version;
Fields fields;
@@ -58,6 +57,7 @@ typedef std::vector< Commit > Commits;
class Transaction {
public:
+ std::string user;
std::string cpr;
std::string version;
diff --git a/server/src/xmlparser.cc b/server/src/xmlparser.cc
index d4a6bd8..31ffbed 100644
--- a/server/src/xmlparser.cc
+++ b/server/src/xmlparser.cc
@@ -33,9 +33,9 @@
#include <string>
#include <map>
-bool done = false;
+static bool done = false;
-void start_hndl(void *p, const char *el, const char **attr)
+static void start_hndl(void *p, const char *el, const char **attr)
{
Transaction *transaction = (Transaction*)XML_GetUserData(p);
@@ -63,6 +63,7 @@ void start_hndl(void *p, const char *el, const char **attr)
// Do something reasonable with them...
if(name == "pracro") {
+ transaction->user = attributes["user"];
transaction->cpr = attributes["cpr"];
transaction->version = attributes["version"];
}
@@ -75,7 +76,6 @@ void start_hndl(void *p, const char *el, const char **attr)
if(name == "commit") {
Commit c;
- c.user = attributes["user"];
c.macro = attributes["macro"];
c.version = attributes["version"];
transaction->commits.push_back(c);
@@ -90,7 +90,7 @@ void start_hndl(void *p, const char *el, const char **attr)
}
-void end_hndl(void *p, const char *el)
+static void end_hndl(void *p, const char *el)
{
// printf("End tag [%s]\n", el);
if(!strcmp(el, "pracro")) done = true;
diff --git a/server/xml/Makefile.am b/server/xml/Makefile.am
index 3ad491e..0e86339 100644
--- a/server/xml/Makefile.am
+++ b/server/xml/Makefile.am
@@ -1,7 +1,9 @@
EXTRA_DIST = \
- example.xml
+ example.xml \
+ patient.xml
xmldir = $(datadir)/xml
xml_DATA = \
- example.xml
+ example.xml \
+ patient.xml
diff --git a/server/xml/example.xml b/server/xml/example.xml
index 3e31f56..60068ca 100644
--- a/server/xml/example.xml
+++ b/server/xml/example.xml
@@ -1,27 +1,31 @@
- <macro name="fundus" version="1.0">
- <window name="mainwindow"
- caption="Fundus"
- width="800"
- height="600"
- layout="vbox">
- <include name="patient"/>
- <frame name="spl_frame" caption="Spl:" layout="vbox">
- <textedit name="spl_note" value="På begge sider alderssvarende forhold. Der er let katarakt, som dog ikke er operationskrævende."/>
+<?xml version="1.0" encoding="UTF-8"?>
+<macro name="fundus" version="1.0">
+ <window name="mainwindow"
+ caption="Fundus"
+ width="500"
+ height="500"
+ layout="vbox">
+ <include name="patient"/>
+ <frame name="spl_frame" caption="Spl:" layout="vbox">
+ <textedit name="spl_note" regexp=".*" value="På begge sider alderssvarende forhold. Der er let katarakt, som dog ikke er operationskrævende."/>
+ </frame>
+ <frame name="linse_frame" caption="Linse:" layout="vbox">
+ <lineedit name="linse" regexp="[0-9]{5}" value="90-D linse"/>
+ <textedit name="linse_note" regexp=".*" value="Der findes centrale atrofiske forandringer."/>
+ </frame>
+ <frame name="swelling_frame" layout="hbox">
+ <label name="swelling" caption="Der findes central hævelse med:"/>
+ <frame name="swelling_radios" layout="vbox">
+ <radiobuttons name="radio" layout="vbox">
+ <item caption="Randblødning" value="rand"/>
+ <item caption="Exsudater" value="exsudater"/>
+ <item caption="Blahblah" value="blabla"/>
+ </radiobuttons>
</frame>
- <frame name="linse_frame" caption="Linse:" layout="vbox">
- <lineedit name="linse" caption="90-D linse"/>
- <textedit name="linse_note" value="Der findes centrale atrofiske forandringer."/>
- </frame>
- <frame name="swelling_frame" layout="hbox">
- <label name="swelling" caption="Der findes central hævelse med:"/>
- <frame name="swelling_radios" layout="vbox"/>
- <radiobutton name="radio1" caption="Randblødning"/>
- <radiobutton name="radio2" caption="Exsudater"/>
- </frame>
- </frame>
- <frame name="buttons" layout="hbox">
- <button name="cancel" caption="Annuller"/>
- <button name="commit" caption="Godkend"/>
- </frame>
- </window>
- </macro>
+ </frame>
+ <frame name="buttons" layout="hbox">
+ <button name="cancel" caption="Annuller" action="cancel"/>
+ <button name="commit" caption="Godkend" action="commit"/>
+ </frame>
+ </window>
+</macro>
diff --git a/server/xml/patient.xml b/server/xml/patient.xml
new file mode 100644
index 0000000..751f8f0
--- /dev/null
+++ b/server/xml/patient.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<macro name="patient" version="1.0">
+ <frame name="cpr_frame" caption="CPR" layout="vbox">
+ <lineedit name="patient_cpr" regexp="\d{6}-{0,1}\d{4}" value=""/>
+ </frame>
+ <frame name="name_frame" caption="Navn:" layout="vbox">
+ <lineedit name="patient_navn" regexp=".+" value=""/>
+ <textedit name="patient_note" regexp=".*" value=""/>
+ </frame>
+</macro>