Line data Source code
1 : /*
2 : * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt
3 : * Authors: Andreas Vogel, Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG_BRIDGE__REGISTRY_IMPL__
34 : #define __H__UG_BRIDGE__REGISTRY_IMPL__
35 :
36 : #include "registry_util.h"
37 : #include "common/util/typename.h"
38 :
39 : namespace ug{
40 : namespace bridge
41 : {
42 :
43 : //////////////////////
44 : // global functions
45 : //////////////////////
46 : // template<typename TClass>
47 : // struct AddTypeName
48 : // {
49 : // static void add(std::string &s)
50 : // {
51 : // #ifdef UG_POSIX
52 : // if(s.length() != 0)
53 : // s += std::string(", ");
54 : // s += std::string("C++ Name: ") + TypeName<TClass>();
55 : // #endif
56 : // }
57 : // };
58 :
59 : template<class TFunc>
60 1819 : Registry& Registry::
61 : add_function(std::string funcName, TFunc func, std::string group,
62 : std::string retValInfos, std::string paramInfos,
63 : std::string tooltip, std::string help)
64 : {
65 3638 : add_and_get_function(funcName, func, group, retValInfos, paramInfos,
66 : tooltip, help);
67 1819 : return *this;
68 : }
69 :
70 : template<class TFunc>
71 1819 : ExportedFunction* Registry::
72 : add_and_get_function(std::string funcName, TFunc func, std::string group,
73 : std::string retValInfos, std::string paramInfos,
74 : std::string tooltip, std::string help)
75 : {
76 : // At this point the method name contains parameters (name|param1=...).
77 : //todo: they should be removed and specified with an extra parameter.
78 :
79 : std::string strippedMethodName = funcName;
80 : std::string methodOptions;
81 : std::string::size_type pos = strippedMethodName.find("|");
82 1819 : if(pos != std::string::npos){
83 0 : methodOptions = strippedMethodName.substr(pos + 1, strippedMethodName.length() - pos);
84 0 : strippedMethodName = strippedMethodName.substr(0, pos);
85 : }
86 :
87 : // trim whitespaces
88 1819 : strippedMethodName = TrimString(strippedMethodName);
89 3638 : methodOptions = TrimString(methodOptions);
90 :
91 : // check that name is not empty
92 1819 : if(strippedMethodName.empty())
93 : {
94 0 : UG_THROW_REGISTRY_ERROR(strippedMethodName,
95 : "Trying to register empty function name.");
96 : }
97 :
98 : // check that name does not contain illegal characters
99 1819 : if (!IsValidRegistryIdentifier(strippedMethodName)) {
100 0 : UG_THROW_REGISTRY_ERROR(strippedMethodName,
101 : "Trying to register function '" << strippedMethodName << "' that"
102 : << " contains illegal characters. " << GetRegistryIdentifierMessage());
103 : }
104 :
105 : // if the function is already in use, we have to add an overload
106 1819 : ExportedFunctionGroup* funcGrp = get_exported_function_group(strippedMethodName);
107 1819 : if(!funcGrp)
108 : {
109 : // we have to create a new function group
110 321 : funcGrp = new ExportedFunctionGroup(strippedMethodName);
111 321 : m_vFunction.push_back(funcGrp);
112 : }
113 :
114 : // add an overload to the function group
115 1819 : ExportedFunction* ef = funcGrp->add_overload(func, &FunctionProxy<TFunc>::apply,
116 : methodOptions, group,
117 : retValInfos, paramInfos,
118 : tooltip, help);
119 :
120 1819 : if(!ef){
121 0 : UG_THROW_REGISTRY_ERROR(strippedMethodName,
122 : "Trying to register function name '"<<funcName
123 : << "', that is already used by another function in this registry.");
124 : }
125 :
126 1819 : return ef;
127 : }
128 :
129 :
130 : ///////////////////
131 : // classes
132 : ///////////////////
133 :
134 : template <typename TClass, typename TBaseClass>
135 1084 : void Registry::
136 : check_base_class(const std::string& className)
137 : {
138 : // check that className is not already used
139 1084 : if(classname_registered(className))
140 : {
141 0 : UG_THROW_REGISTRY_ERROR(className,
142 : "Trying to register class name '"<<className
143 : << "', that is already used by another class in this registry.");
144 : }
145 : // check that name is not empty
146 1084 : if(className.empty())
147 : {
148 0 : UG_THROW_REGISTRY_ERROR(className,
149 : "Trying to register empty class name.");
150 : }
151 :
152 : // check that base class is not same type as class
153 1084 : if(typeid(TClass) == typeid(TBaseClass))
154 : {
155 0 : UG_THROW_REGISTRY_ERROR(className,
156 : "Trying to register class '"<< className
157 : << "' that derives from itself.");
158 : }
159 :
160 : // check that class derives from base class
161 : if(boost::is_base_of<TBaseClass, TClass>::value == false)
162 : {
163 : UG_THROW_REGISTRY_ERROR(className,
164 : "Trying to register class "<<className
165 : << "with base class that is no base class.");
166 : }
167 1084 : }
168 :
169 : template <typename TClass>
170 316 : ExportedClass<TClass>& Registry::
171 : add_class_(std::string className, std::string group, std::string tooltip)
172 : {
173 : // check that className is not already used
174 316 : if(classname_registered(className))
175 : {
176 0 : UG_THROW_REGISTRY_ERROR(className,
177 : "Trying to register class name '"<<className
178 : << "', that is already used by another class in this registry.");
179 : }
180 : // check that className is not already used as a group name
181 316 : if(groupname_registered(className))
182 : {
183 0 : UG_THROW_REGISTRY_ERROR(className,
184 : "Trying to register class name '"<<className
185 : << "', that is already used by another group in this registry.");
186 : }
187 : // check that name is not empty
188 316 : if(className.empty())
189 : {
190 0 : UG_THROW_REGISTRY_ERROR(className,
191 : "Trying to register empty class name.");
192 : }
193 :
194 : // check that name does not contain illegal characters
195 316 : if (!IsValidRegistryIdentifier(className)) {
196 0 : UG_THROW_REGISTRY_ERROR(className,
197 : "Trying to register class '" << className << "' that"
198 : << " contains illegal characters. "<< GetRegistryIdentifierMessage());
199 : }
200 :
201 : // new class pointer
202 : ExportedClass<TClass>* newClass = NULL;
203 :
204 : // AddTypeName<TClass>::add(tooltip);
205 316 : newClass = new ExportedClass<TClass>(className, group, tooltip);
206 :
207 : // add new class to list of classes
208 316 : m_vClass.push_back(newClass);
209 :
210 316 : return *newClass;
211 : }
212 :
213 : template <typename TClass, typename TBaseClass>
214 982 : ExportedClass<TClass>& Registry::
215 : add_class_(std::string className, std::string group, std::string tooltip)
216 : {
217 : // check that className is not already used
218 982 : if(classname_registered(className))
219 : {
220 0 : UG_THROW_REGISTRY_ERROR(className,
221 : "Trying to register class name '"<<className
222 : << "', that is already used by another class in this registry.");
223 : }
224 : // check that className is not already used as a group name
225 982 : if(groupname_registered(className))
226 : {
227 0 : UG_THROW_REGISTRY_ERROR(className,
228 : "Trying to register class name '"<<className
229 : << "', that is already used by another group in this registry.");
230 : }
231 : // check that name is not empty
232 982 : if(className.empty())
233 : {
234 0 : UG_THROW_REGISTRY_ERROR(className,
235 : "Trying to register empty class name.");
236 : }
237 :
238 : // check that name does not contain illegal characters
239 982 : if (!IsValidRegistryIdentifier(className)) {
240 0 : UG_THROW_REGISTRY_ERROR(className,
241 : "Trying to register class '" << className << "' that"
242 : << " contains illegal characters. "<< GetRegistryIdentifierMessage());
243 : }
244 :
245 : // check
246 982 : check_base_class<TClass, TBaseClass>(className);
247 :
248 : // new class pointer
249 : ExportedClass<TClass>* newClass = NULL;
250 :
251 : // AddTypeName<TClass>::add(tooltip);
252 :
253 : // try creation of new class
254 982 : newClass = new ExportedClass<TClass>(className, group, tooltip);
255 :
256 : // set base class names
257 : ClassNameProvider<TClass>::template set_name<TBaseClass>(className, group);
258 :
259 : // add cast function
260 : ClassCastProvider::add_cast_func<TBaseClass, TClass>();
261 :
262 : // add new class to list of classes
263 982 : m_vClass.push_back(newClass);
264 982 : return *newClass;
265 : }
266 :
267 : template <typename TClass, typename TBaseClass1, typename TBaseClass2>
268 51 : ExportedClass<TClass>& Registry::
269 : add_class_(std::string className, std::string group, std::string tooltip)
270 : {
271 : // check that className is not already used
272 51 : if(classname_registered(className))
273 : {
274 0 : UG_THROW_REGISTRY_ERROR(className,
275 : "Trying to register class name '"<<className
276 : << "', that is already used by another class in this registry.");
277 : }
278 : // check that className is not already used as a group name
279 51 : if(groupname_registered(className))
280 : {
281 0 : UG_THROW_REGISTRY_ERROR(className,
282 : "Trying to register class name '"<<className
283 : << "', that is already used by another group in this registry.");
284 : }
285 : // check that name is not empty
286 51 : if(className.empty())
287 : {
288 0 : UG_THROW_REGISTRY_ERROR(className,
289 : "Trying to register empty class name.");
290 : }
291 :
292 : // check that name does not contain illegal characters
293 51 : if (!IsValidRegistryIdentifier(className)) {
294 0 : UG_THROW_REGISTRY_ERROR(className,
295 : "Trying to register class '" << className << "' that"
296 : << " contains illegal characters. " << GetRegistryIdentifierMessage());
297 : }
298 :
299 : // check
300 51 : check_base_class<TClass, TBaseClass1>(className);
301 51 : check_base_class<TClass, TBaseClass2>(className);
302 :
303 : // new class pointer
304 : ExportedClass<TClass>* newClass = NULL;
305 :
306 : // AddTypeName<TClass>::add(tooltip);
307 :
308 : // try creation of new class
309 51 : newClass = new ExportedClass<TClass>(className, group, tooltip);
310 :
311 : // set base class names
312 51 : ClassNameProvider<TClass>::template set_name<TBaseClass1, TBaseClass2>(className, group);
313 :
314 : // add cast function
315 : ClassCastProvider::add_cast_func<TBaseClass1, TClass>();
316 : ClassCastProvider::add_cast_func<TBaseClass2, TClass>();
317 :
318 : // add new class to list of classes
319 51 : m_vClass.push_back(newClass);
320 51 : return *newClass;
321 : }
322 :
323 : template <typename TClass>
324 9 : ExportedClass<TClass>& Registry::
325 : get_class_()
326 : {
327 : // get class names
328 : const std::string& name = ClassNameProvider<TClass>::name();
329 :
330 : // look for class in this registry
331 10953 : for(size_t i = 0; i < m_vClass.size(); ++i)
332 10953 : if(name == m_vClass[i]->name())
333 9 : return *dynamic_cast<ExportedClass<TClass>* >(m_vClass[i]);
334 :
335 : // not found
336 0 : UG_THROW_REGISTRY_ERROR(name,
337 : "Trying to get class with name '" << name
338 : << "', that has not yet been registered to this Registry.");
339 : }
340 :
341 : }// end of namespace
342 : }// end of namespace
343 :
344 : #endif
|