Salome HOME
Roll back the modification, not yet approved
[modules/shaper.git] / src / ParametersPlugin / ParametersPlugin_EvalListener.cpp
index 8413223988f1287357fef28536b88717673ad3b5..029800afa4e2dcf7315b865d1cf863d20045f0b2 100644 (file)
 
 #include <Events_Error.h>
 
+#include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeValidator.h>
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Tools.h>
-#include <ModelAPI_AttributeValidator.h>
 
 #include <ModelAPI_AttributeDouble.h>
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
 
 #include <string>
+#include <set>
 #include <sstream>
 
 ParametersPlugin_EvalListener::ParametersPlugin_EvalListener()
@@ -61,8 +63,8 @@ void ParametersPlugin_EvalListener::processEvent(
   }
 }
 
-double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression,
-                                               std::string& theError)
+double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression, std::string& theError, 
+                                               const std::shared_ptr<ModelAPI_Document>& theDocument)
 {
   std::list<std::string> anExprParams = myInterp->compile(theExpression);
   // find expression's params in the model
@@ -71,7 +73,8 @@ double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression,
   for ( ; it != anExprParams.end(); it++) {
     double aValue;
     ResultParameterPtr aParamRes;
-    if (!ModelAPI_Tools::findVariable(*it, aValue, aParamRes)) continue;
+    // If variable does not exist python interpreter will generate an error. It is OK.
+    if (!ModelAPI_Tools::findVariable(*it, aValue, aParamRes, theDocument)) continue;
 
     std::ostringstream sstream;
     sstream << aValue;
@@ -84,72 +87,77 @@ double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression,
   return result;
 }
 
+std::set<std::string> toSet(const std::list<std::string>& theContainer)
+{
+  return std::set<std::string>(theContainer.begin(), theContainer.end());
+}
+
 void ParametersPlugin_EvalListener::processEvaluationEvent(
     const std::shared_ptr<Events_Message>& theMessage)
 {
   std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
       std::dynamic_pointer_cast<ModelAPI_AttributeEvalMessage>(theMessage);
 
-  // Double
-  AttributeDoublePtr aDoubleAttribute =
-      std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aMessage->attribute());
-  if (aDoubleAttribute.get()) {
+  if (aMessage->attribute()->attributeType() == ModelAPI_AttributeDouble::typeId()) {
+    AttributeDoublePtr anAttribute =
+        std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aMessage->attribute());
     std::string anError;
-    double aValue = evaluate(aDoubleAttribute->text(), anError);
-    if (anError.empty()) {
-      aDoubleAttribute->setCalculatedValue(aValue);
-      aDoubleAttribute->setExpressionInvalid(false);
-    } else { // set feature as invalid-parameter arguments
-      aDoubleAttribute->setExpressionInvalid(true);
-    }
-  }
-
-  // Point
-  AttributePointPtr aPointAttribute =
-      std::dynamic_pointer_cast<GeomDataAPI_Point>(aMessage->attribute());
-  if (aPointAttribute.get()) {
-    std::string anError[3];
-    double aValue[3] = {
-        evaluate(aPointAttribute->textX(), anError[0]),
-        evaluate(aPointAttribute->textY(), anError[1]),
-        evaluate(aPointAttribute->textZ(), anError[2])
+    double aValue = evaluate(anAttribute->text(), anError, anAttribute->owner()->document());
+    bool isValid = anError.empty();
+    if (isValid)
+      anAttribute->setCalculatedValue(aValue);
+    anAttribute->setUsedParameters(isValid ? toSet(myInterp->compile(anAttribute->text())) : std::set<std::string>());
+    anAttribute->setExpressionInvalid(!isValid);
+    anAttribute->setExpressionError(anAttribute->text().empty() ? "" : anError);
+  } else
+  if (aMessage->attribute()->attributeType() == GeomDataAPI_Point::typeId()) {
+    AttributePointPtr anAttribute =
+        std::dynamic_pointer_cast<GeomDataAPI_Point>(aMessage->attribute());
+    std::string aText[] = {
+      anAttribute->textX(),
+      anAttribute->textY(),
+      anAttribute->textZ()
     };
-    bool isValid[3] = {
-        anError[0].empty(),
-        anError[1].empty(),
-        anError[2].empty()
+    double aCalculatedValue[] = {
+      anAttribute->x(),
+      anAttribute->y(),
+      anAttribute->z()
     };
-    aPointAttribute->setExpressionInvalid(0, !isValid[0]);
-    aPointAttribute->setExpressionInvalid(1, !isValid[1]);
-    aPointAttribute->setExpressionInvalid(2, !isValid[2]);
-
-    aPointAttribute->setCalculatedValue(
-        isValid[0] ? aValue[0] : aPointAttribute->x(),
-        isValid[1] ? aValue[1] : aPointAttribute->y(),
-        isValid[2] ? aValue[2] : aPointAttribute->z()
-    );
-  }
-
-  // Point2D
-  AttributePoint2DPtr aPoint2DAttribute =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aMessage->attribute());
-  if (aPoint2DAttribute.get()) {
-    std::string anError[2];
-    double aValue[2] = {
-        evaluate(aPoint2DAttribute->textX(), anError[0]),
-        evaluate(aPoint2DAttribute->textY(), anError[1])
+    for (int i = 0; i < 3; ++i) {
+      std::string anError;
+      double aValue = evaluate(aText[i], anError, anAttribute->owner()->document());
+      bool isValid = anError.empty();
+      if (isValid) aCalculatedValue[i] = aValue;
+      anAttribute->setUsedParameters(i, isValid ? toSet(myInterp->compile(aText[i])) : std::set<std::string>());
+      anAttribute->setExpressionInvalid(i, !isValid);
+      anAttribute->setExpressionError(i, aText[i].empty() ? "" : anError);
+    }
+    anAttribute->setCalculatedValue(aCalculatedValue[0],
+                                    aCalculatedValue[1],
+                                    aCalculatedValue[2]);
+  } else
+  if (aMessage->attribute()->attributeType() == GeomDataAPI_Point2D::typeId()) {
+    AttributePoint2DPtr anAttribute =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aMessage->attribute());
+    std::string aText[] = {
+      anAttribute->textX(),
+      anAttribute->textY()
     };
-    bool isValid[2] = {
-        anError[0].empty(),
-        anError[1].empty()
+    double aCalculatedValue[] = {
+      anAttribute->x(),
+      anAttribute->y()
     };
-    aPoint2DAttribute->setExpressionInvalid(0, !isValid[0]);
-    aPoint2DAttribute->setExpressionInvalid(1, !isValid[1]);
-
-    aPoint2DAttribute->setCalculatedValue(
-        isValid[0] ? aValue[0] : aPoint2DAttribute->x(),
-        isValid[1] ? aValue[1] : aPoint2DAttribute->y()
-    );
+    for (int i = 0; i < 2; ++i) {
+      std::string anError;
+      double aValue = evaluate(aText[i], anError, anAttribute->owner()->document());
+      bool isValid = anError.empty();
+      if (isValid) aCalculatedValue[i] = aValue;
+      anAttribute->setUsedParameters(i, isValid ? toSet(myInterp->compile(aText[i])) : std::set<std::string>());
+      anAttribute->setExpressionInvalid(i, !isValid);
+      anAttribute->setExpressionError(i, aText[i].empty() ? "" : anError);
+    }
+    anAttribute->setCalculatedValue(aCalculatedValue[0],
+                                    aCalculatedValue[1]);
   }
 }
 
@@ -215,83 +223,64 @@ void ParametersPlugin_EvalListener::renameInAttribute(
     const std::string& theOldName,
     const std::string& theNewName)
 {
-  // Double
-  AttributeDoublePtr aDoubleAttribute =
-      std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
-  if (aDoubleAttribute.get()) {
-    std::string anExpressionString = aDoubleAttribute->text();
+  if (theAttribute->attributeType() == ModelAPI_AttributeDouble::typeId()) {
+    AttributeDoublePtr anAttribute =
+        std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
+    std::string anExpressionString = anAttribute->text();
     anExpressionString = renameInPythonExpression(anExpressionString,
-                                                  theOldName,
-                                                  theNewName);
-    aDoubleAttribute->setText(anExpressionString);
-  }
-
-  // Point
-  AttributePointPtr aPointAttribute =
-      std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
-  if (aPointAttribute.get()) {
+                                                  theOldName, theNewName);
+    anAttribute->setText(anExpressionString);
+  } else
+  if (theAttribute->attributeType() == GeomDataAPI_Point::typeId()) {
+    AttributePointPtr anAttribute =
+        std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
     std::string anExpressionString[3] = {
-      aPointAttribute->textX(),
-      aPointAttribute->textY(),
-      aPointAttribute->textZ()
+      anAttribute->textX(),
+      anAttribute->textY(),
+      anAttribute->textZ()
     };
     for (int i = 0; i < 3; ++i)
       anExpressionString[i] = renameInPythonExpression(anExpressionString[i],
-                                                       theOldName,
-                                                       theNewName);
-    aPointAttribute->setText(anExpressionString[0],
-                             anExpressionString[1],
-                             anExpressionString[2]);
-  }
-
-  // Point2D
-  AttributePoint2DPtr aPoint2DAttribute =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
-  if (aPoint2DAttribute.get()) {
+                                                       theOldName, theNewName);
+    anAttribute->setText(anExpressionString[0],
+                         anExpressionString[1],
+                         anExpressionString[2]);
+  } else
+  if (theAttribute->attributeType() == GeomDataAPI_Point2D::typeId()) {
+    AttributePoint2DPtr anAttribute =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
     std::string anExpressionString[2] = {
-      aPoint2DAttribute->textX(),
-      aPoint2DAttribute->textY()
+      anAttribute->textX(),
+      anAttribute->textY()
     };
     for (int i = 0; i < 2; ++i)
       anExpressionString[i] = renameInPythonExpression(anExpressionString[i],
-                                                       theOldName,
-                                                       theNewName);
-    aPoint2DAttribute->setText(anExpressionString[0],
-                               anExpressionString[1]);
+                                                       theOldName, theNewName);
+    anAttribute->setText(anExpressionString[0],
+                         anExpressionString[1]);
   }
 }
 
 bool isValidAttribute(const AttributePtr& theAttribute)
 {
-  std::list<ModelAPI_Validator*> aValidators;
-  std::list<std::list<std::string> > anArguments;
-
-  FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
-  if (!aFeature.get())
-    return false;
-
-  ModelAPI_Session::get()->validators()->validators(aFeature->getKind(), 
-                                                    theAttribute->id(), 
-                                                    aValidators, anArguments);
-  std::list<ModelAPI_Validator*>::const_iterator aValidatorIt = aValidators.begin();
-  std::list<std::list<std::string> >::const_iterator anArgumentIt = anArguments.begin();
-  for (; aValidatorIt != aValidators.end() || anArgumentIt != anArguments.end(); ++aValidatorIt, ++anArgumentIt) {
-    const ModelAPI_AttributeValidator * anAttributeValidator =
-        dynamic_cast<const ModelAPI_AttributeValidator *>(*aValidatorIt);
-    if (!anAttributeValidator)
-      continue;
-    if (!anAttributeValidator->isValid(theAttribute, *anArgumentIt))
-      return false;
-  }
-  return true;
+  std::string aValidator, anError;
+  return ModelAPI_Session::get()->validators()->validate(theAttribute, aValidator, anError);
 }
 
