XmlContextBaseClassGenerator.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  */
25 
26 #include <filesystem>
27 
28 #include <boost/format.hpp>
29 #include <boost/regex.hpp>
30 
31 #include <SimoxUtility/algorithm/string/string_tools.h>
32 
38 
39 #include "../GroupXmlReader.h"
40 using namespace armarx;
41 #include <tuple>
42 
44 {
45 }
46 
47 std::tuple<std::string, std::string>
48 XmlContextBaseClassGenerator::GenerateCpp(std::vector<std::string> namespaces,
49  std::vector<std::string> proxies,
50  std::string groupName,
51  VariantInfoPtr variantInfo,
52  const std::set<std::string>& usedVariantTypes)
53 {
54  CppClassPtr cppClass, cppClassBase;
55  std::tie(cppClass, cppClassBase) =
56  BuildClass(namespaces, proxies, groupName, variantInfo, usedVariantTypes);
57  CppWriterPtr writer(new CppWriter(true));
58  cppClass->writeCpp(writer);
59  CppWriterPtr writerBase(new CppWriter(true));
60  cppClassBase->writeCpp(writerBase);
61  return std::make_tuple(writer->getString(), writerBase->getString());
62 }
63 
64 std::tuple<CppClassPtr, CppClassPtr>
65 XmlContextBaseClassGenerator::BuildClass(std::vector<std::string> namespaces,
66  std::vector<std::string> proxies,
67  std::string groupName,
68  VariantInfoPtr variantInfo,
69  const std::set<std::string>& usedVariantTypes)
70 {
71  std::string className = groupName + "StatechartContext";
72 
73  for (std::string& ns : namespaces)
74  {
75  ns = simox::alg::replace_all(ns, "-", "_");
76  }
77 
78  CppClassPtr cppImplClass(new CppClass(namespaces, className));
79  CppClassPtr cppBaseClass(new CppClass(namespaces, className + "Base"));
80 
81  cppImplClass->addInherit("virtual public XMLStatechartContext");
82  cppImplClass->addInherit("public " + cppBaseClass->getName());
83 
84  cppImplClass->addInclude("<ArmarXCore/core/Component.h>");
85  cppImplClass->addInclude("<ArmarXCore/core/system/ImportExportComponent.h>");
86  cppImplClass->addInclude("<ArmarXCore/statechart/StatechartContext.h>");
87  cppImplClass->addInclude("\"" + className + "Base.generated.h\"");
88  cppBaseClass->addInclude("<ArmarXCore/core/system/ImportExportComponent.h>");
89 
90  std::vector<VariantInfo::ProxyEntryPtr> proxyEntries;
91 
92  for (std::string proxyId : proxies)
93  {
94  VariantInfo::ProxyEntryPtr p = variantInfo->getProxyEntry(proxyId);
95 
96  if (p)
97  {
98  proxyEntries.push_back(p);
99  }
100  }
101 
102  CppClassPtr propertiesClass = cppImplClass->addInnerClass("PropertyDefinitions");
103  propertiesClass->addInherit("public StatechartContextPropertyDefinitions");
104 
105  CppCtorPtr propertiesCtor = propertiesClass->addCtor("std::string prefix");
106  propertiesCtor->addInitListEntry("StatechartContextPropertyDefinitions", "prefix");
107 
108  CppMethodPtr getDefaultName =
109  cppImplClass->addPublicMethod("std::string getDefaultName() const override");
110  CppMethodPtr onInit = cppImplClass->addPublicMethod("void onInitStatechartContext() override");
111  CppMethodPtr onConnect =
112  cppImplClass->addPublicMethod("void onConnectStatechartContext() override");
113 
114  getDefaultName->addLine(fmt("return \"%s\";", className));
115 
116  for (VariantInfo::ProxyEntryPtr p : proxyEntries)
117  {
118  std::string description = fmt("Name of the %s that should be used",
119  simox::alg::to_lower(magicNameSplit(p->getPropertyName())));
120 
121  if (p->getPropertyIsOptional())
122  {
123  propertiesCtor->addLine(
124  fmt("defineOptionalProperty<std::string>(\"%s\", \"%s\", \"%s\");",
125  p->getPropertyName(),
126  p->getPropertyDefaultValue(),
127  description));
128  }
129  else
130  {
131  propertiesCtor->addLine(fmt("defineRequiredProperty<std::string>(\"%s\", \"%s\");",
132  p->getPropertyName(),
133  description));
134  }
135 
136 
137  if (p->getProxyType() == VariantInfo::SingleProxy)
138  {
139  onInit->addLine(fmt("usingProxy(getProperty<std::string>(\"%s\").getValue());",
140  p->getPropertyName()));
141  onConnect->addLine(
142  fmt("%s = getProxy<%s>(getProperty<std::string>(\"%s\").getValue());",
143  p->getMemberName(),
144  p->getTypeName(),
145  p->getPropertyName()));
146  }
147  else if (p->getProxyType() == VariantInfo::Topic)
148  {
149  onInit->addLine(fmt("offeringTopic(getProperty<std::string>(\"%s\").getValue());",
150  p->getPropertyName()));
151  onConnect->addLine(
152  fmt("%s = getTopic<%s>(getProperty<std::string>(\"%s\").getValue());",
153  p->getMemberName(),
154  p->getTypeName(),
155  p->getPropertyName()));
156  }
157  else
158  {
159  throw LocalException("Not supported ProxyType");
160  }
161 
162  CppFieldPtr f = CppFieldPtr(new CppField(p->getTypeName(), p->getMemberName()));
163  cppImplClass->addPrivateField(f);
164  std::string proxyFuncVirtual =
165  fmt("virtual const %s& %s() const = 0;", p->getTypeName(), p->getGetterName());
166  std::string proxyFuncOverride =
167  fmt("const %s& %s() const override", p->getTypeName(), p->getGetterName());
168  CppMethodPtr virtualGetProxy = cppBaseClass->addPublicMethod(proxyFuncVirtual);
169  CppMethodPtr getProxy = cppImplClass->addPublicMethod(proxyFuncOverride);
170  getProxy->addLine(fmt("return %s;", p->getMemberName()));
171  getProxy->setCompact(true);
172  getProxy->setEnforceBlockGeneration(true);
173  cppBaseClass->addInclude(fmt("<%s>", p->getIncludePath()));
174  }
175 
176  // special custom proxy code
177  for (VariantInfo::ProxyEntryPtr p : proxyEntries)
178  {
179  for (std::string member : p->getMembers())
180  {
181  CppFieldPtr f =
182  CppFieldPtr(new CppField(member, "")); // hack full member definition to type
183  cppImplClass->addPrivateField(f);
184  }
185 
186  for (std::string include : p->getIncludes())
187  {
188  cppBaseClass->addInclude(fmt("<%s>", include));
189  }
190 
191  for (std::string oni : p->getOnInit())
192  {
193  onInit->addLine(oni);
194  }
195 
196  for (std::string onc : p->getOnConnect())
197  {
198  onConnect->addLine(onc);
199  }
200 
201  for (std::pair<std::string, std::string> method : p->getMethods())
202  {
203  cppImplClass->addPublicMethod(method.first + " override")->addLine(method.second);
204  cppBaseClass->addPublicMethod("virtual " + method.first + " = 0;");
205  }
206  }
207 
208  const std::string baseVirtualDtor = fmt("virtual ~%sBase() = default;", className);
209  cppBaseClass->addPublicMethod(baseVirtualDtor);
210 
211 
212  CppMethodPtr createPropertyDefinitions = cppImplClass->addPublicMethod(
213  "PropertyDefinitionsPtr createPropertyDefinitions() override");
214  createPropertyDefinitions->addLine(
215  fmt("return PropertyDefinitionsPtr(new %s::PropertyDefinitions(getConfigIdentifier()));",
216  className));
217 
218  if (usedVariantTypes.size() > 0)
219  {
220  // Add special method that uses all non-basic types to force compiler/linker to include/load all libraries in binary (ensure GCC does not optimise it out).
221  CppMethodPtr forceLibLoading(
222  new CppMethod("void __attribute__((used)) __forceLibLoading()"));
223  forceLibLoading->addLine("// Do not call this method.");
224  forceLibLoading->addLine("// The sole purpose of this method is to force the "
225  "compiler/linker to include all libraries.");
226 
227  int typeNr = 1;
228  std::set<std::string> includes;
229  for (std::string innerNonBasicVariantDataType : usedVariantTypes)
230  {
232  variantInfo->findLibByVariant(innerNonBasicVariantDataType);
233 
234  ARMARX_CHECK_EXPRESSION(lib) << innerNonBasicVariantDataType;
235  for (auto& include : lib->getFactoryIncludes())
236  {
237  includes.insert(include);
238  }
239  for (auto& include : lib->getVariantIncludes(innerNonBasicVariantDataType))
240  {
241  includes.insert(include);
242  }
243  std::string implementationType =
244  variantInfo->getDataTypeName(innerNonBasicVariantDataType);
245  forceLibLoading->addLine(
246  fmt("armarx::GenericFactory< %s, %s> ().create(%s::ice_staticId());",
247  implementationType,
248  implementationType,
249  implementationType));
250  typeNr++;
251  }
252  for (auto& include : includes)
253  {
254  cppImplClass->addInclude("<" + include + ">");
255  }
256 
257  cppImplClass->addPublicMethod(forceLibLoading);
258  }
259 
260  return std::make_tuple(cppImplClass, cppBaseClass);
261 }
262 
263 std::string
264 XmlContextBaseClassGenerator::magicNameSplit(std::string name)
265 {
266  if (simox::alg::ends_with(name, "Name"))
267  {
268  name = name.substr(0, name.size() - 4);
269  }
270 
271  boost::regex re("([A-Z][a-z])");
272  name = boost::regex_replace(name, re, " \\1");
273  name = simox::alg::to_lower(name);
274  simox::alg::trim(name);
275  return name;
276 }
277 
278 std::string
279 XmlContextBaseClassGenerator::fmt(const std::string& fmt, const std::string& arg1)
280 {
281  return str(boost::format(fmt) % arg1);
282 }
283 
284 std::string
285 XmlContextBaseClassGenerator::fmt(const std::string& fmt,
286  const std::string& arg1,
287  const std::string& arg2)
288 {
289  return str(boost::format(fmt) % arg1 % arg2);
290 }
291 
292 std::string
293 XmlContextBaseClassGenerator::fmt(const std::string& fmt,
294  const std::string& arg1,
295  const std::string& arg2,
296  const std::string& arg3)
297 {
298  return str(boost::format(fmt) % arg1 % arg2 % arg3);
299 }
str
std::string str(const T &t)
Definition: UserAssistedSegmenterGuiWidgetController.cpp:43
armarx::CppCtorPtr
std::shared_ptr< CppCtor > CppCtorPtr
Definition: CppCtor.h:31
VariantContainer.h
armarx::CppClassPtr
std::shared_ptr< CppClass > CppClassPtr
Definition: CppClass.h:35
armarx::XmlContextBaseClassGenerator::GenerateCpp
static std::tuple< std::string, std::string > GenerateCpp(std::vector< std::string > namespaces, std::vector< std::string > proxies, std::string groupName, VariantInfoPtr variantInfo, const std::set< std::string > &usedVariantTypes)
Definition: XmlContextBaseClassGenerator.cpp:48
armarx::CppFieldPtr
std::shared_ptr< CppField > CppFieldPtr
Definition: CppField.h:33
armarx::VariantInfo::SingleProxy
@ SingleProxy
Definition: VariantInfo.h:71
armarx::VariantInfo::ProxyEntryPtr
std::shared_ptr< ProxyEntry > ProxyEntryPtr
Definition: VariantInfo.h:76
armarx::VariantInfo::Topic
@ Topic
Definition: VariantInfo.h:72
armarx::CppClass
Definition: CppClass.h:37
armarx::CppMethodPtr
std::shared_ptr< CppMethod > CppMethodPtr
Definition: CppMethod.h:31
ExpressionException.h
CMakePackageFinder.h
armarx::CppWriter
Definition: CppWriter.h:37
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
XmlContextBaseClassGenerator.h
armarx::ends_with
bool ends_with(const std::string &haystack, const std::string &needle)
Definition: StringHelpers.cpp:53
armarx::VariantInfoPtr
std::shared_ptr< VariantInfo > VariantInfoPtr
Definition: VariantInfo.h:39
armarx::CppField
Definition: CppField.h:35
armarx::CppWriterPtr
std::shared_ptr< CppWriter > CppWriterPtr
Definition: CppWriter.h:35
armarx::CppMethod
Definition: CppMethod.h:33
Logging.h
ArmarXDataPath.h
armarx::VariantInfo::LibEntryPtr
std::shared_ptr< LibEntry > LibEntryPtr
Definition: VariantInfo.h:211
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::XmlContextBaseClassGenerator::XmlContextBaseClassGenerator
XmlContextBaseClassGenerator()
Definition: XmlContextBaseClassGenerator.cpp:43