]> SALOME platform Git repositories - modules/shaper.git/blobdiff - src/ExchangePlugin/ExchangePlugin_ImportPart.cpp
Salome HOME
Task 5.1.7: To be able to export a part to a file and import it into an existing...
[modules/shaper.git] / src / ExchangePlugin / ExchangePlugin_ImportPart.cpp
index 9522e20bc53d88a457bc2a38bc86ab3fa8904a5f..4a40de68c25028fc739ef0f9bcb9545040890b40 100644 (file)
 
 #include <PartSetPlugin_Part.h>
 
+#include <map>
+#include <sstream>
+
+// Update names of imported features/results concurent with existing objects.
+static void correntNonUniqueNames(DocumentPtr theDocument, std::list<FeaturePtr>& theImported);
+
 ExchangePlugin_ImportPart::ExchangePlugin_ImportPart()
 {
 }
@@ -47,7 +53,8 @@ void ExchangePlugin_ImportPart::execute()
   SessionPtr aSession = ModelAPI_Session::get();
   DocumentPtr aDoc = document();
   bool isPartSet = aDoc == aSession->moduleDocument();
-  bool isOk = aDoc->import(aFilename.c_str(), isPartSet);
+  std::list<FeaturePtr> anImportedFeatures;
+  bool isOk = aDoc->import(aFilename.c_str(), anImportedFeatures, isPartSet);
   if (!isOk && isPartSet) {
     // there are features not appropriate for PartSet,
     // create new part and load there
@@ -57,8 +64,122 @@ void ExchangePlugin_ImportPart::execute()
       aPartFeature->execute();
       aPartResult = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeature->lastResult());
     }
-    isOk = aPartResult && aPartResult->partDoc()->import(aFilename.c_str());
+    if (aPartResult) {
+      aDoc = aPartResult->partDoc();
+      isOk = aDoc->import(aFilename.c_str(), anImportedFeatures);
+    }
   }
-  if (!isOk)
+  if (isOk)
+    correntNonUniqueNames(aDoc, anImportedFeatures);
+  else
     setError("Cannot import the document.");
 }
+
+
+// ================================     Auxiliary functions     ===================================
+
+bool splitName(std::string& theName, int& theIndex)
+{
+  size_t aLastUndercore = theName.find_last_of('_');
+  bool isOk = aLastUndercore != std::string::npos;
+  if (isOk) {
+    char* isNumber;
+    std::string anIndexStr = theName.substr(aLastUndercore + 1);
+    theIndex = std::strtol(anIndexStr.c_str(), &isNumber, 10);
+    isOk = isNumber != 0;
+    if (isOk)
+      theName.erase(aLastUndercore);
+  }
+  return isOk;
+}
+
+void addIndexedName(const std::string& theName, std::map<std::string, std::set<int> >& theIndexedNames)
+{
+  std::string aName = theName;
+  int anIndex = 0;
+  bool isIndexed = splitName(aName, anIndex);
+  std::set<int>& anIndices = theIndexedNames[aName];
+  if (isIndexed)
+    anIndices.insert(anIndex);
+}
+
+// Collect names of features and results in the document before the import.
+// The name of indexed feature/result will be split to the name and the index. For example ,
+// 'Point_1', 'Point_2' will be placed at the same key with the set of corrsponding indices:
+// 'Point_1', 'Point_2' => {'Point', [1, 2]}.
+// Thus, the new point should have index 3 and therefore the name 'Point_3'.
+static void collectOldNames(DocumentPtr theDocument, std::list<FeaturePtr>& theAvoided,
+                            std::map<std::string, std::set<int> >& theIndexedNames)
+{
+  std::list<FeaturePtr> anAllFeatures = theDocument->allFeatures();
+  std::list<FeaturePtr>::iterator aFIt = anAllFeatures.begin();
+  std::list<FeaturePtr>::iterator anAvoidIt = theAvoided.begin();
+  for (; aFIt != anAllFeatures.end(); ++aFIt) {
+    if (anAvoidIt != theAvoided.end() && *aFIt == *anAvoidIt) {
+      // skip this feature
+      ++anAvoidIt;
+      continue;
+    }
+
+    // store name of feature
+    addIndexedName((*aFIt)->data()->name(), theIndexedNames);
+    // store names of results
+    const std::list<ResultPtr>& aResults = (*aFIt)->results();
+    for (std::list<ResultPtr>::const_iterator aRIt = aResults.begin();
+         aRIt != aResults.end(); ++aRIt)
+      addIndexedName((*aRIt)->data()->name(), theIndexedNames);
+  }
+}
+
+static std::string uniqueName(const std::string& theName,
+                              std::map<std::string, std::set<int> >& theExistingNames)
+{
+  std::string aName = theName;
+  int anIndex = 1;
+  splitName(aName, anIndex);
+
+  std::map<std::string, std::set<int> >::iterator aFound = theExistingNames.find(aName);
+  bool isUnique = false;
+  if (aFound == theExistingNames.end())
+    isUnique = true;
+  else {
+    // search the appropriate index
+    std::set<int>::iterator aFoundIndex = aFound->second.find(anIndex);
+    for (; aFoundIndex != aFound->second.end(); ++aFoundIndex, ++anIndex)
+      if (anIndex != *aFoundIndex)
+        break;
+    // compose the new name
+    std::ostringstream aNewName;
+    aNewName << aName << "_" << anIndex;
+    aName = aNewName.str();
+    // add new index
+    aFound->second.insert(anIndex);
+  }
+
+  if (isUnique) {
+    // name is unique
+    aName = theName;
+    addIndexedName(theName, theExistingNames);
+  }
+  return aName;
+}
+
+void correntNonUniqueNames(DocumentPtr theDocument, std::list<FeaturePtr>& theImported)
+{
+  std::map<std::string, std::set<int> > aNames;
+  collectOldNames(theDocument, theImported, aNames);
+
+  for (std::list<FeaturePtr>::iterator anIt = theImported.begin();
+       anIt != theImported.end(); ++anIt) {
+    // update name of feature
+    std::string aNewName = uniqueName((*anIt)->data()->name(), aNames);
+    (*anIt)->data()->setName(aNewName);
+    // update names of results
+    const std::list<ResultPtr>& aResults = (*anIt)->results();
+    for (std::list<ResultPtr>::const_iterator aRIt = aResults.begin();
+         aRIt != aResults.end(); ++aRIt) {
+      aNewName = uniqueName((*aRIt)->data()->name(), aNames);
+      (*aRIt)->data()->setName(aNewName);
+    }
+  }
+}