-void setParameterName(std::shared_ptr<ParametersPlugin_Parameter> theParameter, const std::string& theName)
+void setParameterName(ResultParameterPtr theResultParameter, const std::string& theName)
 {
-  theParameter->data()->blockSendAttributeUpdated(true);
-  theParameter->data()->setName(theName);
-  theParameter->string(ParametersPlugin_Parameter::VARIABLE_ID())->setValue(theName);
-  theParameter->data()->blockSendAttributeUpdated(false);
+  theResultParameter->data()->blockSendAttributeUpdated(true);
+  theResultParameter->data()->setName(theName);
+  theResultParameter->data()->blockSendAttributeUpdated(false);
+
+  std::shared_ptr<ParametersPlugin_Parameter> aParameter = 
+      std::dynamic_pointer_cast<ParametersPlugin_Parameter>(
+          ModelAPI_Feature::feature(theResultParameter));
+
+  aParameter->data()->blockSendAttributeUpdated(true);
+  aParameter->data()->setName(theName);
+  aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID())->setValue(theName);
+  aParameter->data()->blockSendAttributeUpdated(false);
 }
 
 void ParametersPlugin_EvalListener::processObjectRenamedEvent(
@@ -300,75 +289,52 @@ void ParametersPlugin_EvalListener::processObjectRenamedEvent(
   std::shared_ptr<ModelAPI_ObjectRenamedMessage> aMessage =
       std::dynamic_pointer_cast<ModelAPI_ObjectRenamedMessage>(theMessage);
 
-  if (!aMessage.get() || aMessage->oldName().empty() || aMessage->newName().empty())
+  // Empty new name is not available too but it will be rejected by
+  // name validator in isValidAttribute.
+  if (!aMessage.get() || aMessage->oldName().empty())
     return;
 
-  // check that the renamed object is a result 
+  // check if the renamed object is a result parameter
   ResultParameterPtr aResultParameter =
       std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aMessage->object());
   if (!aResultParameter.get()) 
     return;
 
   // get parameter feature for the result
-  FeaturePtr aFeature = aResultParameter->document()->feature(aResultParameter);
   std::shared_ptr<ParametersPlugin_Parameter> aParameter =
-      std::dynamic_pointer_cast<ParametersPlugin_Parameter>(aFeature);
+      std::dynamic_pointer_cast<ParametersPlugin_Parameter>(
+          ModelAPI_Feature::feature(aResultParameter));
   if (!aParameter.get())
     return;
 
-  // rename a parameter attributes
-  // short way:
-  //aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID())->setValue(aMessage->newName());
-  //aParameter->execute();
-  // manual way:
-  setParameterName(aParameter, aMessage->newName());
-
+  // try to update the parameter feature according the new name
+  setParameterName(aResultParameter, aMessage->newName());
   // TODO(spo): replace with ModelAPI_Session::get()->validators()->validate(aParameter, ParametersPlugin_Parameter::VARIABLE_ID())
   // when ModelAPI_ValidatorsFactory::validate(const std::shared_ptr<ModelAPI_Feature>& theFeature, const std::string& theAttribute) const
   // is ready
   if (!isValidAttribute(aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID()))) {
-    setParameterName(aParameter, aMessage->oldName());
+    setParameterName(aResultParameter, aMessage->oldName());
     return;
   }
 
