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