/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * widgetgenerator.cc * * Mon May 19 09:58:41 CEST 2008 * Copyright 2008 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 "debug.h" #include "widgetgenerator.h" #include "configuration.h" #include "xml_encode_decode.h" static std::string automap(std::string name) { std::string group; std::string groupcheck = "if("; for(size_t i = 0; i < name.length(); i++) { group += name[i]; if(name[i] == '.') groupcheck += " and " + group; else groupcheck += name[i]; } groupcheck += " and " + name + ".value and " + name + ".timestamp and " + name + ".source"; groupcheck += ")\n"; std::string automapstring = "-- Returning 0, 0 invalidates the result\n" "value = 0\n" "timestamp = 0\n" "source = 0\n" "\n" + groupcheck + "then\n" " value = " + name + ".value\n" " timestamp = " + name + ".timestamp\n" " source = " + name + ".source\n" "end\n" "return value, timestamp, source\n"; PRACRO_DEBUG(widget, "Automap:\n%s\n", automapstring.c_str()); return automapstring; } static std::string send_macro_widget(Macro ¯o, Widget &widget, std::string tabs, LUAQueryMapper &mapper, Values &values) { std::string result; std::string prefilled; time_t timestamp = 0; time_t now = time(NULL); result = tabs + "<" + widget.attributes["tagname"]; std::map< std::string, std::string >::iterator p = widget.attributes.begin(); PRACRO_DEBUG(prefill, "%s: %s\n", widget.attributes["tagname"].c_str(), widget.attributes["name"].c_str()); PRACRO_DEBUG(prefill, "0: (%s, %s, %d)\n", prefilled.c_str(), widget.attributes["value"].c_str(), (int)timestamp); // Check if the field has a map, and fill in the value if it has... if(widget.attributes.find("map") != widget.attributes.end()) { std::string luamap; std::vector< Map >::iterator li = macro.maps.begin(); while(li != macro.maps.end()) { Map &map = *li; if(map.attributes["name"] == widget.attributes["map"]) { luamap = map.attributes["lua"]; } li++; } // Check to see if we should automap if(luamap == "") { luamap = automap(widget.attributes["map"]); } // printf("LUAMAP: %s\n", luamap.c_str()); fflush(stdout); if(luamap != "") { Value value = mapper.map(luamap); if(value.timestamp > now - Conf::pentominos_max_ttl) { widget.attributes["value"] = xml_encode(value.value); timestamp = value.timestamp; prefilled = xml_encode(value.source); } PRACRO_DEBUG(prefill, "map: (%s, %d)\n", value.value.c_str(), (int)value.timestamp); } // widget.attributes.erase(widget.attributes.find("map")); } PRACRO_DEBUG(prefill, "1: (%s, %s, %d)\n", prefilled.c_str(), widget.attributes["value"].c_str(), (int)timestamp); // Check if there is a previously stored value in the db... if(values.find(widget.attributes["name"]) != values.end()) { PRACRO_DEBUG(prefill, "db: (%s, %d)\n", values[widget.attributes["name"]].value.c_str(), (int)values[widget.attributes["name"]].timestamp); if(values[widget.attributes["name"]].timestamp > timestamp) { if(values[widget.attributes["name"]].timestamp > now - Conf::db_max_ttl) { widget.attributes["value"] = xml_encode(values[widget.attributes["name"]].value); timestamp = values[widget.attributes["name"]].timestamp; prefilled = "pracro"; } } } PRACRO_DEBUG(prefill, "2: (%s, %s, %d)\n", prefilled.c_str(), widget.attributes["value"].c_str(), (int)timestamp); while(p != widget.attributes.end()) { if(p->first != "tagname" && p->first != "map") { if( ! (p->first == "name" && p->second == "") ) result += " " + p->first + "=\"" + p->second + "\""; } p++; } if(prefilled != "") result += " prefilled=\"" + prefilled + "\""; if(widget.widgets.size() == 0) { // If node is empty, use short tag form result += "/>\n"; return result; } result += ">\n"; std::vector< Widget >::iterator w = widget.widgets.begin(); while(w != widget.widgets.end()) { result += send_macro_widget(macro, *w, tabs + " ", mapper, values); w++; } result += tabs + "\n"; return result; } static void get_fields(Widget &widget, Fieldnames &fields) { if(widget.attributes.find("value") != widget.attributes.end()) { if(widget.attributes["name"] != "") fields.push_back(widget.attributes["name"]); } std::vector< Widget >::iterator w = widget.widgets.begin(); while(w != widget.widgets.end()) { get_fields(*w, fields); w++; } } std::string widgetgenerator(std::string cpr, Macro ¯o, LUAQueryMapper &mapper, Database &db) { Fieldnames fields; get_fields(macro.widgets, fields); Values values = db.getValues(cpr, fields); return send_macro_widget(macro, macro.widgets, " ", mapper, values); } #ifdef TEST_WIDGETGENERATOR #include #define PATIENTID "1234567890" int main() { time_t now = time(NULL); printf("Test pretty printer:\n"); { Macro macro; macro.widgets.attributes["tagname"] = "lineedit"; macro.widgets.attributes["name"] = "mywidget"; macro.widgets.attributes["value"] = "myvalue"; macro.widgets.attributes["map"] = "mapvalue"; macro.widgets.widgets.push_back(macro.widgets); Database db("testdb", "", "", "", "", ""); LUAQueryMapper mapper; std::string result; Fields fields; QueryResult queryresult; // Test simple result = widgetgenerator(PATIENTID, macro, mapper, db); printf("[%s]\n", result.c_str()); if(result != " \n" " \n" " \n") return 1; } printf("Positive tests:\n"); { Macro macro; macro.widgets.attributes["tagname"] = "lineedit"; macro.widgets.attributes["name"] = "mywidget"; macro.widgets.attributes["value"] = "myvalue"; macro.widgets.attributes["map"] = "mapvalue"; Database db("testdb", "", "", "", "", ""); LUAQueryMapper mapper; std::string result; Fields fields; QueryResult queryresult; // Test simple result = widgetgenerator(PATIENTID, macro, mapper, db); printf("[%s]\n", result.c_str()); if(result != " \n") return 1; // Make a database commit and test if the value shows up fields["mywidget"] = "testval"; db.commitTransaction("testuser", PATIENTID, macro, fields, now); result = widgetgenerator(PATIENTID, macro, mapper, db); printf("[%s]\n", result.c_str()); if(result != " \n") return 1; // Make a query result (newer than the db value) and see if it shows up queryresult.timestamp = now + 1; queryresult.source = "testsource"; queryresult.values["mapvalue"] = "mymapvalue"; mapper.addQueryResult(queryresult); result = widgetgenerator(PATIENTID, macro, mapper, db); printf("[%s]\n", result.c_str()); if(result != " \n") return 1; // Make another db value (newer than the query result) and see if it shows up. fields["mywidget"] = "testval2"; db.commitTransaction("testuser", PATIENTID, macro, fields, now + 2); result = widgetgenerator(PATIENTID, macro, mapper, db); printf("[%s]\n", result.c_str()); if(result != " \n") return 1; } printf("Negative tests:\n"); { Macro macro; macro.widgets.attributes["tagname"] = "lineedit"; macro.widgets.attributes["name"] = "mywidget"; macro.widgets.attributes["value"] = "myvalue"; macro.widgets.attributes["map"] = "mapvalue"; Database db("testdb", "", "", "", "", ""); LUAQueryMapper mapper; std::string result; Fields fields; QueryResult queryresult; // Test simple result = widgetgenerator(PATIENTID, macro, mapper, db); printf("[%s]\n", result.c_str()); if(result != " \n") return 1; // Make a database commit too old, and test if the value shows up fields["mywidget"] = "testval"; db.commitTransaction("testuser", PATIENTID, macro, fields, now - Conf::db_max_ttl - 1); result = widgetgenerator(PATIENTID, macro, mapper, db); printf("[%s]\n", result.c_str()); if(result == " \n") return 1; // Make a too old query result (newer than the db value) and see if it shows up queryresult.timestamp = now - Conf::pentominos_max_ttl - 1; queryresult.source = "testsource"; queryresult.values["mapvalue"] = "mymapvalue"; mapper.addQueryResult(queryresult); result = widgetgenerator(PATIENTID, macro, mapper, db); printf("[%s]\n", result.c_str()); if(result == " \n") return 1; } return 0; } #endif/*TEST_WIDGETGENERATOR*/