summaryrefslogtreecommitdiff
path: root/src/nodemanager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/nodemanager.cc')
-rw-r--r--src/nodemanager.cc407
1 files changed, 407 insertions, 0 deletions
diff --git a/src/nodemanager.cc b/src/nodemanager.cc
new file mode 100644
index 0000000..32a93b4
--- /dev/null
+++ b/src/nodemanager.cc
@@ -0,0 +1,407 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * node.cc
+ *
+ * Fri Feb 24 08:16:30 CET 2012
+ * Copyright 2012 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Munia.
+ *
+ * Munia 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.
+ *
+ * Munia 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 Munia; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "nodemanager.h"
+
+#include <stdio.h>
+
+#include "hugin.hpp"
+
+// Global NodeManager object.
+NodeManager node_manager;
+
+#define ROOT_ID 0
+#define FINISHED_ID 1
+#define BACKLOG_ID 2
+#define LOSTFOUND_ID 3
+#define PROJECTS_ID 4
+#define FIRST_NODE_ID 10
+
+static bool isProtected(nodeid_t id)
+{
+ return id < FIRST_NODE_ID;
+}
+
+NodeManager::NodeManager()
+{
+ idCount = FIRST_NODE_ID;
+}
+
+NodeManager::~NodeManager()
+{
+}
+
+void NodeManager::init(std::string filename)
+{
+ DEBUG(nodemgr, "Reading nodes from file: %s\n", filename.c_str());
+ file = filename;
+
+ 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
+ {
+
+ // Create new basis config
+ node_t t;
+
+ t.attributes["title"] = "root";
+ t.id = ROOT_ID;
+ tree.insertAsChild(0, ROOT_ID, t);
+
+ t.attributes["title"] = "Finished";
+ t.id = FINISHED_ID;
+ tree.insertAsChild(ROOT_ID, FINISHED_ID, t);
+
+ t.attributes["title"] = "Backlog";
+ t.id = BACKLOG_ID;
+ tree.insertAsChild(ROOT_ID, BACKLOG_ID, t);
+
+ t.attributes["title"] = "Lost+Found";
+ t.id = LOSTFOUND_ID;
+ tree.insertAsChild(ROOT_ID, LOSTFOUND_ID, t);
+
+ t.attributes["title"] = "Projects";
+ t.id = PROJECTS_ID;
+ tree.insertAsChild(ROOT_ID, PROJECTS_ID, t);
+ }
+
+ tree.toStdOut();
+}
+
+node_t NodeManager::node(nodeid_t t)
+{
+ return tree.data(t);
+}
+
+nodeid_t NodeManager::createId()
+{
+ return tree.createId();
+}
+
+NodeIdListPair NodeManager::moveNode(nodeid_t id, nodeid_t to)
+ throw (std::exception)
+{
+ if(isProtected(id))
+ {
+ return NodeIdListPair();
+ }
+
+ if(id == to)
+ {
+ throw std::exception(); // Node and new parent are the same node.
+ }
+
+ //node_t t = tree.data(id);
+
+ // Make sure the new parent exists. This will throw an exception if it doesn't
+ //node_t t_ = tree.data(to);
+
+ //t.parentid = to;
+
+ //NodeIdList tilremove = tree.remove(id);
+ NodeIdList tilremove;
+ tilremove.push_back(id);
+ NodeIdList ancestors = tree.ancestorList(id);
+ tilremove.insert(tilremove.end(), ancestors.begin(), ancestors.end());
+
+ // NodeIdList tilcreate = tree.insertAsChild(to, id, t);
+ NodeIdList tilcreate;
+ tilcreate.push_back(to);
+ ancestors = tree.ancestorList(to);
+ tilcreate.insert(tilcreate.end(), ancestors.begin(), ancestors.end());
+
+ tree.move(id, to);
+
+ NodeIdListPair tilpair;
+ tilpair.first = tilremove;
+ tilpair.second = tilcreate;
+
+ flushNodes();
+
+ return tilpair;
+}
+
+NodeIdList NodeManager::removeNode(nodeid_t id)
+ throw (std::exception)
+{
+ if(isProtected(id))
+ {
+ return NodeIdList();
+ }
+
+ NodeIdList affectedNodes;
+
+ if(tree.bfs(id).size() > 1)
+ {
+ throw std::exception();
+ }
+
+ try
+ {
+ affectedNodes = tree.remove(id);
+ }
+ catch(std::exception& e)
+ {
+ throw e;
+ }
+
+ flushNodes();
+
+ return affectedNodes;
+}
+
+NodeIdList NodeManager::updateNode(nodeid_t id, const std::string &name,
+ const std::string &value)
+ throw (std::exception)
+{
+ if(isProtected(id))
+ {
+ return NodeIdList();
+ }
+
+ NodeIdList affectedNodes;
+
+ try
+ {
+ affectedNodes = tree.updateData(id, name, value);
+ }
+ catch(std::exception& e)
+ {
+ throw e;
+ }
+
+ flushNodes();
+
+ return affectedNodes;
+}
+
+NodeIdList NodeManager::createNode(nodeid_t parentid, nodeid_t *pid)
+ throw (std::exception)
+{
+ NodeIdList affectedNodes;
+
+ node_t t;
+ nodeid_t id = *pid;//createId();
+ t.attributes["title"] = "";
+ t.id = id;
+ if(pid)
+ {
+ *pid = id;
+ }
+
+ try
+ {
+ affectedNodes = tree.insertAsChild(parentid, id, t);
+ }
+ catch(std::exception& e)
+ {
+ throw e;
+ }
+
+ flushNodes();
+
+ return affectedNodes;
+}
+
+NodeIdList NodeManager::subNodes(nodeid_t t)
+ throw (std::exception)
+{
+ NodeIdList affectedNodes;
+
+ try
+ {
+ affectedNodes = tree.bfs(t);
+ }
+ catch(std::exception& e)
+ {
+ throw e;
+ }
+
+ return affectedNodes;
+}
+
+//NodeIdList NodeManager::ancestorList(nodeid_t id)
+// throw (std::exception)
+//{
+// NodeIdList ancestors;
+//
+// try
+// {
+// ancestors = tree.ancestorList(id);
+// goto finish;
+// }
+// catch(std::exception& e)
+// {
+// throw e;
+// }
+//
+//finish:
+// return ancestors;
+//}
+
+void NodeManager::flushNodes()
+{
+ 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
+NodeList nodelist;
+
+node_t create_node(std::string title, std::string desc)
+{
+ node_t t;
+ t.parent_id = current_id_count();
+ t.attributes["title"] = title;
+ t.desc = desc;
+ t.id = id_count; id_count++;
+
+ return t;
+}
+
+NodeList load_nodelist_from_file(std::string file)
+{
+ NodeList list;
+
+ // create MuniaDb class which handles nodes, db-flush and db-init.
+
+ return list;
+}
+
+bool save_nodelist_to_file(NodeList list, std::string file)
+{
+ FILE* fp;
+
+ if(! (fp = fopen(file.c_str(), "w")))
+ {
+ return false;
+ }
+
+ if(!fprintf(fp, "<nodelist>\n"))
+ {
+ fclose(fp);
+ return false;
+ }
+
+ NodeList::iterator it;
+ for(it = nodelist.begin(); it != nodelist.end(); it++)
+ {
+ node_t t = *it;
+ int r = 1;
+
+ //printf("Flushing node %d\n", t.id);
+ r |= fprintf(fp, " <node id=\"%d\" parent_id=\"%d\">\n", t.id, t.parent_id);
+ r |= fprintf(fp, " <title>%s</title>\n", xml_encode(t.attributes["title"]).c_str());
+ r |= fprintf(fp, " <desc>%s</desc>\n", xml_encode(t.attributes["description"]).c_str());
+ r |= fprintf(fp, " </node>)\n");
+
+ if(!r)
+ {
+ fclose(fp);
+ return false;
+ }
+ }
+
+ if(!fprintf(fp, "</nodelist>\n"))
+ {
+ fclose(fp);
+ return false;
+ }
+
+ fclose(fp);
+ return true;
+}
+
+static void delete_node(node_t t, NodeList& graveyard);
+
+static void delete_children(node_t t, NodeList& graveyard)
+{
+ NodeList::iterator it;
+ for(it = nodelist.begin(); it != nodelist.end(); it++)
+ {
+ if(it->parent_id == t.id) {
+ delete_node(*it, graveyard);
+ }
+ }
+}
+
+static void delete_node(node_t t, NodeList& graveyard)
+{
+ NodeList::iterator it;
+ for(it = nodelist.begin(); it != nodelist.end(); it++)
+ {
+ if(it->id == t.id)
+ {
+ break;
+ }
+ }
+
+ if(it != nodelist.end())
+ {
+ graveyard.push_back(*it);
+ delete_children(*it, graveyard);
+ }
+}
+
+void delete_node(int id, NodeList& graveyard)
+{
+ node_t t;
+ t.id = id;
+ delete_node(t, graveyard);
+
+ for(NodeList::iterator it = graveyard.begin();
+ it != graveyard.end(); it++)
+ {
+ for(NodeList::iterator it_tl = nodelist.begin();
+ it_tl != nodelist.end(); it_tl++)
+ {
+ if(it_tl->id == it->id)
+ {
+ nodelist.erase(it_tl);
+ break;
+ }
+ }
+ }
+}
+#endif