PropertyExpressionEngine: Refactored and moved visitor code to separate file.
This commit is contained in:
parent
095c823fda
commit
810135fad4
|
@ -85,6 +85,7 @@ SET(Document_HPP_SRCS
|
|||
DocumentObserver.h
|
||||
DocumentObserverPython.h
|
||||
Expression.h
|
||||
ExpressionVisitors.h
|
||||
FeatureCustom.h
|
||||
FeaturePython.h
|
||||
FeaturePythonPyImp.h
|
||||
|
|
|
@ -1100,11 +1100,21 @@ void VariableExpression::setPath(const ObjectIdentifier &path)
|
|||
var = path;
|
||||
}
|
||||
|
||||
bool VariableExpression::validDocumentObjectRename(const std::string &oldName, const std::string &newName)
|
||||
{
|
||||
return var.validDocumentObjectRename(oldName, newName);
|
||||
}
|
||||
|
||||
bool VariableExpression::renameDocumentObject(const std::string &oldName, const std::string &newName)
|
||||
{
|
||||
return var.renameDocumentObject(oldName, newName);
|
||||
}
|
||||
|
||||
bool VariableExpression::validDocumentRename(const std::string &oldName, const std::string &newName)
|
||||
{
|
||||
return var.validDocumentRename(oldName, newName);
|
||||
}
|
||||
|
||||
bool VariableExpression::renameDocument(const std::string &oldName, const std::string &newName)
|
||||
{
|
||||
return var.renameDocument(oldName, newName);
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
virtual void visit(Expression * e) = 0;
|
||||
};
|
||||
|
||||
template<class P> class AppExport ExpressionModifier : public ExpressionVisitor {
|
||||
template<class P> class ExpressionModifier : public ExpressionVisitor {
|
||||
public:
|
||||
ExpressionModifier(P & _prop)
|
||||
: prop(_prop) { }
|
||||
|
@ -368,8 +368,12 @@ public:
|
|||
|
||||
void setPath(const ObjectIdentifier & path);
|
||||
|
||||
bool validDocumentObjectRename(const std::string & oldName, const std::string & newName);
|
||||
|
||||
bool renameDocumentObject(const std::string & oldName, const std::string & newName);
|
||||
|
||||
bool validDocumentRename(const std::string &oldName, const std::string &newName);
|
||||
|
||||
bool renameDocument(const std::string &oldName, const std::string &newName);
|
||||
|
||||
const App::Property *getProperty() const;
|
||||
|
|
128
src/App/ExpressionVisitors.h
Normal file
128
src/App/ExpressionVisitors.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2016 *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef RENAMEOBJECTIDENTIFIEREXPRESSIONVISITOR_H
|
||||
#define RENAMEOBJECTIDENTIFIEREXPRESSIONVISITOR_H
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
#include "Expression.h"
|
||||
|
||||
namespace App {
|
||||
|
||||
/**
|
||||
* @brief The RenameObjectIdentifierExpressionVisitor class is a functor used to visit each node of an expression, and
|
||||
* possibly rename VariableExpression nodes.
|
||||
*/
|
||||
|
||||
template<class P> class RenameObjectIdentifierExpressionVisitor : public ExpressionModifier<P> {
|
||||
public:
|
||||
RenameObjectIdentifierExpressionVisitor(P & _prop,
|
||||
const std::map<ObjectIdentifier, ObjectIdentifier> &_paths, const ObjectIdentifier & _owner)
|
||||
: ExpressionModifier<P>(_prop)
|
||||
, paths(_paths)
|
||||
, owner(_owner)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(Expression *node) {
|
||||
VariableExpression *expr = Base::freecad_dynamic_cast<VariableExpression>(node);
|
||||
|
||||
if (expr) {
|
||||
const App::ObjectIdentifier & oldPath = expr->getPath().canonicalPath();
|
||||
const std::map<ObjectIdentifier, ObjectIdentifier>::const_iterator it = paths.find(oldPath);
|
||||
|
||||
if (it != paths.end()) {
|
||||
ExpressionModifier<P>::setExpressionChanged();
|
||||
expr->setPath(it->second.relativeTo(owner));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const std::map<ObjectIdentifier, ObjectIdentifier> &paths; /**< Map with current and new object identifiers */
|
||||
const ObjectIdentifier owner; /**< Owner of expression */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The RelabelDocumentObjectExpressionVisitor class is a functor class used to rename variables in an expression.
|
||||
*/
|
||||
|
||||
template<class P> class RelabelDocumentObjectExpressionVisitor : public ExpressionModifier<P> {
|
||||
public:
|
||||
|
||||
RelabelDocumentObjectExpressionVisitor(P & _prop, const std::string & _oldName, const std::string & _newName)
|
||||
: ExpressionModifier<P>(_prop)
|
||||
, oldName(_oldName)
|
||||
, newName(_newName)
|
||||
{
|
||||
}
|
||||
|
||||
~RelabelDocumentObjectExpressionVisitor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Visit each node in the expression, and if it is a VariableExpression object, incoke renameDocumentObject in it.
|
||||
* @param node Node to visit
|
||||
*/
|
||||
|
||||
void visit(Expression * node) {
|
||||
VariableExpression *expr = Base::freecad_dynamic_cast<VariableExpression>(node);
|
||||
|
||||
if (expr && expr->validDocumentObjectRename(oldName, newName)) {
|
||||
ExpressionModifier<P>::setExpressionChanged();
|
||||
expr->renameDocumentObject(oldName, newName);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string oldName; /**< Document object name to replace */
|
||||
std::string newName; /**< New document object name */
|
||||
};
|
||||
|
||||
template<class P> class RelabelDocumentExpressionVisitor : public ExpressionModifier<P> {
|
||||
public:
|
||||
|
||||
RelabelDocumentExpressionVisitor(P & prop, const std::string & _oldName, const std::string & _newName)
|
||||
: ExpressionModifier<P>(prop)
|
||||
, oldName(_oldName)
|
||||
, newName(_newName)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(Expression * node) {
|
||||
VariableExpression *expr = Base::freecad_dynamic_cast<VariableExpression>(node);
|
||||
|
||||
if (expr && expr->validDocumentRename(oldName, newName)) {
|
||||
ExpressionModifier<P>::setExpressionChanged();
|
||||
expr->renameDocument(oldName, newName);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string oldName;
|
||||
std::string newName;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // RENAMEOBJECTIDENTIFIEREXPRESSIONVISITOR_H
|
|
@ -365,6 +365,29 @@ bool ObjectIdentifier::renameDocumentObject(const std::string &oldName, const st
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check whether a rename call with the same arguments would actually cause a rename.
|
||||
* @param oldName Name of current document object
|
||||
* @param newName New name of document object
|
||||
*/
|
||||
|
||||
bool ObjectIdentifier::validDocumentObjectRename(const std::string &oldName, const std::string &newName)
|
||||
{
|
||||
if (oldName == newName)
|
||||
return false;
|
||||
|
||||
if (documentObjectNameSet && documentObjectName == oldName)
|
||||
return true;
|
||||
else {
|
||||
ResolveResults result(*this);
|
||||
|
||||
if (result.propertyIndex == 1 && result.resolvedDocumentObjectName == oldName)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Modify object identifier given that the document \a oldName has changed name to \a newName.
|
||||
* @param oldName Name of current document
|
||||
|
@ -392,6 +415,29 @@ bool ObjectIdentifier::renameDocument(const std::string &oldName, const std::str
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether a rename call with the same arguments would actually cause a rename.
|
||||
* @param oldName Name of current document
|
||||
* @param newName New name of document
|
||||
*/
|
||||
|
||||
bool ObjectIdentifier::validDocumentRename(const std::string &oldName, const std::string &newName)
|
||||
{
|
||||
if (oldName == newName)
|
||||
return false;
|
||||
|
||||
if (documentNameSet && documentName == oldName)
|
||||
return true;
|
||||
else {
|
||||
ResolveResults result(*this);
|
||||
|
||||
if (result.resolvedDocumentName == oldName)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sub field part of a property as a string.
|
||||
* @return String representation of path.
|
||||
|
|
|
@ -190,8 +190,12 @@ public:
|
|||
|
||||
const String getDocumentObjectName() const;
|
||||
|
||||
bool validDocumentObjectRename(const std::string &oldName, const std::string &newName);
|
||||
|
||||
bool renameDocumentObject(const std::string & oldName, const std::string & newName);
|
||||
|
||||
bool validDocumentRename(const std::string &oldName, const std::string &newName);
|
||||
|
||||
bool renameDocument(const std::string &oldName, const std::string &newName);
|
||||
|
||||
App::Document *getDocument(String name = String()) const;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <Base/Writer.h>
|
||||
#include <Base/Reader.h>
|
||||
#include "Expression.h"
|
||||
#include "ExpressionVisitors.h"
|
||||
#include "PropertyExpressionEngine.h"
|
||||
#include "PropertyStandard.h"
|
||||
#include "PropertyUnits.h"
|
||||
|
@ -41,59 +42,6 @@ using namespace App;
|
|||
using namespace Base;
|
||||
using namespace boost;
|
||||
|
||||
typedef boost::function<void ()> aboutToSetValueFunc;
|
||||
typedef boost::function<void ()> hasSetValueFunc;
|
||||
|
||||
/**
|
||||
* @brief The RelabelDocumentObjectExpressionVisitor class is a functor class used to rename variables in an expression.
|
||||
*/
|
||||
|
||||
class RelabelDocumentObjectExpressionVisitor : public ExpressionVisitor {
|
||||
public:
|
||||
|
||||
RelabelDocumentObjectExpressionVisitor(aboutToSetValueFunc _aboutToSetValue, hasSetValueFunc _hasSetValue, const std::string & _oldName, const std::string & _newName)
|
||||
: aboutToSetValue(_aboutToSetValue)
|
||||
, hasSetValue(_hasSetValue)
|
||||
, oldName(_oldName)
|
||||
, newName(_newName)
|
||||
, changed(0)
|
||||
{
|
||||
}
|
||||
|
||||
~RelabelDocumentObjectExpressionVisitor() {
|
||||
if (changed > 0)
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Visit each node in the expression, and if it is a VariableExpression object, incoke renameDocumentObject in it.
|
||||
* @param node Node to visit
|
||||
*/
|
||||
|
||||
void visit(Expression * node) {
|
||||
VariableExpression *expr = freecad_dynamic_cast<VariableExpression>(node);
|
||||
|
||||
if (expr) {
|
||||
if (expr->renameDocumentObject(oldName, newName)) {
|
||||
if (!changed) {
|
||||
aboutToSetValue();
|
||||
++changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int getChanged() const { return changed; }
|
||||
|
||||
private:
|
||||
aboutToSetValueFunc aboutToSetValue;
|
||||
hasSetValueFunc hasSetValue;
|
||||
std::string oldName; /**< Document object name to replace */
|
||||
std::string newName; /**< New document object name */
|
||||
int changed;
|
||||
};
|
||||
|
||||
class ObjectDeletedExpressionVisitor : public ExpressionVisitor {
|
||||
public:
|
||||
|
||||
|
@ -329,9 +277,7 @@ void PropertyExpressionEngine::slotObjectRenamed(const DocumentObject &obj)
|
|||
if (!docObj || docObj->getNameInDocument() == 0)
|
||||
return;
|
||||
|
||||
RelabelDocumentObjectExpressionVisitor v(boost::bind( &PropertyExpressionEngine::aboutToSetValue, this),
|
||||
boost::bind( &PropertyExpressionEngine::hasSetValue, this),
|
||||
obj.getOldLabel(), obj.Label.getStrValue());
|
||||
RelabelDocumentObjectExpressionVisitor<PropertyExpressionEngine> v(*this, obj.getOldLabel(), obj.Label.getStrValue());
|
||||
|
||||
for (ExpressionMap::iterator it = expressions.begin(); it != expressions.end(); ++it) {
|
||||
int changed = v.getChanged();
|
||||
|
@ -773,42 +719,6 @@ void PropertyExpressionEngine::renameExpressions(const std::map<ObjectIdentifier
|
|||
hasSetValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The RenameObjectIdentifierExpressionVisitor class is a functor used to visit each node of an expression, and
|
||||
* possibly rename VariableExpression nodes.
|
||||
*/
|
||||
|
||||
class RenameObjectIdentifierExpressionVisitor : public ExpressionVisitor {
|
||||
public:
|
||||
|
||||
RenameObjectIdentifierExpressionVisitor(const std::map<ObjectIdentifier, ObjectIdentifier> &_paths, const ObjectIdentifier & _owner)
|
||||
: paths(_paths)
|
||||
, owner(_owner)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief If node is a VariableExpression object, look it up in the paths map, and possibly rename it.
|
||||
* @param node Node to visit.
|
||||
*/
|
||||
|
||||
void visit(Expression * node) {
|
||||
VariableExpression *expr = freecad_dynamic_cast<VariableExpression>(node);
|
||||
|
||||
if (expr) {
|
||||
const App::ObjectIdentifier & oldPath = expr->getPath().canonicalPath();
|
||||
const std::map<ObjectIdentifier, ObjectIdentifier>::const_iterator it = paths.find(oldPath);
|
||||
|
||||
if (it != paths.end())
|
||||
expr->setPath(it->second.relativeTo(owner));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const std::map<ObjectIdentifier, ObjectIdentifier> &paths; /**< Map with current and new object identifiers */
|
||||
const ObjectIdentifier & owner; /**< Owner og expression */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Rename object identifiers in the registered expressions.
|
||||
* @param paths Map with current and new object identifiers.
|
||||
|
@ -816,9 +726,8 @@ private:
|
|||
|
||||
void PropertyExpressionEngine::renameObjectIdentifiers(const std::map<ObjectIdentifier, ObjectIdentifier> &paths)
|
||||
{
|
||||
|
||||
for (ExpressionMap::iterator it = expressions.begin(); it != expressions.end(); ++it) {
|
||||
RenameObjectIdentifierExpressionVisitor v(paths, it->first);
|
||||
RenameObjectIdentifierExpressionVisitor<PropertyExpressionEngine> v(*this, paths, it->first);
|
||||
it->second.expression->visit(v);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user