App: circular reference testing routine for new links

DocumentObject::testIfLinkDAGCompatible: return true if link can be
created (no cycles will be made). False if the link will cause a
circular dependency and break recomputes.
This commit is contained in:
DeepSOIC 2015-07-08 21:36:39 +03:00 committed by Stefan Tröger
parent 5725dd7721
commit a1557d07da
3 changed files with 56 additions and 2 deletions

View File

@ -1662,8 +1662,11 @@ Document::getDependencyList(const std::vector<App::DocumentObject*>& objs) const
// this sort gives the execute
boost::topological_sort(DepList, std::front_inserter(make_order));
}
catch (const std::exception&) {
return std::vector<App::DocumentObject*>();
catch (const std::exception& e) {
std::stringstream ss;
ss << "Gathering all dependencies failed, probably due to circular dependencies. Error: ";
ss << e.what();
throw Base::Exception(ss.str().c_str());
}
std::set<Vertex> out;

View File

@ -172,6 +172,41 @@ DocumentObjectGroup* DocumentObject::getGroup() const
return DocumentObjectGroup::getGroupOfObject(this);
}
bool DocumentObject::testIfLinkDAGCompatible(DocumentObject *linkTo) const
{
std::vector<App::DocumentObject*> linkTo_in_vector;
linkTo_in_vector.reserve(1);
linkTo_in_vector.push_back(linkTo);
return this->testIfLinkDAGCompatible(linkTo_in_vector);
}
bool DocumentObject::testIfLinkDAGCompatible(const std::vector<DocumentObject *> &linksTo) const
{
Document* doc = this->getDocument();
if (!doc)
throw Base::Exception("DocumentObject::testIfLinkIsDAG: object is not in any document.");
std::vector<App::DocumentObject*> deplist = doc->getDependencyList(linksTo);
if( std::find(deplist.begin(),deplist.end(),this) != deplist.end() )
//found this in dependency list
return false;
else
return true;
}
bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSubList &linksTo) const
{
const std::vector<App::DocumentObject*> &linksTo_in_vector = linksTo.getValues();
return this->testIfLinkDAGCompatible(linksTo_in_vector);
}
bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSub &linkTo) const
{
std::vector<App::DocumentObject*> linkTo_in_vector;
linkTo_in_vector.reserve(1);
linkTo_in_vector.push_back(linkTo.getValue());
return this->testIfLinkDAGCompatible(linkTo_in_vector);
}
void DocumentObject::onLostLinkToObject(DocumentObject*)
{

View File

@ -26,6 +26,7 @@
#include <App/PropertyContainer.h>
#include <App/PropertyStandard.h>
#include <App/PropertyLinks.h>
#include <App/PropertyExpressionEngine.h>
#include <Base/TimeInfo.h>
@ -132,6 +133,21 @@ public:
/// get group if object is part of a group, otherwise 0 is returned
DocumentObjectGroup* getGroup() const;
/**
* @brief testIfLinkIsDAG tests a link that is about to be created for
* circular references.
* @param objToLinkIn (input). The object this object is to depend on after
* the link is going to be created.
* @return true if link can be created (no cycles will be made). False if
* the link will cause a circular dependency and break recomputes. Throws an
* error if the document already has a circular dependency.
* That is, if the return is true, the link is allowed.
*/
bool testIfLinkDAGCompatible(DocumentObject* linkTo) const;
bool testIfLinkDAGCompatible(const std::vector<DocumentObject *> &linksTo) const;
bool testIfLinkDAGCompatible(App::PropertyLinkSubList &linksTo) const;
bool testIfLinkDAGCompatible(App::PropertyLinkSub &linkTo) const;
public:
/** mustExecute