StateRenamer.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "StateRenamer.h"
25 
26 #include <filesystem>
27 #include <IceUtil/UUID.h>
28 #include <QDir>
29 #include <QDirIterator>
30 #include <QFileInfo>
34 #include <filesystem>
35 
37 
38 using namespace armarx;
39 using namespace armarx::statechartmodel;
40 
41 bool StateRenamer::RenameState(const QVector<InstanceRenameInfo>& instanceRenameInfos,
42  const StateTreeNodePtr& state,
43  const QString& newStateName,
44  const StatechartGroupPtr& group)
45 {
46  RenameStateInstances(instanceRenameInfos);
47 
48  if (!RenameStateClass(state, newStateName))
49  {
50  return false;
51  }
52 
53  if (!AdjustStatechartGroupFile(group, state, newStateName))
54  {
55  return false;
56  }
57 
58  auto cmakeListPath = QString::fromUtf8((group->getBoostDefinitionFilePath().remove_filename() / "CMakeLists.txt").c_str());
59  auto fileContents = GuiStatechartGroupXmlReader::ReadFileContents(cmakeListPath);
60  fileContents = fileContents.replace(state->getState()->getStateName() + ".xml", newStateName + ".xml");
61  fileContents = fileContents.replace(state->getState()->getStateName() + ".cpp", newStateName + ".cpp");
62  fileContents = fileContents.replace(state->getState()->getStateName() + ".h", newStateName + ".h");
63  fileContents = fileContents.replace(state->getState()->getStateName() + ".generated.h", newStateName + ".generated.h");
64  GroupXmlWriter::WriteFileContents(cmakeListPath, fileContents);
65 
66  return true;
67 }
68 
69 void StateRenamer::RenameStateInstances(const QVector<InstanceRenameInfo>& instanceRename)
70 {
71  for (const auto& entry : instanceRename)
72  {
73  if (entry.fromName == entry.toName)
74  {
75  continue;
76  }
77 
78  auto xmlProcessor = [&](const std::string & nodeName, const std::string & attribName, const std::string & attribValue) -> std::string
79  {
80  QString value = QString::fromUtf8(attribValue.c_str());
81  const bool nameRef = attribName == "name" && value == entry.fromName;
82  const bool transitionRef = nodeName == "Transition" && (attribName == "from" || attribName == "to") && value == entry.fromName;
83  const bool startRef = nodeName == "StartState" && attribName == "substateName" && value == entry.fromName;
84 
85  if (nameRef || transitionRef || startRef)
86  {
87  return entry.toName.toUtf8().data();
88  }
89 
90  return attribValue;
91  };
92 
93  auto statePath = entry.parentState->getBoostXmlFilePath(StateTreeNode::Path::Absolute).string();
94 
95  ARMARX_VERBOSE_S << "processing xml file: " << statePath;
96  auto readerPtr = RapidXmlReader::FromFile(statePath);
97  RapidXmlReaderNode rootNode = readerPtr->getRoot();
98  RapidXmlWriter writer;
99  auto writerNode = writer.createRootNode(rootNode.name());
100 
101  GroupCloner::ProcessXMLFile(rootNode, writerNode, xmlProcessor);
102 
103  writer.saveToFile(statePath, true);
104  }
105 }
106 
107 bool StateRenamer::RenameStateClass(const StateTreeNodePtr& state, const QString& newStateName)
108 {
109  const std::string newStateNameStd = newStateName.toUtf8().data();
110  auto oldStateName = state->getState()->getStateName();
111  auto oldStatePath = state->getBoostXmlFilePath(StateTreeNode::Path::Absolute);
112  auto newStatePath = state->getBoostXmlFilePath(StateTreeNode::Path::Absolute).remove_filename() / (newStateNameStd + ".xml");
113  auto readerPtr = RapidXmlReader::FromFile(oldStatePath.string());
114  RapidXmlReaderNode rootNode = readerPtr->getRoot();
115  RapidXmlWriter writer;
116  auto writerNode = writer.createRootNode(rootNode.name());
117 
118  auto xmlProcessor = [&](const std::string & nodeName, const std::string & attribName, const std::string & attribValue) -> std::string
119  {
120  QString value = QString::fromUtf8(attribValue.c_str());
121 
122  if (nodeName == "State" && attribName == "name" && value == state->getState()->getStateName())
123  {
124  ARMARX_CHECK_EXPRESSION(state->getState()->getStateName() == value)
125  << "expected state file of '"
126  << state->getState()->getStateName()
127  << "', but got '" << value << "'";
128  return newStateName.toUtf8().data();
129  }
130 
131  return attribValue;
132  };
133 
134  GroupCloner::ProcessXMLFile(rootNode, writerNode, xmlProcessor);
135  writer.saveToFile(newStatePath.string(), true);
136 
137  QVector<QPair<QRegExp, QString>> codeFileReplaceList;
138  codeFileReplaceList.push_back({QRegExp{"\\b(" + oldStateName + ")\\b"}, newStateName});
139  codeFileReplaceList.push_back({QRegExp{"_" + oldStateName + "_"}, "_" + newStateName + "_"});
140  codeFileReplaceList.push_back({QRegExp{oldStateName + "GeneratedBase"}, newStateName + "GeneratedBase"});
141 
142  bool success = true;
143 
144  if (state->checkCppExists())
145  {
146  auto oldCppPath = state->getBoostCppFilePath();
147  auto newCppPath = state->getBoostCppFilePath().parent_path() / (newStateNameStd + ".cpp");
148  auto oldHPath = state->getBoostHFilePath();
149  auto newHPath = state->getBoostHFilePath().parent_path() / (newStateNameStd + ".h");
150  auto genPath = state->getBoostGeneratedHFilePath();
151 
152  GroupCloner::RegexReplaceFile(QString::fromUtf8(oldCppPath.c_str()), QString::fromUtf8(newCppPath.c_str()), codeFileReplaceList);
153  GroupCloner::RegexReplaceFile(QString::fromUtf8(oldHPath.c_str()), QString::fromUtf8(newHPath.c_str()), codeFileReplaceList);
154  success = !std::filesystem::exists(oldCppPath) || std::filesystem::remove(oldCppPath);
155  success &= !std::filesystem::exists(oldHPath) || std::filesystem::remove(oldHPath);
156  success &= !std::filesystem::exists(genPath) || std::filesystem::remove(genPath);
157  }
158 
159 
160  return success;
161 }
162 
163 bool StateRenamer::AdjustStatechartGroupFile(const StatechartGroupPtr& group, const StateTreeNodePtr& state, const QString& newName)
164 {
165  std::string path = group->getDefinitionFilePath().toUtf8().data();
166  auto readerPtr = RapidXmlReader::FromFile(path);
167  RapidXmlReaderNode rootNode = readerPtr->getRoot();
168  RapidXmlWriter writer;
169  auto writerNode = writer.createRootNode(rootNode.name());
170 
171  auto scgxmlProcessor = [&](const std::string & nodeName, const std::string & attribName, const std::string & attribValue) -> std::string
172  {
173  QString value = QString::fromUtf8(attribValue.c_str());
174 
175  if (nodeName == "State" && attribName == "filename" && value == state->getBasename())
176  {
177  const QString newStateFile = newName + ".xml";
178  return newStateFile.toUtf8().data();
179  }
180 
181  return attribValue;
182  };
183 
184  GroupCloner::ProcessXMLFile(rootNode, writerNode, scgxmlProcessor);
185  writer.saveToFile(path, true);
186  return true;
187 }
188 
189 bool StateRenamer::AttemptMoveTo(const QString& source, const QString& target)
190 {
191  if (!QFile(source).rename(target))
192  {
193  ARMARX_ERROR_S << "Could not move '" << source << "' to '" << target << "'";
194  return false;
195  }
196 
197  return true;
198 }
armarx::RapidXmlReader::FromFile
static RapidXmlReaderPtr FromFile(const std::string &path)
Definition: RapidXmlReader.h:497
armarx::RapidXmlWriter
Definition: RapidXmlWriter.h:99
XmlReader.h
armarx::GuiStatechartGroupXmlReader::ReadFileContents
static QString ReadFileContents(QString path)
Definition: GroupXmlReader.cpp:109
armarx::StateTreeNodePtr
std::shared_ptr< StateTreeNode > StateTreeNodePtr
Definition: StatechartGroupDefs.h:31
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:688
armarx::GroupCloner::ProcessXMLFile
static void ProcessXMLFile(RapidXmlReaderNode source, RapidXmlWriterNode target, const Function &processorFunction)
Definition: GroupCloner.h:64
StateRenamer.h
armarx::GroupCloner::RegexReplaceFile
static void RegexReplaceFile(const QString &srcFilePath, const QString &tgtFilePath, const QVector< QPair< QRegExp, QString >> &replaceList)
Definition: GroupCloner.cpp:499
armarx::RapidXmlReaderNode::name
std::string name() const
Definition: RapidXmlReader.h:349
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::GroupXmlWriter::WriteFileContents
static void WriteFileContents(QString path, QString contents)
Definition: GroupXmlWriter.cpp:90
if
if(!yyvaluep)
Definition: Grammar.cpp:724
ARMARX_ERROR_S
#define ARMARX_ERROR_S
Definition: Logging.h:209
armarx::statechartmodel
Definition: XmlWriter.h:36
armarx::RapidXmlReaderNode
Definition: RapidXmlReader.h:68
boost::source
Vertex source(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:681
GroupXmlWriter.h
armarx::StatechartGroupPtr
std::shared_ptr< StatechartGroup > StatechartGroupPtr
Definition: StatechartGroupDefs.h:34
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
armarx::RapidXmlWriter::saveToFile
void saveToFile(const std::string &path, bool indent)
Definition: RapidXmlWriter.h:126
GroupCloner.h
armarx::RapidXmlWriter::createRootNode
RapidXmlWriterNode createRootNode(const std::string &name)
Definition: RapidXmlWriter.h:113
GroupXmlReader.h
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:200
armarx::StateRenamer::RenameState
static bool RenameState(const QVector< InstanceRenameInfo > &instanceRenameInfos, const StateTreeNodePtr &state, const QString &newStateName, const StatechartGroupPtr &group)
Definition: StateRenamer.cpp:41
armarx::StateTreeNode::Path::Absolute
@ Absolute
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::status::success
@ success