Added support for re-parenting a node

This commit is contained in:
Kristian Flikka
2013-11-20 13:48:55 +01:00
parent de095b5cf9
commit c69beedb30
8 changed files with 196 additions and 57 deletions

View File

@@ -31,21 +31,28 @@ namespace Opm {
}
GroupTreeNodePtr GroupTree::updateTree(const std::string& childName) {
if (getNode(childName)) {
throw std::invalid_argument("Node \"" + childName + "\" is already in tree, cannot move (yet)");
}
return m_root->addChildGroup(childName);
return updateTree(childName, m_root->name());
}
GroupTreeNodePtr GroupTree::updateTree(const std::string& childName, const std::string& parentName) {
if (getNode(childName)) {
throw std::invalid_argument("Node \"" + childName + "\" is already in tree, cannot move (yet)");
if (childName == m_root->name()) {
throw std::domain_error("Error, trying to add node with the same name as the root, offending name: " + childName);
}
GroupTreeNodePtr parentNode = getNode(parentName);
if (!parentNode) {
parentNode = updateTree(parentName);
GroupTreeNodePtr newParentNode = getNode(parentName);
if (!newParentNode) {
newParentNode = updateTree(parentName);
}
GroupTreeNodePtr childNodeInTree = getNode(childName);
if (childNodeInTree) {
GroupTreeNodePtr currentParent = getParent(childName);
currentParent->removeChild(childNodeInTree);
newParentNode->addChildGroup(childNodeInTree);
return childNodeInTree;
} else {
return newParentNode->addChildGroup(childName);
}
return parentNode->addChildGroup(childName);
}
GroupTreeNodePtr GroupTree::getNode(const std::string& nodeName) const {
@@ -59,7 +66,28 @@ namespace Opm {
} else {
std::map<std::string, GroupTreeNodePtr>::iterator iter = current->begin();
while (iter != current->end()) {
GroupTreeNodePtr result = getNode(nodeName, (*iter).second);
GroupTreeNodePtr result = getNode(nodeName, (*iter).second);
if (result) {
return result;
}
++iter;
}
return GroupTreeNodePtr();
}
}
GroupTreeNodePtr GroupTree::getParent(const std::string& childName) const {
GroupTreeNodePtr currentChild = m_root;
return getParent(childName, currentChild, GroupTreeNodePtr());
}
GroupTreeNodePtr GroupTree::getParent(const std::string& childName, GroupTreeNodePtr currentChild, GroupTreeNodePtr parent) const {
if (currentChild->name() == childName) {
return parent;
} else {
std::map<std::string, GroupTreeNodePtr>::iterator iter = currentChild->begin();
while (iter != currentChild->end()) {
GroupTreeNodePtr result = getParent(childName, (*iter).second, currentChild);
if (result) {
return result;
}
@@ -100,7 +128,7 @@ namespace Opm {
std::map<std::string, GroupTreeNodePtr >::iterator iter = fromNode->begin();
while (iter != fromNode->end()) {
GroupTreeNodePtr child = (*iter).second;
std::cout << "<-" << child->name() << "(" << child.get() << ")" << std::endl;
std::cout << "<-" << child->name() << "(" << child.get() << ")" << std::endl;
printTree(child);
++iter;
}

View File

@@ -32,9 +32,11 @@ namespace Opm {
public:
GroupTree();
GroupTreeNodePtr updateTree(const std::string& childName);
GroupTreeNodePtr updateTree(const std::string& childName, const std::string& parentName );
GroupTreeNodePtr updateTree(const std::string& childName, const std::string& parentName);
GroupTreeNodePtr getNode(const std::string& nodeName) const;
GroupTreeNodePtr getParent(const std::string& childName) const;
boost::shared_ptr<GroupTree> deepCopy() const;
void printTree() const;
@@ -42,11 +44,10 @@ namespace Opm {
private:
GroupTreeNodePtr m_root;
GroupTreeNodePtr getNode(const std::string& nodeName, GroupTreeNodePtr current) const;
GroupTreeNodePtr getParent(const std::string& childName, GroupTreeNodePtr currentChild, GroupTreeNodePtr parent) const;
void deepCopy(GroupTreeNodePtr origin, GroupTreeNodePtr copy) const;
void printTree(GroupTreeNodePtr fromNode) const;
};
typedef boost::shared_ptr<GroupTree> GroupTreePtr;

View File

@@ -24,30 +24,35 @@ namespace Opm {
GroupTreeNode::GroupTreeNode(const std::string& name) {
m_name = name;
m_parent = NULL;
}
GroupTreeNode::GroupTreeNode(const std::string& name, GroupTreeNode * parent) {
m_name = name;
m_parent = parent;
}
const std::string& GroupTreeNode::name() const {
return m_name;
}
GroupTreeNode * GroupTreeNode::parent() const {
return m_parent;
}
GroupTreeNodePtr GroupTreeNode::addChildGroup(const std::string& childName) {
if (hasChildGroup(childName)) {
throw std::invalid_argument("Child group with name \"" + childName + "\"already exists.");
}
GroupTreeNodePtr child(new GroupTreeNode(childName, this));
GroupTreeNodePtr child(new GroupTreeNode(childName));
m_childGroups[childName] = child;
return child;
}
void GroupTreeNode::addChildGroup(boost::shared_ptr<GroupTreeNode> childGroup) {
if (hasChildGroup(childGroup->name())) {
throw std::invalid_argument("Child group with name \"" + childGroup->name() + "\"already exists under node " + m_name);
}
m_childGroups[childGroup->name()] = childGroup;
}
void GroupTreeNode::removeChild(GroupTreeNodePtr child) {
if (!hasChildGroup(child->name())) {
throw std::invalid_argument("The node " + m_name + " does not have a child named " + child->name());
}
m_childGroups.erase(child->name());
}
bool GroupTreeNode::hasChildGroup(const std::string& childName) const {
return m_childGroups.find(childName) != m_childGroups.end();

View File

@@ -32,12 +32,13 @@ namespace Opm {
class GroupTreeNode {
public:
const std::string& name() const;
GroupTreeNode * parent() const;
boost::shared_ptr<GroupTreeNode> addChildGroup(const std::string& childName);
void addChildGroup(boost::shared_ptr<GroupTreeNode> childGroup);
bool hasChildGroup(const std::string& childName) const;
void removeChild(boost::shared_ptr<GroupTreeNode> child);
boost::shared_ptr<GroupTreeNode> getChildGroup(const std::string& childName);
void setParent(GroupTreeNode * parent);
static boost::shared_ptr<GroupTreeNode> createFieldNode();
std::map<std::string, boost::shared_ptr<GroupTreeNode> >::iterator begin();
std::map<std::string, boost::shared_ptr<GroupTreeNode> >::iterator end();
@@ -45,10 +46,8 @@ namespace Opm {
private:
GroupTreeNode(const std::string& name);
GroupTreeNode(const std::string& name, GroupTreeNode * parent);
std::string m_name;
std::map<std::string, boost::shared_ptr<GroupTreeNode> > m_childGroups;
GroupTreeNode * m_parent;
};
typedef boost::shared_ptr<GroupTreeNode> GroupTreeNodePtr;

View File

@@ -33,20 +33,6 @@ BOOST_AUTO_TEST_CASE(CreateFieldNode) {
BOOST_CHECK_EQUAL("FIELD", node->name());
}
BOOST_AUTO_TEST_CASE(CreateFieldNode_HasNoParent) {
GroupTreeNodePtr node = GroupTreeNode::createFieldNode();
BOOST_CHECK(!node->parent());
}
BOOST_AUTO_TEST_CASE(CreateChild_WithFieldParent_ParentSet) {
GroupTreeNodePtr fieldNode = GroupTreeNode::createFieldNode();
GroupTreeNodePtr child = fieldNode->addChildGroup("Child");
BOOST_CHECK_EQUAL(fieldNode.get(), child->parent());
}
BOOST_AUTO_TEST_CASE(CreateChild_WithFieldParent_ParentHasChild) {
GroupTreeNodePtr fieldNode = GroupTreeNode::createFieldNode();
BOOST_CHECK(!fieldNode->hasChildGroup("Child"));
@@ -55,16 +41,38 @@ BOOST_AUTO_TEST_CASE(CreateChild_WithFieldParent_ParentHasChild) {
BOOST_CHECK_EQUAL(child, fieldNode->getChildGroup("Child"));
}
BOOST_AUTO_TEST_CASE(CreateChildGroup_ChildExists_Throws) {
GroupTreeNodePtr fieldNode = GroupTreeNode::createFieldNode();
GroupTreeNodePtr child = fieldNode->addChildGroup("Child");
BOOST_CHECK_THROW(fieldNode->addChildGroup("Child"), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(GetChildGroup_ChildNotExisting_Throws) {
GroupTreeNodePtr fieldNode = GroupTreeNode::createFieldNode();
GroupTreeNodePtr child = fieldNode->addChildGroup("Child2");
BOOST_CHECK_THROW(fieldNode->getChildGroup("Child"), std::invalid_argument);
}
}
BOOST_AUTO_TEST_CASE(RemoveChild_ChildNonExisting_Throws) {
GroupTreeNodePtr fieldNodeDummy = GroupTreeNode::createFieldNode();
GroupTreeNodePtr fieldNode = GroupTreeNode::createFieldNode();
GroupTreeNodePtr child = fieldNode->addChildGroup("Child1");
BOOST_CHECK_THROW(fieldNode->removeChild(fieldNodeDummy), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(RemoveChild_RemoveTwice_Throws) {
GroupTreeNodePtr fieldNodeDummy = GroupTreeNode::createFieldNode();
GroupTreeNodePtr fieldNode = GroupTreeNode::createFieldNode();
GroupTreeNodePtr child = fieldNode->addChildGroup("Child1");
BOOST_CHECK_NO_THROW(fieldNode->removeChild(child));;
BOOST_CHECK_THROW(fieldNode->removeChild(child), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(RemoveChild_ChildExists_ChildRemoved) {
GroupTreeNodePtr fieldNode = GroupTreeNode::createFieldNode();
GroupTreeNodePtr child = fieldNode->addChildGroup("Child1");
BOOST_CHECK_NO_THROW(fieldNode->removeChild(child));
BOOST_CHECK(!fieldNode->hasChildGroup("Child1"));
}

View File

@@ -40,7 +40,20 @@ BOOST_AUTO_TEST_CASE(GetNode_NonExistingNode_ReturnsNull) {
BOOST_CHECK_EQUAL(GroupTreeNodePtr(), tree.getNode("Non-existing"));
}
BOOST_AUTO_TEST_CASE(AddNode_ParentNotSpecified_AddedUnderField) {
BOOST_AUTO_TEST_CASE(GetNodeAndParent_AllOK) {
GroupTree tree;
tree.updateTree("GRANDPARENT", "FIELD");
tree.updateTree("PARENT", "GRANDPARENT");
tree.updateTree("GRANDCHILD", "PARENT");
GroupTreeNodePtr grandchild = tree.getNode("GRANDCHILD");
BOOST_CHECK(grandchild);
GroupTreeNodePtr parent = tree.getParent("GRANDCHILD");
BOOST_CHECK_EQUAL("PARENT", parent->name());
BOOST_CHECK(parent->hasChildGroup("GRANDCHILD"));
}
BOOST_AUTO_TEST_CASE(UpdateTree_ParentNotSpecified_AddedUnderField) {
GroupTree tree;
tree.updateTree("CHILD_OF_FIELD");
BOOST_CHECK(tree.getNode("CHILD_OF_FIELD"));
@@ -48,7 +61,7 @@ BOOST_AUTO_TEST_CASE(AddNode_ParentNotSpecified_AddedUnderField) {
BOOST_CHECK(rootNode->hasChildGroup("CHILD_OF_FIELD"));
}
BOOST_AUTO_TEST_CASE(AddNode_ParentIsField_AddedUnderField) {
BOOST_AUTO_TEST_CASE(UpdateTree_ParentIsField_AddedUnderField) {
GroupTree tree;
tree.updateTree("CHILD_OF_FIELD", "FIELD");
BOOST_CHECK(tree.getNode("CHILD_OF_FIELD"));
@@ -56,7 +69,7 @@ BOOST_AUTO_TEST_CASE(AddNode_ParentIsField_AddedUnderField) {
BOOST_CHECK(rootNode->hasChildGroup("CHILD_OF_FIELD"));
}
BOOST_AUTO_TEST_CASE(AddNode_ParentNotAdded_ChildAndParentAdded) {
BOOST_AUTO_TEST_CASE(UpdateTree_ParentNotAdded_ChildAndParentAdded) {
GroupTree tree;
tree.updateTree("CHILD", "NEWPARENT");
BOOST_CHECK(tree.getNode("CHILD"));
@@ -66,6 +79,37 @@ BOOST_AUTO_TEST_CASE(AddNode_ParentNotAdded_ChildAndParentAdded) {
BOOST_CHECK(newParent->hasChildGroup("CHILD"));
}
BOOST_AUTO_TEST_CASE(UpdateTree_AddFieldNode_Throws) {
GroupTree tree;
BOOST_CHECK_THROW(tree.updateTree("FIELD", "NEWPARENT"), std::domain_error);
BOOST_CHECK_THROW(tree.updateTree("FIELD"), std::domain_error);
}
BOOST_AUTO_TEST_CASE(UpdateTree_ChildExists_ChildMoved) {
GroupTree tree;
tree.updateTree("OLDPARENT", "FIELD");
tree.updateTree("NEWPARENT", "FIELD");
tree.updateTree("THECHILD", "OLDPARENT");
tree.updateTree("GRANDCHILD1", "THECHILD");
tree.updateTree("GRANDCHILD2", "THECHILD");
GroupTreeNodePtr oldParent = tree.getNode("OLDPARENT");
BOOST_CHECK(oldParent->hasChildGroup("THECHILD"));
GroupTreeNodePtr theChild = oldParent->getChildGroup("THECHILD");
BOOST_CHECK(theChild->hasChildGroup("GRANDCHILD1"));
GroupTreeNodePtr newParent = tree.getNode("NEWPARENT");
BOOST_CHECK(!newParent->hasChildGroup("THECHILD"));
tree.updateTree("THECHILD", "NEWPARENT");
BOOST_CHECK(!oldParent->hasChildGroup("THECHILD"));
BOOST_CHECK(newParent->hasChildGroup("THECHILD"));
theChild = newParent->getChildGroup("THECHILD");
BOOST_CHECK(theChild->hasChildGroup("GRANDCHILD1"));
}
BOOST_AUTO_TEST_CASE(DeepCopy_TreeWithChildren_ObjectsDifferContentMatch) {
GroupTreePtr tree(new GroupTree());
tree->updateTree("L1CHILD1", "FIELD");
@@ -73,33 +117,33 @@ BOOST_AUTO_TEST_CASE(DeepCopy_TreeWithChildren_ObjectsDifferContentMatch) {
tree->updateTree("L2CHILD1", "L1CHILD1");
tree->updateTree("L2CHILD2", "L1CHILD1");
tree->updateTree("L3CHILD1", "L2CHILD1");
GroupTreePtr copiedTree = tree->deepCopy();
GroupTreeNodePtr fieldNodeCopy = copiedTree->getNode("FIELD");
GroupTreeNodePtr fieldNodeOriginal = tree->getNode("FIELD");
BOOST_CHECK(!(fieldNodeCopy == fieldNodeOriginal));
BOOST_CHECK_EQUAL(fieldNodeCopy->name(), fieldNodeOriginal->name());
GroupTreeNodePtr L1CHILD1NodeCopy = fieldNodeCopy->getChildGroup("L1CHILD1");
GroupTreeNodePtr L1CHILD1NodeOriginal = fieldNodeOriginal->getChildGroup("L1CHILD1");
BOOST_CHECK(!(L1CHILD1NodeCopy == L1CHILD1NodeOriginal));
BOOST_CHECK_EQUAL(L1CHILD1NodeCopy->name(), L1CHILD1NodeOriginal->name());
GroupTreeNodePtr L1CHILD2NodeCopy = fieldNodeCopy->getChildGroup("L1CHILD2");
GroupTreeNodePtr L1CHILD2NodeOriginal = fieldNodeOriginal->getChildGroup("L1CHILD2");
BOOST_CHECK(!(L1CHILD2NodeCopy == L1CHILD2NodeOriginal));
BOOST_CHECK_EQUAL(L1CHILD2NodeCopy->name(), L1CHILD2NodeOriginal->name());
GroupTreeNodePtr L2CHILD1NodeCopy = L1CHILD1NodeCopy->getChildGroup("L2CHILD1");
GroupTreeNodePtr L2CHILD1NodeOriginal = L1CHILD1NodeOriginal->getChildGroup("L2CHILD1");
BOOST_CHECK(!(L2CHILD1NodeCopy == L2CHILD1NodeOriginal));
BOOST_CHECK_EQUAL(L2CHILD1NodeCopy->name(), L2CHILD1NodeOriginal->name());
GroupTreeNodePtr L2CHILD2NodeCopy = L1CHILD1NodeCopy->getChildGroup("L2CHILD2");
GroupTreeNodePtr L2CHILD2NodeOriginal = L1CHILD1NodeOriginal->getChildGroup("L2CHILD2");
BOOST_CHECK(!(L2CHILD2NodeCopy == L2CHILD2NodeOriginal));
BOOST_CHECK_EQUAL(L2CHILD2NodeCopy->name(), L2CHILD2NodeOriginal->name());
GroupTreeNodePtr L3CHILD1NodeCopy = L2CHILD1NodeCopy->getChildGroup("L3CHILD1");
GroupTreeNodePtr L3CHILD1NodeOriginal = L2CHILD1NodeOriginal->getChildGroup("L3CHILD1");
BOOST_CHECK(!(L3CHILD1NodeCopy == L3CHILD1NodeOriginal));

View File

@@ -189,6 +189,40 @@ BOOST_AUTO_TEST_CASE(GroupTreeTest_WELSPECS_AND_GRUPTREE_correct_tree) {
BOOST_CHECK_EQUAL("GROUP_NILS", GROUP_NILS->name());
};
BOOST_AUTO_TEST_CASE(GroupTreeTest_GRUPTREE_WITH_REPARENT_correct_tree) {
ParserPtr parser(new Parser());
boost::filesystem::path scheduleFile("testdata/integration_tests/SCHEDULE/SCHEDULE_GROUPS_REPARENT");
DeckPtr deck = parser->parse(scheduleFile.string());
ScheduleConstPtr schedule(new Schedule(deck));
schedule->getGroupTree(0)->printTree();
std::cout << std::endl << std::endl;
schedule->getGroupTree(1)->printTree();
// Time , from first GRUPTREE
GroupTreeNodePtr root0 = schedule->getGroupTree(0)->getNode("FIELD");
BOOST_REQUIRE_EQUAL("FIELD", root0->name());
BOOST_CHECK(root0->hasChildGroup("GROUP_BJARNE"));
GroupTreeNodePtr GROUP_BJARNE0 = root0->getChildGroup("GROUP_BJARNE");
BOOST_CHECK_EQUAL("GROUP_BJARNE", GROUP_BJARNE0->name());
BOOST_CHECK(root0->hasChildGroup("GROUP_NEW"));
GroupTreeNodePtr GROUP_NEW0 = root0->getChildGroup("GROUP_NEW");
BOOST_CHECK_EQUAL("GROUP_NEW", GROUP_NEW0->name());
BOOST_CHECK(GROUP_BJARNE0->hasChildGroup("GROUP_BIRGER"));
GroupTreeNodePtr GROUP_BIRGER0 = GROUP_BJARNE0->getChildGroup("GROUP_BIRGER");
BOOST_CHECK_EQUAL("GROUP_BIRGER", GROUP_BIRGER0->name());
BOOST_CHECK(GROUP_NEW0->hasChildGroup("GROUP_NILS"));
GroupTreeNodePtr GROUP_NILS0 = GROUP_NEW0->getChildGroup("GROUP_NILS");
BOOST_CHECK_EQUAL("GROUP_NILS", GROUP_NILS0->name());
// SÅ den nye strukturen med et barneflytt
};
BOOST_AUTO_TEST_CASE(GroupTreeTest_PrintGrouptree) {
ParserPtr parser(new Parser());
boost::filesystem::path scheduleFile("testdata/integration_tests/SCHEDULE/SCHEDULE_WELSPECS_GROUPS");

View File

@@ -0,0 +1,20 @@
START -- Time 0
10 MAI 2007 /
SCHEDULE
GRUPTREE
'GROUP_BIRGER' 'GROUP_BJARNE' / -- BJARNE under FIELD, BIRGER under BJARNE
'GROUP_NILS' 'GROUP_NEW' / -- NILS under NEW, NEW should be under FIELD
/
TSTEP -- Time 1
10 /
GRUPTREE
'GROUP_BIRGER' 'GROUP_NEW' / -- Move BIRGER to NEW, i.e. NEW should now have NILS AND BIRGER, and BJARNE is childless
/