-  // List of documents to process
-  std::list<DocumentPtr> aDocList;
-  SessionPtr aSession = ModelAPI_Session::get();
-  DocumentPtr aDocument = aSession->activeDocument();
-  DocumentPtr aRootDocument = aSession->moduleDocument();
-  aDocList.push_back(aDocument);
-  if (aDocument != aRootDocument) {
-    aDocList.push_back(aRootDocument);
-  }
-
-  // Find all features
-  for (std::list<DocumentPtr>::const_iterator aDicumentIt = aDocList.begin(); 
-       aDicumentIt != aDocList.end(); ++aDicumentIt) {
-    const DocumentPtr& aDocument = *aDicumentIt;
-    std::list<FeaturePtr> aFeatures = aDocument->allFeatures();
-    std::list<FeaturePtr>::iterator aFeatureIt = aFeatures.begin();
-    for (; aFeatureIt != aFeatures.end(); ++aFeatureIt) {
-      const FeaturePtr& aFeature = *aFeatureIt;
-      
-      // If Parameter feature then rename its expression
+  std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes = 
+      aResultParameter->data()->refsToMe();
+  std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator anAttributeIt =
+      anAttributes.cbegin();
+  for (; anAttributeIt != anAttributes.cend(); ++anAttributeIt) {
+    const AttributePtr& anAttribute = *anAttributeIt;
+    AttributeRefListPtr anAttributeRefList =
+        std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(anAttribute);
+    if (anAttributeRefList.get()) {
       std::shared_ptr<ParametersPlugin_Parameter> aParameter =
-          std::dynamic_pointer_cast<ParametersPlugin_Parameter>(aFeature);
-      if (aParameter.get()) {
+          std::dynamic_pointer_cast<ParametersPlugin_Parameter>(
+              anAttributeRefList->owner());
+      if (aParameter.get())
         // Rename
         renameInParameter(aParameter, aMessage->oldName(), aMessage->newName());
-        continue;
-      }      
-
-      // Find all attributes
-      std::list<AttributePtr> anAttributes = aFeature->data()->attributes(std::string());
-      std::list<AttributePtr>::const_iterator anAttributeIt = anAttributes.begin();
-      for (; anAttributeIt != anAttributes.end(); ++anAttributeIt) {
-        const AttributePtr& anAttribute = *anAttributeIt;
-
+    } else
         // Rename
         renameInAttribute(anAttribute, aMessage->oldName(), aMessage->newName());
-      }
-    }
   }
 }