Salome HOME
Implementation of checking the python dump functionality in any unit test (in the...
authormpv <mpv@opencascade.com>
Fri, 12 Aug 2016 14:57:57 +0000 (17:57 +0300)
committermpv <mpv@opencascade.com>
Fri, 12 Aug 2016 14:57:57 +0000 (17:57 +0300)
src/ConstructionPlugin/Test/TestPoint.py
src/GeomDataAPI/GeomDataAPI_Dir.h
src/Model/Model_SelectionNaming.cpp
src/ModelHighAPI/CMakeLists.txt
src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp [new file with mode: 0644]
src/ModelHighAPI/ModelHighAPI_FeatureStore.h [new file with mode: 0644]
src/ModelHighAPI/ModelHighAPI_Tools.cpp
src/ModelHighAPI/ModelHighAPI_Tools.h
src/PythonAPI/model/services/__init__.py

index 5ea7e780b5287d5c07b447730db0ecb09ce1bf7c..4afd7f2b9ef0595466ffdbbf911d8638b9498d63 100644 (file)
@@ -60,3 +60,5 @@ assert (len(aPoint.result()) > 0)
 # aPoint = model.addPoint(aDocument, aSketchLine1.result()[0], aPlane.result()[0])
 # aSession.finishOperation()
 # assert (len(aPoint.result()) > 0)
+
+assert(model.checkPythonDump())
\ No newline at end of file
index 4e61cd8f072ace18a6caa6561712e71bcf9f5339..bd91b7d423b521f79431519b0a47e97fd05180ac 100644 (file)
@@ -52,4 +52,7 @@ class GeomDataAPI_Dir : public ModelAPI_Attribute
   GEOMDATAAPI_EXPORT virtual ~GeomDataAPI_Dir();
 };
 
+//! Pointer on attribute object
+typedef std::shared_ptr<GeomDataAPI_Dir> AttributeDirPtr;
+
 #endif
index 7156e75ac20c9a8a6b86535927f9ab9a445708ee..a9275e4d118451f331512ffae1da63a26feaa6bd 100644 (file)
@@ -8,6 +8,10 @@
 #include "Model_Document.h"
 #include <ModelAPI_Feature.h>
 #include <Events_InfoMessage.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_CompositeFeature.h>
 
 #include <TopoDS_Iterator.hxx>
 #include <TopoDS.hxx>
@@ -26,8 +30,6 @@
 #include <TNaming_NamedShape.hxx>
 #include <TNaming_Localizer.hxx>
 #include <TDataStd_Name.hxx>
-#include <ModelAPI_ResultConstruction.h>
-#include <ModelAPI_CompositeFeature.h>
 #include <TColStd_MapOfTransient.hxx>
 #include <algorithm>
 
@@ -40,7 +42,6 @@ Model_SelectionNaming::Model_SelectionNaming(TDF_Label theSelectionLab)
   myLab = theSelectionLab;
 }
 
