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 : #include <string>
34 :
35 : #include "registry.h"
36 : #include "registry_util.h"
37 : #ifdef UG_FOR_LUA
38 : #include "bindings/lua/lua_function_handle.h"
39 : #endif
40 :
41 : using namespace ug::bridge;
42 :
43 : namespace ug{
44 : namespace bridge
45 : {
46 :
47 1 : Registry::Registry()
48 1 : :m_bForceConstructionWithSmartPtr(false)
49 : {
50 : // register native types as provided in ParameterStack
51 : // we use the c_ prefix to avoid clashes with java native types in java bindings.
52 2 : add_class_<bool>("c_bool");
53 2 : add_class_<int>("c_int");
54 2 : add_class_<size_t>("c_size_t");
55 2 : add_class_<float>("c_float");
56 2 : add_class_<double>("c_double");
57 2 : add_class_<char>("c_char");
58 2 : add_class_<const char*>("c_const_char_ptr");
59 2 : add_class_<std::string>("c_string");
60 2 : add_class_<void>("c_void");
61 : #ifdef UG_FOR_LUA
62 2 : add_class_<LuaFunctionHandle>("c_LuaFunctionHandle");
63 : #endif
64 1 : }
65 :
66 0 : Registry::Registry(const Registry& reg)
67 0 : : m_bForceConstructionWithSmartPtr(false)
68 : {
69 0 : }
70 :
71 1 : Registry::~Registry()
72 : {
73 : // delete registered functions
74 322 : for(size_t i = 0; i < m_vFunction.size(); ++i)
75 : {
76 321 : if(m_vFunction[i] != NULL)
77 321 : delete m_vFunction[i];
78 : }
79 : // delete registered classes
80 1350 : for(size_t i = 0; i < m_vClass.size(); ++i)
81 : {
82 1349 : if(m_vClass[i] != NULL)
83 1349 : delete m_vClass[i];
84 : }
85 : // delete registered class groups
86 274 : for(size_t i = 0; i < m_vClassGroups.size(); ++i){
87 273 : delete m_vClassGroups[i];
88 : }
89 1 : }
90 :
91 :
92 : ////////////////////////
93 : // callbacks
94 : ////////////////////////
95 :
96 0 : void Registry::add_callback(FuncRegistryChanged callback)
97 : {
98 0 : m_callbacksRegChanged.push_back(callback);
99 0 : }
100 :
101 2 : bool Registry::registry_changed()
102 : {
103 2 : if(!m_callbacksRegChanged.empty())
104 0 : UG_THROW("Sorry, currently no listeners can be registered at the "
105 : " the Registry due to restrictions of the VRL binding.");
106 :
107 : // iterate through all callbacks and call them
108 2 : for(size_t i = 0; i < m_callbacksRegChanged.size(); ++i){
109 0 : m_callbacksRegChanged[i](this);
110 : }
111 :
112 : // ok
113 2 : return true;
114 : }
115 :
116 : //////////////////////
117 : // global functions
118 : //////////////////////
119 :
120 0 : size_t Registry::num_functions() const
121 : {
122 0 : return m_vFunction.size();
123 : }
124 :
125 0 : ExportedFunction& Registry::get_function(size_t ind)
126 : {
127 0 : return *m_vFunction.at(ind)->get_overload(0);
128 : }
129 :
130 0 : const ExportedFunction& Registry::get_function(size_t ind) const
131 : {
132 0 : return *m_vFunction.at(ind)->get_overload(0);
133 : }
134 :
135 0 : size_t Registry::num_overloads(size_t ind) const
136 : {
137 0 : return m_vFunction.at(ind)->num_overloads();
138 : }
139 :
140 0 : ExportedFunction& Registry::get_overload(size_t funcInd, size_t oInd)
141 : {
142 0 : return *m_vFunction.at(funcInd)->get_overload(oInd);
143 : }
144 :
145 0 : ExportedFunctionGroup& Registry::get_function_group(size_t ind)
146 : {
147 0 : return *m_vFunction.at(ind);
148 : }
149 :
150 :
151 : ///////////////////
152 : // classes
153 : ///////////////////
154 :
155 0 : size_t Registry::num_classes() const
156 : {
157 0 : return m_vClass.size();
158 : }
159 :
160 : /// returns an exported function
161 0 : const IExportedClass& Registry::get_class(size_t ind) const
162 : {
163 0 : return *m_vClass.at(ind);
164 : }
165 :
166 4961 : IExportedClass* Registry::get_class(const std::string& name)
167 : {
168 : //todo: use a map to access classes by name.
169 3459169 : for(size_t i = 0; i < m_vClass.size(); ++i)
170 3455472 : if(name == m_vClass[i]->name())
171 1264 : return m_vClass[i];
172 :
173 : return NULL;
174 : }
175 :
176 0 : const IExportedClass* Registry::get_class(const std::string& name) const
177 : {
178 : //todo: use a map to access classes by name.
179 0 : for(size_t i = 0; i < m_vClass.size(); ++i)
180 0 : if(name == m_vClass[i]->name())
181 0 : return m_vClass[i];
182 :
183 : return NULL;
184 : }
185 :
186 :
187 0 : void Registry::set_force_construct_via_smart_pointer(bool bForceConstructionWithSmartPtr)
188 : {
189 0 : m_bForceConstructionWithSmartPtr = bForceConstructionWithSmartPtr;
190 0 : }
191 :
192 0 : bool Registry::check_consistency()
193 : {
194 :
195 : // list to check for duplicates in global functions.
196 : // comparison is not case sensitive.
197 : std::vector<std::string> globalFunctionNames;
198 :
199 : // check global functions
200 : size_t globFctUndef = 0;
201 0 : for(size_t i=0; i<num_functions(); i++)
202 : {
203 : // get function
204 0 : ExportedFunctionGroup& funcGrp = get_function_group(i);
205 :
206 : // add lower case name entry
207 0 : globalFunctionNames.push_back(ToLower(funcGrp.name()));
208 :
209 : // check all overloads
210 0 : for(size_t j = 0; j < funcGrp.num_overloads(); ++j){
211 0 : if(!funcGrp.get_overload(j)->check_consistency())
212 0 : globFctUndef++;
213 : }
214 : }
215 :
216 : // check for duplicate function names. comparison is not case sensitive.
217 : std::vector<std::string> globFuncDuplicates =
218 0 : FindDuplicates(globalFunctionNames);
219 : bool globFuncDuplicatesExist = !globFuncDuplicates.empty();
220 : //todo: use stringstream
221 0 : std::string duplicateFuncMsg = "#### Registry ERROR: duplicate function names:\n";
222 0 : if (globFuncDuplicatesExist) {
223 0 : for(size_t i = 0; i < globFuncDuplicates.size();i++) {
224 0 : duplicateFuncMsg+= + "\t" + globFuncDuplicates[i] + "\n";
225 : }
226 : duplicateFuncMsg += "#### NOTE: it is not allowed to register multiple"
227 : " functions with equal names. Comparison is NOT case sensitive,"
228 : " e.g., 'Func' and 'func' are equal.\n\n";
229 : }
230 :
231 0 : set_force_construct_via_smart_pointer(false);
232 :
233 : // check classes and their methods
234 : size_t baseClassUndef = 0;
235 : size_t methodUndef = 0;
236 : size_t constructorUndef = 0;
237 : size_t notConstructedAsSmartPtr = 0;
238 : // list to check for duplicate classes.
239 : // comparison is not case sensitive.
240 : std::vector<std::string> classNames;
241 0 : for(size_t i=0; i<num_classes(); i++)
242 : {
243 : // get class
244 0 : const bridge::IExportedClass &c = get_class(i);
245 :
246 : // check if class is constructed via smart pointer
247 0 : if(m_bForceConstructionWithSmartPtr)
248 : {
249 0 : if(c.is_instantiable() && !c.construct_as_smart_pointer())
250 : {
251 0 : UG_ERR_LOG("#### Registry ERROR: Class " << c.name()<<" is "
252 : "instantiable, but not constructed as Smart Pointer.\n");
253 0 : notConstructedAsSmartPtr++;
254 : }
255 : }
256 :
257 : // add lower case name entry
258 0 : classNames.push_back(ToLower(c.name()));
259 :
260 : // check class (e.g. that base classes have been named)
261 0 : if(!c.check_consistency()){
262 0 : UG_ERR_LOG("#### Registry ERROR: Base Class Error for class " << c.name()<<"\n");
263 0 : baseClassUndef++;
264 : }
265 :
266 : // check methods
267 0 : for(size_t j=0; j<c.num_methods(); j++)
268 0 : if(!c.get_method(j).check_consistency(c.name()))
269 0 : methodUndef++;
270 :
271 0 : for(size_t j=0; j<c.num_const_methods(); j++)
272 0 : if(!c.get_const_method(j).check_consistency(c.name()))
273 0 : methodUndef++;
274 :
275 : // check constructors
276 0 : for(size_t j=0; j<c.num_constructors(); j++)
277 0 : if(!c.get_constructor(j).check_consistency(c.name()))
278 0 : constructorUndef++;
279 : }
280 :
281 : // check for duplicate class names. comparison is not case sensitive.
282 : std::vector<std::string> classDuplicates =
283 0 : FindDuplicates(classNames);
284 : bool classDuplicatesExist = classDuplicates.size()>0;
285 : //todo: use stringstream
286 : std::string duplicateClassMsg =
287 0 : "#### Registry ERROR: duplicate class names:\n";
288 0 : if (classDuplicatesExist) {
289 0 : for(size_t i = 0; i < classDuplicates.size();i++) {
290 0 : duplicateClassMsg+= "\t" + classDuplicates[i] + "\n";
291 : }
292 : duplicateClassMsg += "#### NOTE: it is not allowed to register multiple"
293 : " classes with equal names. Comparison is NOT case sensitive,"
294 : " e.g., 'Class' and 'class' are equal.\n\n";
295 : }
296 :
297 : // log error messages
298 0 : if(globFctUndef > 0)
299 0 : UG_ERR_LOG("#### Registry ERROR: "<<globFctUndef<<
300 : " global Functions are using undeclared Classes.\n");
301 0 : if(methodUndef > 0)
302 0 : UG_ERR_LOG("#### Registry ERROR: "<<methodUndef<<
303 : " Methods are using undeclared Classes.\n");
304 0 : if(baseClassUndef > 0)
305 0 : UG_ERR_LOG("#### Registry ERROR: "<<baseClassUndef<<
306 : " Base-Classes are using undeclared Classes.\n");
307 0 : if(constructorUndef > 0)
308 0 : UG_ERR_LOG("#### Registry ERROR: "<<constructorUndef<<
309 : " Constructors are using undeclared Classes.\n");
310 0 : if(notConstructedAsSmartPtr > 0)
311 0 : UG_ERR_LOG("#### Registry ERROR: "<<notConstructedAsSmartPtr<<
312 : " Classes are not constructed as SmartPtr.\n");
313 0 : if(globFuncDuplicatesExist) {
314 : UG_ERR_LOG(duplicateFuncMsg);
315 : }
316 0 : if(classDuplicatesExist) {
317 : UG_ERR_LOG(duplicateClassMsg);
318 : }
319 :
320 : // return false if undefined classes or functions and/or duplicates have been found
321 0 : if(globFctUndef > 0) return false;
322 0 : if(methodUndef > 0) return false;
323 0 : if(baseClassUndef > 0) return false;
324 0 : if(constructorUndef > 0) return false;
325 0 : if(notConstructedAsSmartPtr > 0) return false;
326 0 : if(globFuncDuplicatesExist) return false;
327 0 : if(classDuplicatesExist) return false;
328 :
329 : // everything fine
330 : return true;
331 0 : }
332 :
333 :
334 0 : size_t Registry::num_class_groups() const
335 : {
336 0 : return m_vClassGroups.size();
337 : }
338 :
339 0 : const ClassGroupDesc* Registry::get_class_group(size_t i) const
340 : {
341 0 : return m_vClassGroups[i];
342 : }
343 :
344 0 : ClassGroupDesc* Registry::get_class_group(size_t i)
345 : {
346 0 : return m_vClassGroups[i];
347 : }
348 :
349 1264 : ClassGroupDesc* Registry::get_class_group(const std::string& name)
350 : {
351 : //todo: use a map to quickly access classGroups by name
352 183401 : for(size_t i = 0; i < m_vClassGroups.size(); ++i)
353 183128 : if(name == m_vClassGroups[i]->name())
354 : return m_vClassGroups[i];
355 :
356 : // since we reached this point, no class-group with the given name exists.
357 :
358 : // check that name does not contain illegal characters
359 273 : if (!IsValidRegistryIdentifier(name)) {
360 0 : UG_THROW_REGISTRY_ERROR(name,
361 : "Trying add group '" << name << "' that"
362 : << " contains illegal characters. "<< GetRegistryIdentifierMessage());
363 : }
364 :
365 273 : ClassGroupDesc* classGroup = new ClassGroupDesc();
366 : classGroup->set_name(name);
367 273 : m_vClassGroups.push_back(classGroup);
368 :
369 : return classGroup;
370 : }
371 :
372 0 : const ClassGroupDesc* Registry::get_class_group(const std::string& name) const
373 : {
374 : //todo: use a map to quickly access classGroups by name
375 0 : for(size_t i = 0; i < m_vClassGroups.size(); ++i)
376 0 : if(name == m_vClassGroups[i]->name())
377 : return m_vClassGroups[i];
378 :
379 : // since we reached this point, no class-group with the given name exists.
380 : return NULL;
381 : }
382 :
383 1264 : void Registry::add_class_to_group(std::string className, std::string groupName,
384 : std::string classTag)
385 : {
386 : // make sure that no class with groupName exists.
387 1264 : if(classname_registered(groupName)){
388 0 : UG_THROW_REGISTRY_ERROR(groupName,
389 : "A class with the given group name '"<<groupName<<"' already exists.");
390 : }
391 :
392 1264 : ClassGroupDesc* groupDesc = get_class_group(groupName);
393 : //todo: make sure that groupDesc does not already contain className.
394 1264 : IExportedClass* expClass = get_class(className);
395 1264 : if(!expClass){
396 0 : UG_THROW_REGISTRY_ERROR(groupName,
397 : "The given class has to be registered before "
398 : "adding it to a group: " << className);
399 : }
400 :
401 : if(expClass)
402 1264 : groupDesc->add_class(expClass, classTag);
403 1264 : }
404 :
405 :
406 3697 : bool Registry::classname_registered(const std::string& name)
407 : {
408 3697 : return get_class(name) != NULL;
409 : }
410 :
411 1349 : bool Registry::groupname_registered(const std::string& name)
412 : {
413 : //todo: use a map to quickly access classGroups by name
414 194526 : for(size_t i = 0; i < m_vClassGroups.size(); ++i){
415 193177 : if(name == m_vClassGroups[i]->name())
416 : return true;
417 : }
418 : return false;
419 : }
420 :
421 : // returns true if functionname is already used by a function in this registry
422 1 : bool Registry::functionname_registered(const std::string& name)
423 : {
424 290 : for(size_t i = 0; i < m_vFunction.size(); ++i)
425 289 : if(name == m_vFunction[i]->name())
426 : return true;
427 :
428 : return false;
429 : }
430 :
431 1819 : ExportedFunctionGroup* Registry::get_exported_function_group(const std::string& name)
432 : {
433 405953 : for(size_t i = 0; i < m_vFunction.size(); ++i)
434 405632 : if(name == m_vFunction[i]->name())
435 : return m_vFunction[i];
436 :
437 : return NULL;
438 : }
439 :
440 : }// end of namespace
441 : }// end of namespace
|