summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordeva <deva>2009-07-17 13:02:45 +0000
committerdeva <deva>2009-07-17 13:02:45 +0000
commit177cea995d02fd14dd82fa010957ebfbc1c5e760 (patch)
tree62703ddc11b83a054e8068c0e9c79ce1951959a6
parenta619ccc300a00947207600e11fac848b7d37b26b (diff)
More work on the macrotool. Now fieldnames can be added and deleted, and a filehandler is able to add new macros assuring no conflicts in macro names/version/filenames happen. Error messages in MacroParser has been made more elaborate.
-rw-r--r--server/src/Makefile.am2
-rw-r--r--server/src/macroparser.cc38
-rw-r--r--server/src/macroparser.h8
-rw-r--r--server/src/macrotool.cc9
-rw-r--r--server/src/macrotool_fieldnames.cc30
-rw-r--r--server/src/macrotool_filehandler.cc218
-rw-r--r--server/src/macrotool_filehandler.h36
-rw-r--r--server/src/pracrodaopgsql.cc27
8 files changed, 348 insertions, 20 deletions
diff --git a/server/src/Makefile.am b/server/src/Makefile.am
index f8f6e21..0589630 100644
--- a/server/src/Makefile.am
+++ b/server/src/Makefile.am
@@ -48,6 +48,7 @@ macrotool_SOURCES = \
macroparser.cc \
macrotool_dump.cc \
macrotool_fieldnames.cc \
+ macrotool_filehandler.cc \
macrotool_util.cc \
pracrodao.cc \
pracrodaopgsql.cc \
@@ -73,6 +74,7 @@ EXTRA_DIST = \
macroparser.h \
macrotool_dump.h \
macrotool_fieldnames.h \
+ macrotool_filehandler.h \
macrotool_util.h \
pracrodao.h \
pracrodaopgsql.h \
diff --git a/server/src/macroparser.cc b/server/src/macroparser.cc
index c5b524d..0f7ed76 100644
--- a/server/src/macroparser.cc
+++ b/server/src/macroparser.cc
@@ -28,6 +28,8 @@
#include "macroparser.h"
#include "configuration.h"
+#include <stdio.h>
+
// For assert
#include <assert.h>
@@ -56,24 +58,37 @@ void MacroParser::error(const char* fmt, ...)
PRACRO_ERR_LOG(macro, "Error in MacroParser: ");
- va_list argp;
- va_start(argp, fmt);
- PRACRO_ERR_LOG_VA(macro, fmt, argp);
- va_end(argp);
+ {
+ va_list argp;
+ va_start(argp, fmt);
+ PRACRO_ERR_LOG_VA(macro, fmt, argp);
+ va_end(argp);
+
+ fprintf(stderr, "\n");
+ }
- fprintf(stderr, "\n");
+ {
+ char *p;
+ va_list argp;
+ va_start(argp, fmt);
+ if(vasprintf(&p, fmt, argp) != -1) {
+ throw Exception("Error in MacroParser: " + std::string(p));
+ free(p);
+ }
+ va_end(argp);
+ }
- throw Exception("Error in MacroParser");
}
-MacroParser::MacroParser(std::string macro)
+MacroParser::MacroParser(std::string macro, bool abspath)
{
state = UNDEFINED;
m = NULL;
current_map = NULL;
current_script = NULL;
- file = Conf::xml_basedir + "/macros/" + macro + ".xml";
+ if(!abspath) file = Conf::xml_basedir + "/macros/" + macro + ".xml";
+ else file = macro;
PRACRO_DEBUG(macro, "Using macro file: %s\n", file.c_str());
@@ -298,6 +313,13 @@ void MacroParser::parseError(char *buf, size_t len, std::string error, int linen
PRACRO_ERR_LOG(macro, "\tBuffer %u bytes: [", len);
if(fwrite(buf, len, 1, stderr) != len) {}
PRACRO_ERR_LOG(macro, "]\n");
+
+ char *slineno;
+ if(asprintf(&slineno, " at line %d\n", lineno) != -1) {
+ throw Exception(error + slineno);
+ free(slineno);
+ }
+
}
Macro *MacroParser::getMacro()
diff --git a/server/src/macroparser.h b/server/src/macroparser.h
index 843cb55..3867ca1 100644
--- a/server/src/macroparser.h
+++ b/server/src/macroparser.h
@@ -45,7 +45,7 @@ class MacroParser : public SAXParser {
} ParserState;
public:
- MacroParser(std::string course);
+ MacroParser(std::string macro, bool abspath = false);
~MacroParser();
void characterData(std::string &data);
@@ -53,6 +53,12 @@ public:
void endTag(std::string name);
void parseError(char *buf, size_t len, std::string error, int lineno);
+ /**
+ * Get a pointer to the parsed macro.
+ * NOTE: The allocated memory for the macro is owned by the parser, and will be
+ * freed upon parser deletion.
+ * @return A pointer to the macro or NULL on error.
+ */
Macro *getMacro();
protected:
diff --git a/server/src/macrotool.cc b/server/src/macrotool.cc
index 44beeef..11c634e 100644
--- a/server/src/macrotool.cc
+++ b/server/src/macrotool.cc
@@ -41,6 +41,7 @@
#include "macrotool_dump.h"
#include "macrotool_fieldnames.h"
+#include "macrotool_filehandler.h"
static const char version_str[] =
"Pracro server v" VERSION "\n"
@@ -65,9 +66,10 @@ static const char usage_str[] =
" -D, --debug ddd Enable debug messages on 'ddd'; see documentation for details\n"
"\n"
"Commands:\n"
-" dump entity Dumps 'entity' to screen ('dump help' to see list of entities).\n"
-" fieldnames entity Add/delete/update entries in the fieldnames database\n"
-" ('fieldnames help' to see list of entities).\n"
+" dump entity Dumps 'entity' to screen ('dump help' to see list of entities).\n"
+" fieldnames entity Add/delete/update entries in the fieldnames database\n"
+" ('fieldnames help' to see list of entities).\n"
+" filehandler entity Handle macro files ('macrohandler help' to see list of entities).\n"
;
ConfigurationParser *configparser = NULL;
@@ -152,6 +154,7 @@ int main(int argc, char *argv[])
if(command == "dump") macrotool_dump(params);
if(command == "fieldnames") macrotool_fieldnames(params);
+ if(command == "filehandler") macrotool_filehandler(params);
// Clean up
if(configfile) free(configfile);
diff --git a/server/src/macrotool_fieldnames.cc b/server/src/macrotool_fieldnames.cc
index eeed648..3c3f8b7 100644
--- a/server/src/macrotool_fieldnames.cc
+++ b/server/src/macrotool_fieldnames.cc
@@ -37,17 +37,21 @@
static const char usage_str[] =
" help Prints this helptext.\n"
-" set name desc Add a field (or update) called 'name', described as 'desc'\n"
+" add name desc Add a field called 'name', described as 'desc'\n"
+" del name Delete a field called 'name'\n"
+" list List all fieldnames as well as their macro references.\n"
;
static void add(std::string name, std::string desc)
{
-#ifndef WITHOUT_DB
- PRACRO_DEBUG("SET (name: %s - desc: %s)\n", name.c_str(), desc.c_str());
-#else /*WITHOUT_DB*/
- printf("Project not compiled with db spport.")
-#endif/*WITHOUT_DB*/
+ Database db("pgsql", Conf::database_addr, "", Conf::database_user, Conf::database_passwd, "");
+ db.addFieldname(name, desc);
+}
+static void del(std::string name)
+{
+ Database db("pgsql", Conf::database_addr, "", Conf::database_user, Conf::database_passwd, "");
+ db.delFieldname(name);
}
static std::vector<std::string> getWidgetNames(Widget &w)
@@ -170,9 +174,9 @@ void macrotool_fieldnames(std::vector<std::string> params)
return;
}
- if(params[0] == "set") {
+ if(params[0] == "add") {
if(params.size() != 3) {
- printf("The command 'set' needs 2 parameters.\n");
+ printf("The command 'add' needs 2 parameters.\n");
printf(usage_str);
return;
}
@@ -180,6 +184,16 @@ void macrotool_fieldnames(std::vector<std::string> params)
return;
}
+ if(params[0] == "del") {
+ if(params.size() != 2) {
+ printf("The command 'del' needs 1 parameter.\n");
+ printf(usage_str);
+ return;
+ }
+ del(params[1]);
+ return;
+ }
+
if(params[0] == "help") {
printf(usage_str);
return;
diff --git a/server/src/macrotool_filehandler.cc b/server/src/macrotool_filehandler.cc
new file mode 100644
index 0000000..524761c
--- /dev/null
+++ b/server/src/macrotool_filehandler.cc
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * macrotool_filehandler.cc
+ *
+ * Fri Jul 17 08:48:09 CEST 2009
+ * Copyright 2009 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 "macrotool_filehandler.h"
+
+#include <fstream>
+#include <ios>
+
+#include "macroparser.h"
+#include "template.h"
+
+#include "debug.h"
+
+#include "macrotool_util.h"
+
+#include "configuration.h"
+
+static const char usage_str[] =
+" help Prints this helptext.\n"
+" add file Add a file called 'file' to the macro or template folder, according\n"
+" to its contents.\n"
+" check file Check if a file is valid, and print a resume of its contents.\n"
+;
+
+/**
+class Macro {
+public:
+ std::vector< Query > queries;
+ std::vector< Map > maps;
+ std::vector< Script > scripts;
+ Widget window;
+ std::map< std::string, std::string > attributes;
+ Resume resume;
+};
+ **/
+static bool check(std::string file, std::string *name = NULL, std::string *version = NULL);
+static bool check(std::string file, std::string *name, std::string *version)
+{
+ try {
+ MacroParser parser(file, true);
+ parser.parse();
+ Macro *macro = parser.getMacro();
+ if(!macro) {
+ printf("Macro malformed!\n");
+ return false;
+ }
+
+ printf("Parsing of %s was succesful.\n", file.c_str());
+ printf("Name: %s\n", macro->attributes["name"].c_str());
+ printf("Version: %s\n", macro->attributes["version"].c_str());
+
+ if(name) *name = macro->attributes["name"];
+ if(version) *version = macro->attributes["version"];
+
+ } catch( std::exception &e ) {
+ printf("%s\n", e.what());
+ return false;
+ }
+ return true;
+}
+
+static bool macro_exists(std::string name, std::string version, std::string &clashfile)
+{
+ std::vector<std::string> macrofiles = getMacros();
+ std::vector<std::string>::iterator mfs = macrofiles.begin();
+ while(mfs != macrofiles.end()) {
+ std::string macroname = mfs->substr(0, mfs->length() - 4);
+
+ MacroParser parser(macroname);
+ parser.parse();
+ Macro *macro = parser.getMacro();
+
+ if(name == macro->attributes["name"] &&
+ version == macro->attributes["version"]) {
+ clashfile = *mfs;
+ return true;
+ }
+
+ mfs++;
+ }
+
+ return false;
+}
+
+static std::string strippath(std::string filename)
+{
+ if(filename.find('/') == std::string::npos) return filename;
+ return filename.substr(filename.rfind('/')+1);
+}
+
+static bool file_exist(std::string file)
+{
+ FILE *fp = fopen(file.c_str(), "r");
+ if(!fp) return false;
+ fclose(fp);
+ return true;
+}
+
+static void add(std::string file)
+{
+ std::string name;
+ std::string version;
+ std::string clashfile;
+ std::string target;
+
+ if(!check(file, &name, &version)) {
+ printf("File not a valid macro file.\nAborting...\n");
+ return;
+ }
+
+ if(macro_exists(name, version, clashfile)) {
+ printf("WARNING: A macro with that name and version already exists."
+ " THE EXISTING FILE WILL BE OVERWRITTEN!\n");
+ printf("File: %s\n", clashfile.c_str());
+ char answer[32];
+ answer[0] = '\0';
+ while(std::string(answer) != "yes\n" && std::string(answer) != "no\n") {
+ if(answer[0] == '\0') printf("Are you sure you want to put the file in the macro directory? [yes/no]\n");
+ else printf("Please answer 'yes' or 'no'\n");
+ fgets(answer, sizeof(answer), stdin);
+ }
+
+ if(std::string(answer) == "no\n") {
+ printf("Aborting...\n");
+ return;
+ }
+ target = Conf::xml_basedir + "/macros/" + clashfile;
+ } else {
+ target = Conf::xml_basedir + "/macros/" + strippath(file);
+
+ size_t cnt = 0;
+ while(file_exist(target)) {
+ char *num;
+ if(cnt) asprintf(&num, "-%d", cnt);
+ else num = strdup("");
+ target = Conf::xml_basedir + "/macros/" + name + "-" + version + num + ".xml";
+ printf("Trying: %d %s\n", cnt, target.c_str());
+ free(num);
+ cnt++;
+ }
+ }
+
+ printf("Copying '%s' to '%s' ...\n", file.c_str(), target.c_str());
+
+ {
+ std::ifstream ifs(file.c_str(), std::ios::binary);
+ if(!ifs) {
+ printf("Could read source file.\nAborting...\n");
+ return;
+ }
+ std::ofstream ofs(target.c_str(), std::ios::binary);
+ ofs << ifs.rdbuf();
+ }
+ printf("done\n");
+}
+
+void macrotool_filehandler(std::vector<std::string> params)
+{
+ if(params.size() < 1) {
+ printf(usage_str);
+ return;
+ }
+
+ PRACRO_DEBUG(filehandler, "filehandler: %s\n", params[0].c_str());
+
+ if(params[0] == "add") {
+ if(params.size() != 2) {
+ printf("The command 'add' needs 1 parameter.\n");
+ printf(usage_str);
+ return;
+ }
+ add(params[1]);
+ return;
+ }
+
+ if(params[0] == "check") {
+ if(params.size() != 2) {
+ printf("The command 'check' needs 1 parameter.\n");
+ printf(usage_str);
+ return;
+ }
+ check(params[1]);
+ return;
+ }
+
+ if(params[0] == "help") {
+ printf(usage_str);
+ return;
+ }
+
+ printf("Unknown command '%s'\n", params[0].c_str());
+ printf(usage_str);
+ return;
+}
diff --git a/server/src/macrotool_filehandler.h b/server/src/macrotool_filehandler.h
new file mode 100644
index 0000000..70777fc
--- /dev/null
+++ b/server/src/macrotool_filehandler.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * macrotool_filehandler.h
+ *
+ * Fri Jul 17 08:48:09 CEST 2009
+ * Copyright 2009 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_MACROTOOL_FILEHANDLER_H__
+#define __PRACRO_MACROTOOL_FILEHANDLER_H__
+
+#include <vector>
+#include <string>
+
+void macrotool_filehandler(std::vector<std::string> params);
+
+#endif/*__PRACRO_MACROTOOL_FILEHANDLER_H__*/
diff --git a/server/src/pracrodaopgsql.cc b/server/src/pracrodaopgsql.cc
index 683fe85..7159b03 100644
--- a/server/src/pracrodaopgsql.cc
+++ b/server/src/pracrodaopgsql.cc
@@ -244,10 +244,37 @@ unsigned PracroDAOPgsql::nrOfCommits(std::string patientid, std::string macronam
void PracroDAOPgsql::addFieldname(std::string name, std::string description)
{
+ std::stringstream timestamp; timestamp << time(NULL);
+ std::string ts;
+ try {
+ pqxx::work W(*conn);
+ ts = "INSERT INTO fieldnames (name, description, \"timestamp\") VALUES ("
+ " '" + W.esc(name) + "', "
+ " '" + W.esc(description) + "', "
+ " '" + W.esc(timestamp.str()) + "' "
+ ")"
+ ;
+ PRACRO_DEBUG(sql, "Query: %s\n", ts.c_str());
+ pqxx::result R = W.exec(ts);
+ W.commit();
+ } catch (std::exception &e) {
+ PRACRO_ERR_LOG(db, "Query failed: %s: %s\n", e.what(), ts.c_str());
+ }
}
void PracroDAOPgsql::delFieldname(std::string name)
{
+ std::string ts;
+ try {
+ pqxx::work W(*conn);
+ ts = "DELETE FROM fieldnames WHERE name="
+ "'" + W.esc(name) + "' ";
+ PRACRO_DEBUG(sql, "Query: %s\n", ts.c_str());
+ pqxx::result R = W.exec(ts);
+ W.commit();
+ } catch (std::exception &e) {
+ PRACRO_ERR_LOG(db, "Query failed: %s: %s\n", e.what(), ts.c_str());
+ }
}
std::vector<Fieldname> PracroDAOPgsql::getFieldnames()