-
 std::string Model_SelectionNaming::getShapeName(
   std::shared_ptr<Model_Document> theDoc, const TopoDS_Shape& theShape)
 {
@@ -53,13 +54,6 @@ std::string Model_SelectionNaming::getShapeName(
       aName = TCollection_AsciiString(anAttr->Get()).ToCString();
       if(!aName.empty()) {         
         const TDF_Label& aLabel = theDoc->findNamingName(aName);
-        /* MPV: the same shape with the same name may be duplicated on different labels (selection of the same construction object)
-        if(!aLabel.IsEqual(aNS->Label())) {
-        //aName.erase(); //something is wrong, to be checked!!!
-        aName += "_SomethingWrong";
-        return aName;
-        }*/
-
         static const std::string aPostFix("_");
         TNaming_Iterator anItL(aNS);
         for(int i = 1; anItL.More(); anItL.Next(), i++) {
@@ -75,8 +69,6 @@ std::string Model_SelectionNaming::getShapeName(
   return aName;
 }
 
-
-
 bool isTrivial (const TopTools_ListOfShape& theAncestors, TopTools_IndexedMapOfShape& theSMap)
 {
   // a trivial case: F1 & F2,  aNumber = 1, i.e. intersection gives 1 edge.
@@ -599,9 +591,6 @@ std::string Model_SelectionNaming::shortName(
   return aName;
 }
 
-#include <ModelAPI_Session.h>
-#include <ModelAPI_ResultPart.h>
-
 // type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT
 bool Model_SelectionNaming::selectSubShape(const std::string& theType, 
   const std::string& theSubShapeName, std::shared_ptr<Model_Document> theDoc,
index 7b650a573cf8c4746ce19a15ece7a5d14e85b17a..a5280ec4ecc1879e47d7e02706c8fbd721845fbf 100644 (file)
@@ -14,6 +14,7 @@ SET(PROJECT_HEADERS
   ModelHighAPI_Selection.h
   ModelHighAPI_Services.h
   ModelHighAPI_Tools.h
+  ModelHighAPI_FeatureStore.h
 )
 
 SET(PROJECT_SOURCES
@@ -26,6 +27,7 @@ SET(PROJECT_SOURCES
   ModelHighAPI_Selection.cpp
   ModelHighAPI_Services.cpp
   ModelHighAPI_Tools.cpp
+  ModelHighAPI_FeatureStore.cpp
 )
 
 SET(PROJECT_LIBRARIES
@@ -33,6 +35,7 @@ SET(PROJECT_LIBRARIES
   Events
   GeomAPI
   GeomDataAPI
+  GeomAlgoAPI
   ModelAPI
 )
 
@@ -58,6 +61,7 @@ INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/Config
   ${PROJECT_SOURCE_DIR}/src/Events
   ${PROJECT_SOURCE_DIR}/src/GeomAPI
+  ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
   ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
   ${PROJECT_SOURCE_DIR}/src/ModelAPI
   ${PROJECT_SOURCE_DIR}/src/PartSetPlugin
diff --git a/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp b/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp
new file mode 100644 (file)
index 0000000..ed67336
--- /dev/null
@@ -0,0 +1,256 @@
+// Copyright (C) 2016-20xx CEA/DEN, EDF R&D -->
+
+// File:        ModelHighAPI_FeatureStore.cpp
+// Created:     12 August 2016
+// Author:      Mikhail PONIKAROV
+
+#include <ModelHighAPI_FeatureStore.h>
+
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeDocRef.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeIntArray.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefAttrList.h>
+#include <ModelAPI_AttributeReference.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeDoubleArray.h>
+
+#include <GeomDataAPI_Dir.h>
+#include <GeomDataAPI_Point.h>
+#include <GeomDataAPI_Point2D.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAPI_Pnt.h>
+
+#include <TopoDS_Shape.hxx>
+#include <TopExp_Explorer.hxx>
+
+ModelHighAPI_FeatureStore::ModelHighAPI_FeatureStore(FeaturePtr theFeature) {
+  storeData(theFeature->data(), myAttrs);
+  // iterate results to store
+  std::list<ResultPtr> allResults;
+  ModelAPI_Tools::allResults(theFeature, allResults);
+  std::list<ResultPtr>::iterator aRes = allResults.begin();
+  for(; aRes != allResults.end(); aRes++) {
+    std::map<std::string, std::string> aResDump;
+    storeData((*aRes)->data(), aResDump);
+    myRes.push_back(aResDump);
+  }
+}
+
+std::string ModelHighAPI_FeatureStore::compare(FeaturePtr theFeature) {
+  std::string anError = compareData(theFeature->data(), myAttrs);
+  if (!anError.empty()) {
+    return "Features '" + theFeature->name() + "' differ:" + anError;
+  }
+  std::list<ResultPtr> allResults;
+  ModelAPI_Tools::allResults(theFeature, allResults);
+  std::list<ResultPtr>::iterator aRes = allResults.begin();
+  std::list<std::map<std::string, std::string> >::iterator aResIter = myRes.begin();
+  for(; aRes != allResults.end() && aResIter != myRes.end(); aRes++, aResIter++) {
+    anError = compareData((*aRes)->data(), *aResIter);
+    if (!anError.empty())
+      return "Results of feature '" + theFeature->name() + "' '" + (*aRes)->data()->name() + 
+      "' differ:" + anError;
+  }
+  if (aRes != allResults.end()) {
+    return "Current model has more results '" + (*aRes)->data()->name() + "'";
+  }
+  if (aResIter != myRes.end()) {
+    return "Original model had more results '" + (*aResIter)["__name__"] + "'";
+  }
+  return ""; // ok
+}
+
+void ModelHighAPI_FeatureStore::storeData(std::shared_ptr<ModelAPI_Data> theData, 
+  std::map<std::string, std::string>& theAttrs)
+{
+  theAttrs["__name__"] = theData->name(); // store name to keep also this information and output if needed
+  std::list<std::shared_ptr<ModelAPI_Attribute> > allAttrs = theData->attributes("");
+  std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = allAttrs.begin();
+  for(; anAttr != allAttrs.end(); anAttr++) {
+    theAttrs[(*anAttr)->id()] = dumpAttr(*anAttr);
+  }
+  ResultPtr aShapeOwner = std::dynamic_pointer_cast<ModelAPI_Result>(theData->owner());
+  if (aShapeOwner.get() && aShapeOwner->shape().get()) {
+    theAttrs["__shape__"] = dumpShape(aShapeOwner->shape());
+  }
+}
+
+std::string ModelHighAPI_FeatureStore::compareData(std::shared_ptr<ModelAPI_Data> theData, 
+  std::map<std::string, std::string>& theAttrs)
+{
+  std::map<std::string, std::string> aThis;
+  storeData(theData, aThis);
+  std::map<std::string, std::string>::iterator aThisIter = aThis.begin();
+  for(; aThisIter != aThis.end(); aThisIter++) {
+    if (theAttrs.find(aThisIter->first) == theAttrs.end()) {
+      return "original model had no attribute '" + aThisIter->first + "'";
+    }
+    if (theAttrs[aThisIter->first] != aThisIter->second) {
+      return "attribute '" + aThisIter->first + "' is different '" + 
+        theAttrs[aThisIter->first] + "' != '" + aThisIter->second;
+    }
+  }
+  // iterate back to find lack attribute in the current model
+  std::map<std::string, std::string>::iterator anOrigIter = theAttrs.begin();
+  for(; anOrigIter != theAttrs.end(); anOrigIter++) {
+    if (aThis.find(anOrigIter->first) == aThis.end()) {
+      return "current model had no attribute '" + anOrigIter->first + "'";
+    }
+  }
+  return "";
+}
+
+std::string ModelHighAPI_FeatureStore::dumpAttr(const AttributePtr& theAttr) {
+  if (!theAttr->isInitialized()) {
+    return "__notinitialized__";
+  }
+  std::string aType = theAttr->attributeType();
+  std::ostringstream aResult;
+  if (aType == ModelAPI_AttributeDocRef::typeId()) {
+    AttributeDocRefPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDocRef>(theAttr);
+    DocumentPtr aDoc = ModelAPI_Session::get()->moduleDocument();
+    if (anAttr->value() != aDoc) {
+      ResultPtr aRes = ModelAPI_Tools::findPartResult(aDoc, anAttr->value());
+      if (aRes.get()) {
+        aResult<<aRes->data()->name(); // Part result name (the same as saved file name)
+      }
+    } else {
+      aResult<<aDoc->kind(); // PartSet
+    }
+  } else if (aType == ModelAPI_AttributeInteger::typeId()) {
+    AttributeIntegerPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theAttr);
+    if (anAttr->text().empty())
+      aResult<<anAttr->value();
+    else
+      aResult<<anAttr->text();
+  } else if (aType == ModelAPI_AttributeDouble::typeId()) {
+    AttributeDoublePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttr);
+    if (anAttr->text().empty())
+      aResult<<anAttr->value();
+    else
+      aResult<<anAttr->text();
+  } else if (aType == ModelAPI_AttributeBoolean::typeId()) {
+    AttributeBooleanPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theAttr);
+    aResult<<anAttr->value();
+  } else if (aType == ModelAPI_AttributeString::typeId()) {
+    AttributeStringPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeString>(theAttr);
+    aResult<<anAttr->value();
+  } else if (aType == ModelAPI_AttributeReference::typeId()) {
+    AttributeReferencePtr anAttr =
+      std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttr);
+    if (anAttr->value().get()) {
+      aResult<<anAttr->value()->data()->name();
+    } else {
+      aResult<<"__empty__";
+    }
+  } else if (aType == ModelAPI_AttributeSelection::typeId()) {
+    AttributeSelectionPtr anAttr = 
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttr);
+    aResult<<anAttr->namingName();
+  } else if (aType == ModelAPI_AttributeSelectionList::typeId()) {
+    AttributeSelectionListPtr anAttr = 
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttr);
+    for(int a = 0; a < anAttr->size(); a++) {
+      if (a != 0)
+        aResult<<" ";
+      aResult<<anAttr->value(a)->namingName();
+    }
+  } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
+    AttributeRefAttrPtr anAttr = 
+      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttr);
+    ObjectPtr anObj = anAttr->isObject() ? anAttr->object() : anAttr->attr()->owner();
+    if (anObj.get()) {
+      aResult<<anObj->data()->name();
+      if (!anAttr->isObject()) {
+        aResult<<" "<<anAttr->attr()->id();
+      }
+    } else {
+      aResult<<"__empty__";
+    }
+  } else if (aType == ModelAPI_AttributeRefList::typeId()) {
+    AttributeRefListPtr anAttr = 
+      std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttr);
+    std::list<ObjectPtr> aList = anAttr->list();
+    for(std::list<ObjectPtr>::iterator aL = aList.begin(); aL != aList.end(); aL++) {
+      if (aL != aList.begin())
+        aResult<<" ";
+      if (aL->get()) {
+        aResult<<(*aL)->data()->name();
+      } else {
+        aResult<<"__empty__";
+      }
+    }
+  } else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
+    AttributeRefAttrListPtr anAttr = 
+      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttr);
+    std::list<std::pair<ObjectPtr, AttributePtr> > aList = anAttr->list();
+    std::list<std::pair<ObjectPtr, AttributePtr> >::iterator aL = aList.begin();
+    for(; aL != aList.end(); aL++) {
+      if (aL != aList.begin())
+        aResult<<" ";
+      ObjectPtr anObj = aL->second.get() ? aL->second->owner() : aL->first;
+      if (anObj.get()) {
+        aResult<<anObj->data()->name();
+        if (aL->second.get()) {
+          aResult<<" "<<aL->second->id();
+        }
+      } else {
+        aResult<<"__empty__";
+      }
+    }
+  } else if (aType == ModelAPI_AttributeIntArray::typeId()) {
+    AttributeIntArrayPtr anAttr = 
+      std::dynamic_pointer_cast<ModelAPI_AttributeIntArray>(theAttr);
+    for(int a = 0; a < anAttr->size(); a++)
+      aResult<<anAttr->value(a)<<" ";
+  } else if (aType == ModelAPI_AttributeDoubleArray::typeId()) {
+    AttributeDoubleArrayPtr anAttr = 
+      std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(theAttr);
+    for(int a = 0; a < anAttr->size(); a++)
+      aResult<<anAttr->value(a)<<" ";
+  } else if (aType == GeomDataAPI_Point::typeId()) {
+    AttributePointPtr anAttr = std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttr);
+    aResult<<anAttr->x()<<" "<<anAttr->y()<<" "<<anAttr->z();
+  } else if (aType == GeomDataAPI_Dir::typeId()) {
+    AttributeDirPtr anAttr = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theAttr);
+    aResult<<anAttr->x()<<" "<<anAttr->y()<<" "<<anAttr->z();
+  } else if (aType == GeomDataAPI_Point2D::typeId()) {
+    AttributePoint2DPtr anAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttr);
+    aResult<<anAttr->x()<<" "<<anAttr->y()<<" ";
+  } else {
+    aResult<<"__unknownattribute__";
+  }
+  return aResult.str();
+}
+
+std::string ModelHighAPI_FeatureStore::dumpShape(std::shared_ptr<GeomAPI_Shape>& theShape) {
+  TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
+  if (aShape.IsNull()) {
+    return "null";
+  }
+  std::ostringstream aResult;
+  // output the number of shapes of different types
+  TopAbs_ShapeEnum aType = TopAbs_COMPOUND;
+  for(; aType <= TopAbs_VERTEX; aType = TopAbs_ShapeEnum((int)aType + 1)) {
+    TopExp_Explorer anExp(aShape, aType);
+    int aCount = 0;
+    for(; anExp.More(); anExp.Next()) aCount++;
+    TopAbs::Print(aType, aResult);
+    aResult<<": "<<aCount<<std::endl;
+  }
+  // output the main characteristics
+  aResult<<"Volume: "<<setprecision(2)<<GeomAlgoAPI_ShapeTools::volume(theShape)<<std::endl;
+  std::shared_ptr<GeomAPI_Pnt> aCenter = GeomAlgoAPI_ShapeTools::centreOfMass(theShape);
+  aResult<<"Center of mass: "
+    <<aCenter->x()<<" "<<aCenter->y()<<" "<<aCenter->z()<<std::endl;
+  return aResult.str();
+}
diff --git a/src/ModelHighAPI/ModelHighAPI_FeatureStore.h b/src/ModelHighAPI/ModelHighAPI_FeatureStore.h
new file mode 100644 (file)
index 0000000..d6d92d9
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright (C) 2016-20xx CEA/DEN, EDF R&D -->
+
+// File:        ModelHighAPI_FeatureStore.h
+// Created:     12 August 2016
+// Author:      Mikhail PONIKAROV
+
+#ifndef ModelHighAPI_FeatureStore_H_
+#define ModelHighAPI_FeatureStore_H_
+
+#include "ModelHighAPI.h"
+
+#include <map>
+#include <list>
+#include <string>
+
+class ModelAPI_Feature;
+class ModelAPI_Data;
+class GeomAPI_Shape;
+class ModelAPI_Attribute;
+
+typedef std::shared_ptr<ModelAPI_Feature>  FeaturePtr;
+typedef std::shared_ptr<ModelAPI_Attribute>  AttributePtr;
+
+/**\class ModelHighAPI_FeatureStore
+ * \ingroup CPPHighAPI
+ * \brief Allows to compare the original and the dumped/executed feature
+ */
+class ModelHighAPI_FeatureStore {
+  /// dumps of attributes of the stored feature (id -> dump)
+  std::map<std::string, std::string> myAttrs;
+   /// dumps of attributes of results (list of results id -> dumps)
+  std::list<std::map<std::string, std::string> > myRes;
+public:
+  // unused constructor for the map container needs
+  ModelHighAPI_FeatureStore() {}
+  // constructor that initializes this object by feature to store
+  ModelHighAPI_FeatureStore(FeaturePtr theFeature);
+  // compares the stored feature information with the given feature
+  std::string compare(FeaturePtr theFeature);
+
+private:
+  /// stores the information about all attributes of data in map
+  void storeData(std::shared_ptr<ModelAPI_Data> theData, 
+                 std::map<std::string, std::string>& theAttrs);
+  /// compares the information about all attributes of data with map
+  /// returns not empty string with error if something is different
+  std::string compareData(std::shared_ptr<ModelAPI_Data> theData, 
+                 std::map<std::string, std::string>& theAttrs);
+  /// dumps the attribute content to the string
+  std::string dumpAttr(const AttributePtr& theAttr);
+  /// dumps the shape main charatceristics to string
+  std::string dumpShape(std::shared_ptr<GeomAPI_Shape>& theShape);
+};
+
+#endif
\ No newline at end of file
index f61e4169d3dfd4303919b76df26ae312759c4c41..c19f474096e4178bc5be903561c2523a8f951a07 100644 (file)
@@ -6,6 +6,7 @@
 
 //--------------------------------------------------------------------------------------
 #include "ModelHighAPI_Tools.h"
