Skip to content

Commit

Permalink
#5623: Start adding tests to cover the merge action generation
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed May 24, 2021
1 parent 338d4df commit 0aaa20c
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 151 deletions.
186 changes: 186 additions & 0 deletions libs/scene/merge/MergeAction.h
@@ -1,6 +1,9 @@
#pragma once

#include <memory>
#include "ientity.h"
#include "../Clone.h"
#include "../scenelib.h"

namespace scene
{
Expand Down Expand Up @@ -45,6 +48,189 @@ class MergeAction
virtual void applyChanges() = 0;
};

// Various implementations of the above MergeAction base type following

class RemoveNodeFromParentAction :
public MergeAction
{
private:
scene::INodePtr _nodeToRemove;

protected:
RemoveNodeFromParentAction(const scene::INodePtr& nodeToRemove, ActionType type) :
MergeAction(type),
_nodeToRemove(nodeToRemove)
{
assert(_nodeToRemove);
}

const scene::INodePtr& getNodeToRemove() const
{
return _nodeToRemove;
}

public:
void applyChanges() override
{
removeNodeFromParent(_nodeToRemove);
}
};

class RemoveChildAction :
public RemoveNodeFromParentAction
{
public:
RemoveChildAction(const scene::INodePtr& node) :
RemoveNodeFromParentAction(node, ActionType::RemoveChildNode)
{}
};

class RemoveEntityAction :
public RemoveNodeFromParentAction
{
public:
RemoveEntityAction(const scene::INodePtr& node) :
RemoveNodeFromParentAction(node, ActionType::RemoveEntity)
{}
};

class AddCloneToParentAction :
public MergeAction
{
private:
scene::INodePtr _node;
scene::INodePtr _parent;

protected:
// Will add the given node to the parent when applyChanges() is called
AddCloneToParentAction(const scene::INodePtr& node, const scene::INodePtr& parent, ActionType type) :
MergeAction(type),
_node(node),
_parent(parent)
{
assert(_node);
assert(Node_getCloneable(node));
}

public:
void applyChanges() override
{
// No post-clone callback since we don't care about selection groups right now
auto cloned = cloneNodeIncludingDescendants(_node, PostCloneCallback());

if (!cloned)
{
throw std::runtime_error("Node " + _node->name() + " is not cloneable");
}

addNodeToContainer(cloned, _parent);
}

const scene::INodePtr& getParent() const
{
return _parent;
}

const scene::INodePtr& getSourceNodeToAdd() const
{
return _node;
}
};

class AddEntityAction :
public AddCloneToParentAction
{
public:
AddEntityAction(const scene::INodePtr& node, const scene::IMapRootNodePtr& targetRoot) :
AddCloneToParentAction(node, targetRoot, ActionType::AddEntity)
{}
};

class AddChildAction :
public AddCloneToParentAction
{
public:
AddChildAction(const scene::INodePtr& node, const scene::INodePtr& parent) :
AddCloneToParentAction(node, parent, ActionType::AddChildNode)
{}
};

class SetEntityKeyValueAction :
public MergeAction
{
private:
scene::INodePtr _node;
std::string _key;
std::string _value;

public:
// Will call setKeyValue(key, value) on the targetnode when applyChanges() is called
SetEntityKeyValueAction(const scene::INodePtr& node, const std::string& key, const std::string& value, ActionType mergeActionType) :
MergeAction(mergeActionType),
_node(node),
_key(key),
_value(value)
{
assert(_node);
assert(Node_isEntity(_node));
assert(!_key.empty());
}

void applyChanges() override
{
// No post-clone callback since we don't care about selection groups right now
auto entity = Node_getEntity(_node);

if (!entity)
{
throw std::runtime_error("Node " + _node->name() + " is not an entity");
}

entity->setKeyValue(_key, _value);
}

const scene::INodePtr& getEntityNode() const
{
return _node;
}

const std::string& getKey() const
{
return _key;
}

const std::string& getValue() const
{
return _value;
}
};

class AddEntityKeyValueAction :
public SetEntityKeyValueAction
{
public:
AddEntityKeyValueAction(const scene::INodePtr& node, const std::string& key, const std::string& value) :
SetEntityKeyValueAction(node, key, value, ActionType::AddKeyValue)
{}
};

class RemoveEntityKeyValueAction :
public SetEntityKeyValueAction
{
public:
RemoveEntityKeyValueAction(const scene::INodePtr& node, const std::string& key) :
SetEntityKeyValueAction(node, key, std::string(), ActionType::RemoveKeyValue)
{}
};

class ChangeEntityKeyValueAction :
public SetEntityKeyValueAction
{
public:
ChangeEntityKeyValueAction(const scene::INodePtr& node, const std::string& key, const std::string& value) :
SetEntityKeyValueAction(node, key, value, ActionType::ChangeKeyValue)
{}
};

}

