From 4873e6df45424d2132dc9685f76bcbe2d9dd447e Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 17 May 2012 11:43:16 +0200 Subject: Make persistent store (XML). --- src/taskmanager.cc | 68 +++++++++++++++++++++++++++++++++----------- src/taskmanager.h | 6 +++- src/tasktree.cc | 58 ++++++++++++++++++++++++++++++++++++-- src/tasktree.h | 19 +++++++++---- src/xmlparser.cc | 83 ++++++++++++++++++++---------------------------------- src/xmlparser.h | 27 ++++++------------ 6 files changed, 164 insertions(+), 97 deletions(-) diff --git a/src/taskmanager.cc b/src/taskmanager.cc index 87cf2b0..6ebffd5 100644 --- a/src/taskmanager.cc +++ b/src/taskmanager.cc @@ -44,29 +44,45 @@ static bool isProtected(taskid_t id) return id < FIRST_TASK_ID; } -TaskManager::TaskManager() { +TaskManager::TaskManager(std::string file) { idCount = FIRST_TASK_ID; - task_t t; - t.title = "root"; - t.id = ROOT_ID; - tree.insertAsChild(0, ROOT_ID, t); + this->file = file; + + FILE *fp = fopen(file.c_str(), "r"); + if(fp) { + std::string xml; + while(!feof(fp)) { + char buf[64]; + size_t sz = fread(buf, 1, sizeof(buf), fp); + xml.append(buf, sz); + } + tree.fromXML(xml); + fclose(fp); + } else { - t.title = "Finished"; - t.id = FINISHED_ID; - tree.insertAsChild(ROOT_ID, FINISHED_ID, t); + // Create new basis config + task_t t; + t.title = "root"; + t.id = ROOT_ID; + tree.insertAsChild(0, ROOT_ID, t); - t.title = "Backlog"; - t.id = BACKLOG_ID; - tree.insertAsChild(ROOT_ID, BACKLOG_ID, t); + t.title = "Finished"; + t.id = FINISHED_ID; + tree.insertAsChild(ROOT_ID, FINISHED_ID, t); - t.title = "Lost+Found"; - t.id = LOSTFOUND_ID; - tree.insertAsChild(ROOT_ID, LOSTFOUND_ID, t); + t.title = "Backlog"; + t.id = BACKLOG_ID; + tree.insertAsChild(ROOT_ID, BACKLOG_ID, t); - t.title = "Projects"; - t.id = PROJECTS_ID; - tree.insertAsChild(ROOT_ID, PROJECTS_ID, t); + t.title = "Lost+Found"; + t.id = LOSTFOUND_ID; + tree.insertAsChild(ROOT_ID, LOSTFOUND_ID, t); + + t.title = "Projects"; + t.id = PROJECTS_ID; + tree.insertAsChild(ROOT_ID, PROJECTS_ID, t); + } tree.toStdOut(); } @@ -96,6 +112,8 @@ TaskIdList TaskManager::moveTask(taskid_t id, taskid_t to) throw e; } + flushTasks(); + return affectedTasks; } @@ -115,6 +133,8 @@ TaskIdList TaskManager::removeTask(taskid_t id) throw e; } + flushTasks(); + return affectedTasks; } @@ -132,6 +152,8 @@ TaskIdList TaskManager::updateTask(taskid_t id, task_t t) throw e; } + flushTasks(); + return affectedTasks; } @@ -152,6 +174,8 @@ TaskIdList TaskManager::createTask(taskid_t parentid, taskid_t *pid) throw e; } + flushTasks(); + return affectedTasks; } @@ -188,6 +212,16 @@ TaskIdList TaskManager::ancestorList(taskid_t id) } */ +void TaskManager::flushTasks() +{ + FILE *fp = fopen(file.c_str(), "w"); + if(!fp) return; + std::string xml = tree.toXML(); + fwrite(xml.c_str(), xml.size(), 1, fp); + fclose(fp); +} + + #if 0 TaskList tasklist; diff --git a/src/taskmanager.h b/src/taskmanager.h index dc0cf1c..fbd38ec 100644 --- a/src/taskmanager.h +++ b/src/taskmanager.h @@ -38,7 +38,7 @@ class TaskManager { public: - TaskManager(); + TaskManager(std::string file = "/tmp/munia.xml"); ~TaskManager(); TaskIdList createTask(taskid_t parentid, taskid_t *id) throw (std::exception); @@ -52,11 +52,15 @@ public: task_t task(taskid_t t); + void flushTasks(); + private: // TaskIdList ancestorList(taskid_t task); taskid_t createId(); taskid_t idCount; task_t nextTask(); + + std::string file; }; extern TaskManager task_manager; diff --git a/src/tasktree.cc b/src/tasktree.cc index fc84efa..2576600 100644 --- a/src/tasktree.cc +++ b/src/tasktree.cc @@ -27,10 +27,39 @@ */ #include "tasktree.h" +#include "xmlparser.h" + #include "debug.h" +#include "xml_encode_decode.h" + #define ROOT_PARENT_ID -1 +static inline std::string id2str(taskid_t id) +{ + char buf[32]; + sprintf(buf, "%u", id); + return buf; +} + +std::string node::toXML(std::string prefix) +{ + std::string xml; + + xml += prefix + "\n"; + xml += prefix + " " + xml_encode(data.title) + "\n"; + xml += prefix + " \n"; + NodeList::iterator ni = children.begin(); + while(ni != children.end()) { + xml += (*ni)->toXML(prefix + " "); + ni++; + } + xml += prefix + " \n"; + xml += prefix + "\n"; + + return xml; +} + static void concatTaskIdLists(TaskIdList& pre, TaskIdList& post) { pre.insert(pre.end(), post.begin(), post.end()); // for(TaskIdList::iterator it = post.begin(); @@ -187,7 +216,7 @@ task_t TaskTree::data(taskid_t id) try { node_t* node = id2node.at(id); task_t tmp = node->data; - t.id = tmp.id; + t.id = node->id; t.title = tmp.title; // printf("!!!!t.id and tmp.id in data: %d and %d\n", t.id, tmp.id); if(node->parent) t.parentid = node->parent->id; @@ -267,14 +296,18 @@ node_t* TaskTree::createNode(taskid_t id) { } void TaskTree::insertChild(node_t* parent, node_t* child) { - parent->children.push_back(child); + if(parent) parent->children.push_back(child); + else { + rootid = child->id; + root = child; + } child->parent = parent; } static void printNode(node_t* node, std::string prefix) { if(!node) return; task_t t = node->data; - printf("%s- %u - %s (%p)\n", prefix.c_str(), t.id, t.title.c_str(), node); + printf("%s- %u - %s (%p)\n", prefix.c_str(), node->id, t.title.c_str(), node); NodeList::iterator it; for(it = node->children.begin(); it != node->children.end(); it++) { @@ -287,6 +320,25 @@ void TaskTree::toStdOut() { printNode(root, ""); } +std::string TaskTree::toXML() +{ + node_t *root = id2node.at(rootid); + + std::string xml; + xml += "\n"; + xml += "\n"; + xml += root->toXML(" "); + xml += ""; + + return xml; +} + +void TaskTree::fromXML(std::string xml) +{ + XmlParser p(this); + p.parse(xml.c_str(), xml.size()); +} + #ifdef TEST_TASKTREE //Additional dependency files diff --git a/src/tasktree.h b/src/tasktree.h index d82b9a4..64ce0b6 100644 --- a/src/tasktree.h +++ b/src/tasktree.h @@ -34,18 +34,24 @@ #include "task.h" -typedef struct node node_t; +class node; +typedef std::list NodeList; -typedef std::list NodeList; - -struct node { +class node +{ +public: taskid_t id; - node_t* parent; + node* parent; task_t data; NodeList children; + + std::string toXML(std::string prefix); }; +typedef node node_t; + class TaskTree { + friend class XmlParser; public: TaskTree(); ~TaskTree(); @@ -62,6 +68,9 @@ public: void toStdOut(); + std::string toXML(); + void fromXML(std::string xml); + private: node_t* createNode(taskid_t id); void insertChild(node_t* parent, node_t* child); diff --git a/src/xmlparser.cc b/src/xmlparser.cc index 97a8bdb..112ea00 100644 --- a/src/xmlparser.cc +++ b/src/xmlparser.cc @@ -31,73 +31,50 @@ #include "xml_encode_decode.h" -XmlParser::XmlParser(std::string filename) { - // open file handler - fp = fopen(filename.c_str(), "r"); - if(!fp) { - fprintf(stderr, "Could not open file\n"); - } - - task = NULL; - tasklist.clear(); +#define NOID 0xffffffff - open_tagtype = none; +XmlParser::XmlParser(TaskTree *t) : tree(t) +{ } -XmlParser::~XmlParser() { - // close file handler - fclose(fp); - if(task) delete task; +XmlParser::~XmlParser() +{ } -void XmlParser::characterData(std::string& data) { - characterbuf += data; - - /* - switch(open_tagtype) { - case title: - // task->title += xml_decode(data); - break; - case desc: - // task->desc += xml_decode(data); - break; - default: - break; - } - */ +void XmlParser::characterData(const std::string &data) +{ + cdata += data; } -void XmlParser::startTag(std::string name, attributes_t &attr) { - // printf("start: %s\n", name.c_str()); - characterbuf.clear(); +void XmlParser::startTag(std::string name, attributes_t &attr) +{ if(name == "task") { - if(task) delete task; + taskid_t id = atoi(xml_decode(attr["id"]).c_str()); + + node_t* parent = NULL; + if(parents.size() != 0) parent = tree->id2node.at(parents.top()); + + node = tree->createNode(id); + tree->insertChild(parent, node); + } - task = new task_t(); - task->id = atoi(xml_decode(attr["id"]).c_str()); - // task->parent_id = atoi(xml_decode(attr["parent_id"]).c_str()); + if(name == "children") { + parents.push(node->id); } + cdata = ""; } -void XmlParser::endTag(std::string name) { - // printf("end: %s\n", name.c_str()); - if (name == "task") { - // if(task) tasklist.push_back(*task); - } - else if (name == "title") { - if(task) task->title = characterbuf; - // open_tagtype = title; +void XmlParser::endTag(std::string name) +{ + if(name == "task") { } - else if (name == "desc") { - if(task) task->desc = characterbuf; - // open_tagtype = desc; + + if(name == "children") { + parents.pop(); } - // open_tagtype = none; -} -int XmlParser::readData(char* data, size_t size) { - if(!fp) return 0; // Could not read file - - return fread(data, 1, size, fp); + if (name == "title") { + node->data.title = cdata; + } } diff --git a/src/xmlparser.h b/src/xmlparser.h index a92a515..6f05650 100644 --- a/src/xmlparser.h +++ b/src/xmlparser.h @@ -31,32 +31,23 @@ #include "task.h" #include "saxparser.h" +#include +#include "tasktree.h" + class XmlParser : public SAXParser { public: - XmlParser(std::string filename); + XmlParser(TaskTree *tree); ~XmlParser(); void startTag(std::string name, attributes_t &attr); void endTag(std::string name); - void characterData(std::string& data); - - TaskIdList tasklist; - -protected: - int readData(char* data, size_t size); + void characterData(const std::string &data); private: - FILE* fp; - task_t* task; - std::string characterbuf; - - enum tag_t { - title, - desc, - none - }; - - tag_t open_tagtype; + std::stack parents; + std::string cdata; + node_t *node; + TaskTree *tree; }; #endif/*__MUNIA_XMLPARSER_H__*/ -- cgit v1.2.3