+#include <ModelHighAPI_FeatureStore.h>
 //--------------------------------------------------------------------------------------
 #include <GeomAPI_Dir.h>
 #include <GeomAPI_Pnt.h>
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_ResultPart.h>
+//--------------------------------------------------------------------------------------
+#include <Config_ModuleReader.h>
 //--------------------------------------------------------------------------------------
 #include "ModelHighAPI_Double.h"
 #include "ModelHighAPI_Integer.h"
 #include "ModelHighAPI_Reference.h"
 #include "ModelHighAPI_Selection.h"
 
+#include <Events_InfoMessage.h>
+
 #include <algorithm>
+#include <iostream>
 
 //--------------------------------------------------------------------------------------
 void fillAttribute(const std::shared_ptr<GeomAPI_Pnt2d> & theValue,
@@ -238,4 +248,115 @@ GeomAPI_Shape::ShapeType getShapeType(const ModelHighAPI_Selection& theSelection
   return aShapeType;
 }
 
+/// stores the features information, recoursively stores sub-documetns features
+std::string storeFeatures(const std::string& theDocName, DocumentPtr theDoc,
+  std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> >& theStore,
+  const bool theCompare) // if false => store
+{
+  std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> >::iterator aDocFind;
+  if (theCompare) {
+     aDocFind = theStore.find(theDocName);
+     if (aDocFind == theStore.end()) {
+       return "Document '" + theDocName + "' not found";
+     }
+  }
+  // store the model features information: iterate all features
+  int aFeaturesCount = 0; // stores the number of compared features for this document to compate
+  std::set<std::string> aProcessed; // processed features names (that are in the current document)
+  std::list<FeaturePtr> allFeatures = theDoc->allFeatures();
+  std::list<FeaturePtr>::iterator allIter = allFeatures.begin();
+  for(; allIter != allFeatures.end(); allIter++) {
+    FeaturePtr aFeat = *allIter;
+    if (theCompare) {
+      std::map<std::string, ModelHighAPI_FeatureStore>::iterator 
+        aFeatFind = aDocFind->second.find(aFeat->name());
+      if (aFeatFind == aDocFind->second.end()) {
+        return "Document '" + theDocName + "' feature '" + aFeat->name() + "' not found";
+      }
+      std::string anError = aFeatFind->second.compare(aFeat);
+      if (!anError.empty()) {
+        return anError;
+      }
+      aFeaturesCount++;
+      aProcessed.insert(aFeat->name());
+    } else {
+      theStore[theDocName][aFeat->name()] = ModelHighAPI_FeatureStore(aFeat);
+    }
+    // iterate all results of this feature
+    std::list<ResultPtr> allResults;
+    ModelAPI_Tools::allResults(aFeat, allResults);
+    std::list<ResultPtr>::iterator aRes = allResults.begin();
+    for(; aRes != allResults.end(); aRes++) {
+      if ((*aRes)->groupName() == ModelAPI_ResultPart::group()) { // recoursively store features of sub-documents
+        DocumentPtr aDoc = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRes)->partDoc();
+        if (aDoc.get()) {
+          std::string anError = storeFeatures((*aRes)->data()->name(), aDoc, theStore, theCompare);
+          if (!anError.empty())
+            return anError;
+        }
+      }
+    }
+  }
+  // checks the number of compared features
+  if (theCompare) {
+    if (aDocFind->second.size() != aFeaturesCount) {
+      // search for disappeared feature
+      std::string aLostName;
+      std::map<std::string, ModelHighAPI_FeatureStore>::iterator aLostIter;
+      for(aLostIter = aDocFind->second.begin(); aLostIter != aDocFind->second.end(); aLostIter++) {
+        if (aProcessed.find(aLostIter->first) == aProcessed.end()) {
+          aLostName = aLostIter->first;
+        }
+      }
+      return "For document '" + theDocName + 
+        "' the number of features becomes smaller, there is no feature '" + aLostName + "'";
+    }
+  }
+  return ""; // ok
+}
+
+//==================================================================================================
+bool checkPythonDump()
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+  // dump all to the python file
+  aSession->startOperation("Check python dump");
+  FeaturePtr aDump = aSession->moduleDocument()->addFeature("Dump");
+  if (aDump.get()) {
+    aDump->string("file_path")->setValue("check_dump.py"); // to the current folder
+    aDump->string("file_format")->setValue("py"); // to the current folder
+    aDump->execute();
+  }
+  bool isProblem = !aDump.get() || !aDump->error().empty(); // after "finish" dump will be removed
+  aSession->finishOperation();
+  if (isProblem)
+    return false; // something is wrong during dump
+
+   // map from document name to feature name to feature data
+  std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> > aStore;
+  std::string anError = storeFeatures(
+    aSession->moduleDocument()->kind(), aSession->moduleDocument(), aStore, false);
+  if (!anError.empty()) {
+    Events_InfoMessage anError("checkPythonDump", anError);
+    anError.send();
+    return false;
+  }
+  // close all before importation of the script
+  aSession->closeAll();
+  // execute the dumped
+  Config_ModuleReader::loadScript("check_dump");
+
+  // compare with the stored data
+  anError = storeFeatures(
+    aSession->moduleDocument()->kind(), aSession->moduleDocument(), aStore, true);
+  if (!anError.empty()) {
+    std::cout<<anError<<std::endl;
+    Events_InfoMessage anError("checkPythonDump", anError);
+    anError.send();
+    return false;
+  }
+
+  return true;
+}
+
 //--------------------------------------------------------------------------------------
