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"
40using namespace armarx;
41#include <tuple>
42
46
47std::tuple<std::string, std::string>
48XmlContextBaseClassGenerator::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
64std::tuple<CppClassPtr, CppClassPtr>
65XmlContextBaseClassGenerator::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
263std::string
264XmlContextBaseClassGenerator::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
278std::string
279XmlContextBaseClassGenerator::fmt(const std::string& fmt, const std::string& arg1)
280{
281 return str(boost::format(fmt) % arg1);
282}
283
284std::string
285XmlContextBaseClassGenerator::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
292std::string
293XmlContextBaseClassGenerator::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}
std::string str(const T &t)
std::shared_ptr< LibEntry > LibEntryPtr
std::shared_ptr< ProxyEntry > ProxyEntryPtr
Definition VariantInfo.h:76
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)
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::shared_ptr< CppClass > CppClassPtr
Definition CppClass.h:35
std::shared_ptr< CppWriter > CppWriterPtr
Definition CppWriter.h:35
std::shared_ptr< VariantInfo > VariantInfoPtr
Definition VariantInfo.h:39
std::shared_ptr< CppCtor > CppCtorPtr
Definition CppCtor.h:31
std::shared_ptr< CppMethod > CppMethodPtr
Definition CppMethod.h:31
std::shared_ptr< CppField > CppFieldPtr
Definition CppField.h:33