Expand Down
167 changes: 16 additions & 151 deletions libs/scene/merge/MergeOperation.cpp
Expand Up @@ -10,157 +10,6 @@ namespace scene
namespace merge
{

class RemoveNodeFromParentAction :
public MergeAction
{
private:
scene::INodePtr _child;

protected:
RemoveNodeFromParentAction(const scene::INodePtr& child, ActionType type) :
MergeAction(type),
_child(child)
{
assert(_child);
}

public:
void applyChanges() override
{
removeNodeFromParent(_child);
}
};

class RemoveChildAction :
public RemoveNodeFromParentAction
{
public:
RemoveChildAction(const scene::INodePtr& node) :
RemoveNodeFromParentAction(node, ActionType::RemoveChildNode)
{}
};

class RemoveEntityAction :
public RemoveNodeFromParentAction
{
public:
RemoveEntityAction(const scene::INodePtr& node) :
RemoveNodeFromParentAction(node, ActionType::RemoveEntity)
{}
};

class AddCloneToParentAction :
public MergeAction
{
private:
scene::INodePtr _node;
scene::INodePtr _parent;

protected:
// Will add the given node to the parent when applyChanges() is called
AddCloneToParentAction(const scene::INodePtr& node, const scene::INodePtr& parent, ActionType type) :
MergeAction(type),
_node(node),
_parent(parent)
{
assert(_node);
assert(Node_getCloneable(node));
}

public:
void applyChanges() override
{
// No post-clone callback since we don't care about selection groups right now
auto cloned = cloneNodeIncludingDescendants(_node, PostCloneCallback());

if (!cloned)
{
throw std::runtime_error("Node " + _node->name() + " is not cloneable");
}

addNodeToContainer(cloned, _parent);
}
};

class AddEntityAction :
public AddCloneToParentAction
{
public:
AddEntityAction(const scene::INodePtr& node, const scene::IMapRootNodePtr& targetRoot) :
AddCloneToParentAction(node, targetRoot, ActionType::AddEntity)
{}
};

class AddChildAction :
public AddCloneToParentAction
{
public:
AddChildAction(const scene::INodePtr& node, const scene::INodePtr& parent) :
AddCloneToParentAction(node, parent, ActionType::AddChildNode)
{}
};

class SetEntityKeyValueAction :
public MergeAction
{
private:
scene::INodePtr _node;
std::string _key;
std::string _value;

public:
// Will call setKeyValue(key, value) on the targetnode when applyChanges() is called
SetEntityKeyValueAction(const scene::INodePtr& node, const std::string& key, const std::string& value, ActionType mergeActionType) :
MergeAction(mergeActionType),
_node(node),
_key(key),
_value(value)
{
assert(_node);
assert(!_key.empty());
}

void applyChanges() override
{
// No post-clone callback since we don't care about selection groups right now
auto entity = Node_getEntity(_node);

if (!entity)
{
throw std::runtime_error("Node " + _node->name() + " is not an entity");
}

entity->setKeyValue(_key, _value);
}
};

class AddEntityKeyValueAction :
public SetEntityKeyValueAction
{
public:
AddEntityKeyValueAction(const scene::INodePtr& node, const std::string& key, const std::string& value) :
SetEntityKeyValueAction(node, key, value, ActionType::AddKeyValue)
{}
};

class RemoveEntityKeyValueAction :
public SetEntityKeyValueAction
{
public:
RemoveEntityKeyValueAction(const scene::INodePtr& node, const std::string& key) :
SetEntityKeyValueAction(node, key, std::string(), ActionType::RemoveKeyValue)
{}
};

class ChangeEntityKeyValueAction :
public SetEntityKeyValueAction
{
public:
ChangeEntityKeyValueAction(const scene::INodePtr& node, const std::string& key, const std::string& value) :
SetEntityKeyValueAction(node, key, value, ActionType::ChangeKeyValue)
{}
};

void MergeOperation::addAction(const MergeAction::Ptr& action)
{
_actions.push_back(action);
Expand Down Expand Up @@ -240,6 +89,22 @@ MergeOperation::Ptr MergeOperation::CreateFromComparisonResult(const ComparisonR
return operation;
}

void MergeOperation::applyActions()
{
for (auto& action : _actions)
{
action->applyChanges();
}
}

void MergeOperation::foreachAction(const std::function<void(const MergeAction::Ptr&)>& visitor)
{
for (const auto& action : _actions)
{
visitor(action);
}
}

}

}
5 changes: 5 additions & 0 deletions libs/scene/merge/MergeOperation.h
Expand Up @@ -35,6 +35,11 @@ class MergeOperation

void addAction(const MergeAction::Ptr& action);

// Executes all actions defined in this operation
void applyActions();

void foreachAction(const std::function<void(const MergeAction::Ptr&)>& visitor);

private:
void createActionsForEntity(const ComparisonResult::EntityDifference& difference);
void createActionsForKeyValueDiff(const ComparisonResult::KeyValueDifference& difference,
Expand Down

0 comments on commit 0aaa20c

Please sign in to comment.