27 #include <IceUtil/UUID.h>
29 #include <QDirIterator>
39 packageTool(packageTool)
46 QVector<statechartmodel::StatePtr> states = group->getAllStates(
false);
52 auto it = std::remove_if(result.begin(), result.end(), [&](
const StatechartGroupPtr & g)
54 return g->getGroupPath() == group->getGroupPath();
56 result.erase(it, result.end());
64 QVector<StatechartGroupPtr> result;
68 auto group = treeModel.lock()->getGroupByName(groupMapping.groupName);
76 result.push_back(group);
88 for (
const auto& gEntry : groupsNames)
90 const auto& g = gEntry.first;
91 ARMARX_INFO_S <<
" " << g->getName() <<
" -> " << gEntry.second;
95 return gm.groupName == g->getName();
100 ARMARX_WARNING_S <<
"Mapping file seems to be inconsistent with folder structure";
101 return std::optional<StatechartGroupMapping>();
104 QVector<statechartmodel::StatePtr> states = g->getAllStates();
112 return sm.stateName == state->getStateName();
117 QString targetUUID = state->getUUID();
121 targetUUID = QString::fromUtf8(IceUtil::generateUUID().c_str());
124 groupMapping.stateMappings.insert({state->getStateName(), state->getUUID(), targetUUID});
131 QVector<StatechartGroupPtr> groups;
132 std::transform(groupsNames.begin(), groupsNames.end(), std::back_inserter(groups),
133 [](
const QPair<StatechartGroupPtr, QString>& p)
140 if (!g->existsCMakeLists())
142 ARMARX_WARNING_S << g->getName() <<
" at " << g->getGroupPath() <<
" contains no CMakeLists.txt - is it an installed package? Installed packages cannot be cloned since they do not contain the CMakelists file and CPP files";
143 return std::optional<StatechartGroupMapping>();
147 registerGroups(groups, newMapping, packageDir);
149 for (
const auto& g : groups)
151 if (!cloneGroupTo(g, packageDir, newMapping))
153 ARMARX_WARNING_S <<
"Cloning group '" << g->getName() <<
"' failed, aborting...";
154 return std::optional<StatechartGroupMapping>();
160 return std::optional<StatechartGroupMapping>(newMapping);
163 void GroupCloner::registerGroups(
const QVector<StatechartGroupPtr>& groups,
const StatechartGroupMapping& mapping,
const QString& packageDir)
165 const QString packageName = QFileInfo(packageDir).fileName();
171 QString tempStateName = *groupName +
"TempState";
172 packageTool->addStatechart(groupName->toUtf8().data(), tempStateName.toUtf8().data(), packageDir.toUtf8().data());
174 packageDir + QDir::separator() +
175 "source" + QDir::separator() +
176 packageName + QDir::separator() +
177 "statecharts" + QDir::separator() +
185 QFileInfo packageInfo(packageFolder);
190 QString newGroupName = *newGroupNameOpt;
192 const QString oldPackageName = group->getPackageName();
193 const QString newPackageName = QFileInfo(packageFolder).fileName();
194 const QString packageStatechartsDir =
195 packageFolder + QDir::separator() +
"source" + QDir::separator() + newPackageName + QDir::separator() +
"statecharts";
196 QString newGroupPath = packageStatechartsDir + QDir::separator() + newGroupName;
198 ARMARX_INFO_S <<
"Cloning '" << group->getGroupPath() <<
"' to '" << newGroupPath <<
"'";
200 if (QDir(newGroupPath).exists())
202 ARMARX_WARNING_S << newGroupPath <<
" already exists, but should not exist. Skipping...";
205 else if (!QDir(newGroupPath).mkpath(
"."))
211 QMap<QString, QString> renameCandidateMap;
212 renameCandidateMap.insert(group->getName() +
".scgxml", newGroupName +
".scgxml");
213 renameCandidateMap.insert(group->getName() +
"RemoteStateOfferer.h", newGroupName +
"RemoteStateOfferer.h");
214 renameCandidateMap.insert(group->getName() +
"RemoteStateOfferer.cpp", newGroupName +
"RemoteStateOfferer.cpp");
215 renameCandidateMap.insert(group->getName() +
"StatechartContext.h", newGroupName +
"StatechartContext.h");
216 renameCandidateMap.insert(group->getName() +
"StatechartContext.cpp", newGroupName +
"StatechartContext.cpp");
218 QMap<QString, bool> expectedFileSeenMap;
219 expectedFileSeenMap.insert(
"CMakeLists.txt",
false);
220 expectedFileSeenMap.insert(group->getName() +
".scgxml",
false);
221 expectedFileSeenMap.insert(group->getName() +
"RemoteStateOfferer.h",
false);
222 expectedFileSeenMap.insert(group->getName() +
"RemoteStateOfferer.cpp",
false);
225 QVector<QString> optionalExpectedFiles;
226 optionalExpectedFiles.push_back(group->getName() +
"StatechartContext.generated.h");
227 optionalExpectedFiles.push_back(group->getName() +
"StatechartContext.h");
228 optionalExpectedFiles.push_back(group->getName() +
"StatechartContext.cpp");
230 QVector<QString> doNotCopy;
231 doNotCopy.push_back(group->getName() +
"StatechartContext.generated.h");
233 QVector<StateTreeNodePtr> allNodes = group->getAllNodes();
247 expectedFileSeenMap.insert(xml,
false);
249 if (n->checkCppExists())
251 expectedFileSeenMap.insert(
cpp,
false);
252 expectedFileSeenMap.insert(h,
false);
253 optionalExpectedFiles.push_back(gen);
256 doNotCopy.push_back(gen);
259 QVector<QPair<QRegExp, QString>> codeFileReplaceList;
260 codeFileReplaceList.push_back({QRegExp(oldPackageName +
"_" + group->getName()), newPackageName +
"_" + newGroupName});
261 codeFileReplaceList.push_back({QRegExp(oldPackageName +
"::" + group->getName()), newPackageName +
"::" + newGroupName});
262 codeFileReplaceList.push_back({QRegExp(
"namespace[\\n\\s]*" + group->getName()),
"namespace " + newGroupName});
263 codeFileReplaceList.push_back({QRegExp(
"namespace[\\n\\s]*armarx::" + group->getName()),
"namespace armarx::" + newGroupName});
264 codeFileReplaceList.push_back({QRegExp(group->getName() +
"StatechartContext"), newGroupName +
"StatechartContext"});
265 codeFileReplaceList.push_back({QRegExp(group->getName() +
"RemoteStateOfferer"), newGroupName +
"RemoteStateOfferer"});
266 codeFileReplaceList.push_back({QRegExp(oldPackageName +
"/statecharts/" + group->getName()), newPackageName +
"/statecharts/" + newGroupName});
268 QVector<QPair<QRegExp, QString>> cmakeListsReplaceList;
269 cmakeListsReplaceList.push_back({QRegExp(
"armarx_component_set_name\\(\"" + group->getName() +
"\"\\)"),
270 "armarx_component_set_name(\"" + newGroupName +
"\")"
272 cmakeListsReplaceList.push_back({QRegExp(group->getName() +
"\\.scgxml"), newGroupName +
".scgxml"});
273 cmakeListsReplaceList.push_back({QRegExp(group->getName() +
"StatechartContext"), newGroupName +
"StatechartContext"});
274 cmakeListsReplaceList.push_back({QRegExp(group->getName() +
"RemoteStateOfferer"), newGroupName +
"RemoteStateOfferer"});
276 auto xmlProcessor = [&](
const std::string&,
const std::string & attribName,
const std::string & attribValue) -> std::string
278 QString
value = QString::fromUtf8(attribValue.c_str());
280 if (attribName ==
"refuuid" || attribName ==
"uuid")
282 QString
value = QString::fromUtf8(attribValue.c_str());
286 return qresult->toUtf8().data();
293 else if (attribName ==
"proxyName")
295 value =
value.replace(
"RemoteStateOfferer",
"");
299 return std::string(qresult->toUtf8().data()) +
"RemoteStateOfferer";
310 auto scgxmlProcessor = [&](
const std::string&,
const std::string & attribName,
const std::string & attribValue) -> std::string
312 QString
value = QString::fromUtf8(attribValue.c_str());
314 if (attribName ==
"package" && oldPackageName ==
value)
316 return newPackageName.toUtf8().data();
318 else if (attribName ==
"name")
322 return newGroupName->toUtf8().data();
329 QDirIterator it(group->getGroupPath(), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
333 const auto f = QFileInfo(it.next());
334 QString relativePath = QDir(group->getGroupPath()).relativeFilePath(f.absoluteFilePath());
335 QString srcFilePath = group->getGroupPath() + QDir::separator() + relativePath;
336 QString tgtFilePath = newGroupPath + QDir::separator() + (renameCandidateMap.contains(relativePath) ? renameCandidateMap[relativePath] : relativePath);
340 if (!QDir(tgtFilePath).mkpath(
"."))
350 if (doNotCopy.contains(relativePath))
356 ARMARX_DEBUG_S <<
"Cloning file '" << srcFilePath <<
"' -> '" << tgtFilePath <<
"'";
358 if (expectedFileSeenMap.contains(relativePath))
360 expectedFileSeenMap[relativePath] =
true;
362 else if (!optionalExpectedFiles.contains(relativePath))
364 ARMARX_WARNING_S <<
"Unexpected file '" << relativePath <<
"', processing anyway... - expected files" << expectedFileSeenMap.toStdMap();
367 if (f.suffix() ==
"xml" || f.suffix() ==
"scgxml")
375 if (f.suffix() ==
"xml")
384 writer.
saveToFile(tgtFilePath.toUtf8().data(),
true);
386 else if (f.suffix() ==
"cpp" || f.suffix() ==
"h")
391 else if (f.fileName() ==
"CMakeLists.txt")
403 for (
const auto& f : expectedFileSeenMap.toStdMap())
407 ARMARX_WARNING_S <<
"Expected file '" << f.first <<
"' was not found while cloning";
417 QVector<StatechartGroupPtr> result;
419 for (
const auto& state : states)
421 auto stateGroup = treeModel->getNodeByState(state)->getGroup();
423 bool alreadyExists = std::find_if(result.constBegin(), result.constEnd(), [&](
const StatechartGroupPtr & depGroup)
425 return stateGroup->getDefinitionFilePath() == depGroup->getDefinitionFilePath();
426 }) != result.constEnd();
430 result.push_back(stateGroup);
437 bool GroupCloner::CopyRecursively(
const QString& srcPath,
const QString& tgtParentDirPath)
439 QFileInfo srcInfo(srcPath);
440 QFileInfo tgtInfo(tgtParentDirPath);
442 if (srcInfo.fileName() == tgtInfo.fileName())
444 auto newDir = QDir(tgtParentDirPath);
446 return CopyRecursively(srcPath, newDir.path());
449 if (!tgtInfo.isDir() && tgtInfo.exists())
457 const QString newTgtDirPath = tgtParentDirPath + QDir::separator() + srcInfo.fileName();
458 const auto newDir = QDir(newTgtDirPath);
466 if (!newDir.mkpath(
"."))
472 QDir sourceDir(srcPath);
473 QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
475 for (
const QString& fileName : fileNames)
477 const QString newSrcFilePath = srcPath + QDir::separator() + fileName;
479 if (!CopyRecursively(newSrcFilePath, newTgtDirPath))
487 const QString newTgtFilePath = tgtParentDirPath + QDir::separator() + srcInfo.fileName();
503 for (
const auto& replace : replaceList)
505 fileContent = fileContent.replace(replace.first, replace.second);
516 if (dir.exists(dirName))
518 for (QFileInfo info : dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst))
522 result =
RemoveDir(info.absoluteFilePath());
526 result = QFile::remove(info.absoluteFilePath());
535 result = dir.rmdir(dirName);