/* -*- 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 #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, -1); t.attributes["title"] = "Finished"; t.id = FINISHED_ID; tree.insertAsChild(ROOT_ID, FINISHED_ID, t, -1); t.attributes["title"] = "Backlog"; t.id = BACKLOG_ID; tree.insertAsChild(ROOT_ID, BACKLOG_ID, t, -1); t.attributes["title"] = "Lost+Found"; t.id = LOSTFOUND_ID; tree.insertAsChild(ROOT_ID, LOSTFOUND_ID, t, -1); t.attributes["title"] = "Projects"; t.id = PROJECTS_ID; tree.insertAsChild(ROOT_ID, PROJECTS_ID, t, -1); } 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, nodeid_t beforeId) 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, beforeId); 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, nodeid_t insertbeforeid) 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, insertbeforeid); } 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, "\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, " \n", t.id, t.parent_id); r |= fprintf(fp, " %s\n", xml_encode(t.attributes["title"]).c_str()); r |= fprintf(fp, " %s\n", xml_encode(t.attributes["description"]).c_str()); r |= fprintf(fp, " )\n"); if(!r) { fclose(fp); return false; } } if(!fprintf(fp, "\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