diff options
-rw-r--r-- | server/src/Makefile.am | 3 | ||||
-rw-r--r-- | server/src/database.cc | 20 | ||||
-rw-r--r-- | server/src/macro.h | 58 | ||||
-rw-r--r-- | server/src/macro_parser.cc | 170 | ||||
-rw-r--r-- | server/src/macro_parser.h | 36 | ||||
-rw-r--r-- | server/src/server.cc | 76 | ||||
-rw-r--r-- | server/src/transaction.h | 2 | ||||
-rw-r--r-- | server/src/xmlparser.cc | 8 | ||||
-rw-r--r-- | server/xml/Makefile.am | 6 | ||||
-rw-r--r-- | server/xml/example.xml | 56 | ||||
-rw-r--r-- | server/xml/patient.xml | 10 |
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 ¯o) +{ + + XML_Parser p = XML_ParserCreate(NULL); + if (! p) { + fprintf(stderr, "Couldn't allocate memory for parser\n"); + // throw Exception(...); + return; + } + + MacroParser parser; + parser.macro = ¯o; + 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 ¯o); + +#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> |