index 789d43a0c2fc34e13fd655fd9884db73bf0f0836..5db774d70d2bbe974d5003172a9ec49fce21b5c1 100644 (file)
@@ -25,7 +25,6 @@ class GeomDataAPI_Point;
 class GeomDataAPI_Point2D;
 //--------------------------------------------------------------------------------------
 class ModelAPI_AttributeBoolean;
-class ModelAPI_AttributeDocRef;
 class ModelAPI_AttributeDouble;
 class ModelAPI_AttributeIntArray;
 class ModelAPI_AttributeInteger;
@@ -130,6 +129,12 @@ GeomAPI_Shape::ShapeType shapeTypeByStr(std::string theShapeTypeStr);
 MODELHIGHAPI_EXPORT
 GeomAPI_Shape::ShapeType getShapeType(const ModelHighAPI_Selection& theSelection);
 
+/// Performs the high level API dump, then closes all and executes the script:
+/// model must be recreated fully, with all attributes
+/// \returns true if check is well done
+MODELHIGHAPI_EXPORT
+bool checkPythonDump();
+
 //--------------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------------
 #endif /* SRC_MODELHIGHAPI_MODELHIGHAPI_TOOLS_H_ */ 
index 1fe15791f9ab9e0eac1ff8f971f4c52194c36987..480f8e7e59ae6d86f337d8ae2fc366d5e7da707f 100644 (file)
@@ -8,3 +8,4 @@ from ModelHighAPI import apply as do
 from ModelHighAPI import undo, redo
 from ModelHighAPI import reset
 from ModelHighAPI import ModelHighAPI_Selection as selection
+from ModelHighAPI import checkPythonDump as checkPythonDump