diff --git a/src/Plugins/ITKImageProcessing/src/ITKImageProcessing/Filters/ITKImportImageStack.cpp b/src/Plugins/ITKImageProcessing/src/ITKImageProcessing/Filters/ITKImportImageStack.cpp index 8c306983ca..153a127a1f 100644 --- a/src/Plugins/ITKImageProcessing/src/ITKImageProcessing/Filters/ITKImportImageStack.cpp +++ b/src/Plugins/ITKImageProcessing/src/ITKImageProcessing/Filters/ITKImportImageStack.cpp @@ -212,7 +212,7 @@ Result<> ReadImageStack(DataStructure& dataStructure, const DataPath& imageGeomP // rename grayscale array to reflect original { auto& gray = importedDataStructure.getDataRefAs(imageDataPath.getParent().createChildPath("gray" + imageDataPath.getTargetName())); - if(gray.canRename(imageDataPath.getTargetName()) != 1) + if(!gray.canRename(imageDataPath.getTargetName())) { return MakeErrorResult(-64543, fmt::format("Unable to rename the internal grayscale array to {}", imageDataPath.getTargetName())); } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RenameDataObject.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RenameDataObject.cpp index b2454fa2a2..8afefba03f 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RenameDataObject.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RenameDataObject.cpp @@ -56,6 +56,8 @@ Parameters RenameDataObject::parameters() const Parameters params; params.insertSeparator(Parameters::Separator{"Input Parameters"}); + params.insert(std::make_unique(k_AllowOverwrite_Key, "Allow Overwrite", + "If true existing object with `New Name` and all of its nested objects will be removed to free up the name for the target DataObject", false)); params.insert(std::make_unique(k_DataObject_Key, "DataObject to Rename", "DataPath pointing to the target DataObject", DataPath())); params.insert(std::make_unique(k_NewName_Key, "New Name", "Target DataObject name", "")); return params; @@ -71,10 +73,11 @@ IFilter::UniquePointer RenameDataObject::clone() const IFilter::PreflightResult RenameDataObject::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel) const { + auto allowOverwrite = filterArgs.value(k_AllowOverwrite_Key); auto dataGroupPath = filterArgs.value(k_DataObject_Key); auto newName = filterArgs.value(k_NewName_Key); - auto action = std::make_unique(dataGroupPath, newName); + auto action = std::make_unique(dataGroupPath, newName, allowOverwrite); OutputActions actions; actions.appendAction(std::move(action)); diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RenameDataObject.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RenameDataObject.hpp index 0712195f54..47f4ac3bd3 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RenameDataObject.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/RenameDataObject.hpp @@ -25,6 +25,7 @@ class SIMPLNXCORE_EXPORT RenameDataObject : public IFilter RenameDataObject& operator=(RenameDataObject&&) noexcept = delete; // Parameter Keys + static inline constexpr StringLiteral k_AllowOverwrite_Key = "allow_overwrite"; static inline constexpr StringLiteral k_DataObject_Key = "data_object"; static inline constexpr StringLiteral k_NewName_Key = "new_name"; diff --git a/src/simplnx/DataStructure/BaseGroup.cpp b/src/simplnx/DataStructure/BaseGroup.cpp index 37af7527f5..a6d8a61858 100644 --- a/src/simplnx/DataStructure/BaseGroup.cpp +++ b/src/simplnx/DataStructure/BaseGroup.cpp @@ -246,3 +246,8 @@ void BaseGroup::checkUpdatedIdsImpl(const std::vector> { m_DataMap.updateIds(updatedIds); } + +std::vector BaseGroup::GetChildrenIds() +{ + return m_DataMap.getKeys(); +} \ No newline at end of file diff --git a/src/simplnx/DataStructure/BaseGroup.hpp b/src/simplnx/DataStructure/BaseGroup.hpp index ad500392da..909dfd7e32 100644 --- a/src/simplnx/DataStructure/BaseGroup.hpp +++ b/src/simplnx/DataStructure/BaseGroup.hpp @@ -328,6 +328,11 @@ class SIMPLNX_EXPORT BaseGroup : public DataObject */ std::vector GetChildrenNames(); + /** + * @brief Querys the DataMap for the object ids in m_DataMap + */ + std::vector GetChildrenIds(); + protected: /** * @brief Creates a BaseGroup with the target DataStructure and name. diff --git a/src/simplnx/DataStructure/DataObject.cpp b/src/simplnx/DataStructure/DataObject.cpp index 46a730a552..3d8823774f 100644 --- a/src/simplnx/DataStructure/DataObject.cpp +++ b/src/simplnx/DataStructure/DataObject.cpp @@ -162,38 +162,38 @@ std::string DataObject::getName() const return m_Name; } -int DataObject::canRename(const std::string& name) const +bool DataObject::canRename(const std::string& name) const { if(name == getName()) { - return 1; + return true; } if(!IsValidName(name)) { - return 0; + return false; } const auto* dataStructPtr = getDataStructure(); if(dataStructPtr == nullptr) { - return 0; + return false; } - return (std::any_of(m_ParentList.cbegin(), m_ParentList.cend(), [dataStructPtr, name](IdType parentId) { + return !std::any_of(m_ParentList.cbegin(), m_ParentList.cend(), [dataStructPtr, name](IdType parentId) { const auto* baseGroupPtr = dataStructPtr->getDataAs(parentId); if(baseGroupPtr == nullptr) { std::cout << "DataObject::canRename(name=" << name << ") cannot get baseGroup from parentId = " << parentId << std::endl; } return baseGroupPtr != nullptr && baseGroupPtr->contains(name); - })) ? 2 : 0; + }); } bool DataObject::rename(const std::string& name) { - if(canRename(name) != 1) + if(!canRename(name)) { return false; } diff --git a/src/simplnx/DataStructure/DataObject.hpp b/src/simplnx/DataStructure/DataObject.hpp index 387671713f..1198bde9ce 100644 --- a/src/simplnx/DataStructure/DataObject.hpp +++ b/src/simplnx/DataStructure/DataObject.hpp @@ -207,7 +207,7 @@ class SIMPLNX_EXPORT DataObject * @param name * @return int: 0 = false, 1 = true, 2 = duplicate object found */ - int canRename(const std::string& name) const; + bool canRename(const std::string& name) const; /** * @brief Attempts to rename the DataObject to the provided value. diff --git a/src/simplnx/Filter/Actions/RenameDataAction.cpp b/src/simplnx/Filter/Actions/RenameDataAction.cpp index 158ca7a94b..b7b293fb54 100644 --- a/src/simplnx/Filter/Actions/RenameDataAction.cpp +++ b/src/simplnx/Filter/Actions/RenameDataAction.cpp @@ -7,6 +7,37 @@ using namespace nx::core; +namespace +{ +Result<> TerminateNodesRecursively(DataStructure& dataStructure, DataObject::IdType id, IDataAction::Mode mode, const bool checkDependence) +{ + Result<> result = {}; + DataObject* node = dataStructure.getData(id); + + if(checkDependence) + { + auto parentIds = node->getParentIds(); + if(parentIds.size() > 1) + { + return {}; + } + } + + auto childIds = dataStructure.getDataRefAs(id).GetChildrenIds(); + if(!childIds.empty()) + { + for(const auto& childId : childIds) + { + result = MergeResults(result, std::move(TerminateNodesRecursively(dataStructure, childId, mode, checkDependence))); + } + } + + dataStructure.removeData(node->getId()); + + return result; +} +} // namespace + namespace nx::core { RenameDataAction::RenameDataAction(const DataPath& path, const std::string& newName, bool overwrite) @@ -28,31 +59,64 @@ Result<> RenameDataAction::apply(DataStructure& dataStructure, Mode mode) const return MakeErrorResult(-6601, ss); } - int validRename = dataObject->canRename(m_NewName); - if(validRename == 0) - { - std::string ss = fmt::format("{}Could not rename DataObject at '{}' to '{}'", prefix, m_Path.toString(), m_NewName); - return MakeErrorResult(-6602, ss); - } - if(validRename == 2) + Result<> result = {}; + + bool validRename = dataObject->canRename(m_NewName); + + if(!validRename) { if(m_Overwrite) { if(mode == Mode::Preflight) { + std::vector pathVec = m_Path.getPathVector(); + + // The canRename() function returns 1 if the base object already has the objects new name + // so in that case we will never make it here + for(const auto& name : pathVec) + { + if(name == m_NewName) + { + std::string ss = fmt::format("{}The object that would be overwritten is a parent container to {} cannot rename to {}", prefix, m_Path.getTargetName(), m_NewName); + return MakeErrorResult(-6601, ss); + } + } + std::string ss = fmt::format("{}Another object exists with that name, will overwrite destroying other DataObject at '{}' and replacing it with '{}'", prefix, m_NewName, m_Path.toString()); - Result<>{}.warnings().emplace_back(Warning{-6603,ss}); + result.warnings().emplace_back(Warning{-6602, ss}); + } + else + { + DataObject::IdType targetId = std::numeric_limits::max(); + for(auto dataObjectID : dataStructure.getAllDataObjectIds()) + { + if(dataStructure.getData(dataObjectID)->getName() == m_NewName) + { + targetId = dataObjectID; + break; + } + } + + if(dataStructure.getDataAs(targetId) != nullptr) + { + // Recursive removal of overwritten object + result = MergeResults(result, ::TerminateNodesRecursively(dataStructure, targetId, mode, true)); + } + else + { + dataStructure.removeData(targetId); + } } } else { - std::string ss = fmt::format("{}Another object exists with that name, will not rename DataObject at '{}' to '{}'", prefix, m_Path.toString(), m_NewName); - return MakeErrorResult(-6604, ss); + std::string ss = fmt::format("{}Could not rename DataObject at '{}' to '{}'", prefix, m_Path.toString(), m_NewName); + return MakeErrorResult(-6603, ss); } } dataObject->rename(m_NewName); - return {}; + return result; } IDataAction::UniquePointer RenameDataAction::clone() const