DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
method.cpp
Go to the documentation of this file.
1#define _OksBuildDll_
2
3#include "oks/method.hpp"
4#include "oks/xml.hpp"
5#include "oks/class.hpp"
6#include "oks/cstring.hpp"
7
8#include <stdexcept>
9#include <sstream>
10
11namespace dunedaq {
12namespace oks {
13
14const char OksMethodImplementation::method_impl_xml_tag[] = "method-implementation";
15const char OksMethodImplementation::language_xml_attr[] = "language";
16const char OksMethodImplementation::prototype_xml_attr[] = "prototype";
17const char OksMethodImplementation::body_xml_attr[] = "body";
18
19const char OksMethod::method_xml_tag[] = "method";
20const char OksMethod::name_xml_attr[] = "name";
21const char OksMethod::description_xml_attr[] = "description";
22
23
24OksMethodImplementation::OksMethodImplementation(const std::string& language, const std::string& prototype, const std::string& body, OksMethod * p) :
25 p_language (language),
26 p_prototype (prototype),
27 p_body (body),
28 p_method (p)
29{
30 oks::validate_not_empty(p_language, "method implementation language");
31 oks::validate_not_empty(p_prototype, "method implementation prototype");
32}
33
34bool
36{
37 return (
38 ( this == &i ) ||
40 );
41}
42
43std::ostream&
44operator<<(std::ostream& s, const OksMethodImplementation& i)
45{
46 s << " Method implementation:\n"
47 " language: \"" << i.get_language() << "\"\n"
48 " prototype: \"" << i.get_prototype() << "\"\n"
49 " body: \"" << i.get_body() << "\"\n";
50
51 return s;
52}
53
54
55void
57{
58 s.put(" ");
59
60 s.put_start_tag(method_impl_xml_tag, sizeof(method_impl_xml_tag)-1);
61
62 s.put_attribute( language_xml_attr, sizeof(language_xml_attr)-1, get_language().c_str() );
63 s.put_attribute( prototype_xml_attr, sizeof(prototype_xml_attr)-1, get_prototype().c_str() );
64 s.put_attribute( body_xml_attr, sizeof(body_xml_attr)-1, get_body().c_str() );
65
66 s.put_end_tag();
67}
68
69
71 p_method (parent)
72{
73 try {
74 while(true) {
75 OksXmlAttribute attr(s);
76
77 // check for close of tag
78
79 if(oks::cmp_str1(attr.name(), "/")) { break; }
80
81 // check for known oks-method-implementation' attributes
82
83 else if( oks::cmp_str8(attr.name(), language_xml_attr) ) p_language.assign(attr.value(), attr.value_len());
84 else if( oks::cmp_str9(attr.name(), prototype_xml_attr) ) p_prototype.assign(attr.value(), attr.value_len());
85 else if( oks::cmp_str4(attr.name(), body_xml_attr) ) p_body.assign(attr.value(), attr.value_len());
86 else {
87 s.throw_unexpected_attribute(attr.name());
88 }
89 }
90 }
91 catch(oks::exception & e) {
92 throw oks::FailedRead("xml method implementation", e);
93 }
94 catch (std::exception & e) {
95 throw oks::FailedRead("xml method implementation", e.what());
96 }
97
98 try {
99 oks::validate_not_empty(p_language, "method implementation language");
100 oks::validate_not_empty(p_prototype, "method implementation prototype");
101 }
102 catch(std::exception& ex) {
103 throw oks::FailedRead("oks method implementation", oks::BadFileData(ex.what(), s.get_line_no(), s.get_line_pos()));
104 }
105}
106
107
108OksMethod::OksMethod(const std::string& nm, OksClass * p) :
109 p_class (p),
110 p_name (nm),
111 p_implementations (nullptr)
112{
113 try {
114 oks::validate_not_empty(p_name, "method name");
115 }
116 catch(std::exception& ex) {
117 Oks::error_msg("OksMethod::OksMethod()") << ex.what() << std::endl;
118 }
119}
120
121OksMethod::OksMethod(const std::string& nm, const std::string& desc, OksClass * p) :
122 p_class (p),
123 p_name (nm),
124 p_description (desc),
125 p_implementations (nullptr)
126{
127 oks::validate_not_empty(p_name, "method name");
128}
129
131{
133 while(!p_implementations->empty()) {
135 p_implementations->pop_front();
136 delete i;
137 }
138
139 delete p_implementations;
140 }
141}
142
143
144bool
145OksMethod::operator==(const class OksMethod &m) const
146{
147 // check if compare with self
148
149 if(this == &m) return true;
150
151
152 // check if attributes are different
153
154 if(p_name != m.p_name || p_description != m.p_description) return false;
155
156
157 // check if methods have no implementations
158
159 if(p_implementations == 0 && m.p_implementations == 0) return true;
160
161
162 // check if only one method has implementation
163
164 if(p_implementations == 0 || m.p_implementations == 0) return false;
165
166
167 // check if numbers of implementations are different
168
169 if(p_implementations->size() != m.p_implementations->size()) return false;
170
171
172 // check implementations
173
174 std::list<OksMethodImplementation *>::const_iterator i1 = p_implementations->begin();
175 std::list<OksMethodImplementation *>::const_iterator i2 = m.p_implementations->begin();
176
177 for(;i1 != p_implementations->end(); ++i1, ++i2) {
178 if( !(*(*i1) == *(*i2)) ) return false;
179 }
180
181 return true;
182}
183
184std::ostream&
185operator<<(std::ostream& s, const OksMethod& m)
186{
187 s << "Method name: \"" << m.p_name << "\"\n"
188 " description: \"" << m.p_description << "\"\n";
189
190 if(m.p_implementations) {
191 s << " implementations:\n";
192
193 for(std::list<OksMethodImplementation *>::const_iterator i = m.p_implementations->begin(); i != m.p_implementations->end(); ++i)
194 s << *(*i);
195 }
196 else
197 s << " there are no implementation(s)\n";
198
199 return s;
200}
201
202
203void
205{
206 s.put_raw(' ');
207 s.put_raw(' ');
208
209 s.put_start_tag(method_xml_tag, sizeof(method_xml_tag)-1);
210
211 s.put_attribute(name_xml_attr, sizeof(name_xml_attr)-1, p_name.c_str());
212 s.put_attribute(description_xml_attr, sizeof(description_xml_attr)-1, p_description.c_str());
213
214 s.put_raw('>');
215 s.put_raw('\n');
216
218 for(std::list<OksMethodImplementation *>::iterator i = p_implementations->begin(); i != p_implementations->end(); ++i)
219 (*i)->save(s);
220 }
221
222 s.put_raw(' ');
223 s.put_raw(' ');
224
225 s.put_last_tag(method_xml_tag, sizeof(method_xml_tag)-1);
226}
227
228
230 p_class (parent),
231 p_implementations (0)
232{
233 try {
234 while(true) {
235 OksXmlAttribute attr(s);
236
237 // check for close of tag
238
239 if(oks::cmp_str1(attr.name(), ">")) { break; }
240
241 // check for known oks-relationship' attributes
242
243 else if(oks::cmp_str4(attr.name(), name_xml_attr)) p_name.assign(attr.value(), attr.value_len());
244 else if(oks::cmp_str11(attr.name(), description_xml_attr)) p_description.assign(attr.value(), attr.value_len());
245 else {
246 s.throw_unexpected_attribute(attr.name());
247 }
248 }
249 }
250 catch(oks::exception & e) {
251 throw oks::FailedRead("xml method", e);
252 }
253 catch (std::exception & e) {
254 throw oks::FailedRead("xml method", e.what());
255 }
256
257 // check validity of read values
258
259 try {
260 oks::validate_not_empty(p_name, "method name");
261 }
262 catch(std::exception& ex) {
263 throw oks::FailedRead("oks method", oks::BadFileData(ex.what(), s.get_line_no(), s.get_line_pos()));
264 }
265
266
267 // read 'body' and 'method-actions'
268
269 {
270 while(true) try {
271 const char * tag_start = s.get_tag_start();
272
273 if(oks::cmp_str7(tag_start, "/method")) { break; }
274
275 else if(!strcmp(tag_start, "method-implementation")) {
276 if(!p_implementations) p_implementations = new std::list<OksMethodImplementation *>();
277 p_implementations->push_back(new OksMethodImplementation(s, this));
278 }
279
280 else {
281 std::ostringstream text;
282 text << "Unexpected tag \'" << tag_start << "\' inside method \'" << p_name << "\'\n";
283 throw std::runtime_error( text.str().c_str() );
284 }
285
286 }
287 catch (oks::exception & e) {
288 throw oks::FailedRead("method tag", e);
289 }
290 catch (std::exception & e) {
291 throw oks::FailedRead("method tag", e.what());
292 }
293 }
294}
295
296
297void
298OksMethod::set_name(const std::string& new_name)
299{
300 // ignore when name is the same
301
302 if(p_name == new_name) return;
303
304
305 // additional checks are required,
306 // if the method already belongs to some class
307
308 if(p_class) {
309
310 // check allowed length for attribute name
311
312 try {
313 oks::validate_not_empty(new_name, "name");
314 }
315 catch(std::exception& ex) {
316 throw oks::SetOperationFailed("OksMethod::set_name", ex.what());
317 }
318
319
320 // having a direct method with the same name is an error
321
322 if(p_class->find_direct_method(new_name) != 0) {
323 std::ostringstream text;
324 text << "Class \"" << p_class->get_name() << "\" already has direct method \"" << new_name << '\"';
325 throw oks::SetOperationFailed("OksMethod::set_name", text.str());
326 }
327
328
329 // check that it is possible to lock the file
330
331 p_class->lock_file("OksMethod::set_name");
332
333
334 // probably a non-direct method already exists
335
336 OksMethod * m = p_class->find_method(new_name);
337
338
339 // change the name
340
341 p_name = new_name;
342
343
344 // registrate the change
345
347 }
348 else {
349 p_name = new_name;
350 }
351}
352
354OksMethod::find_implementation(const std::string& language) const
355{
357 for(std::list<OksMethodImplementation *>::iterator i = p_implementations->begin(); i != p_implementations->end(); ++i)
358 if(language == (*i)->get_language()) return *i;
359 }
360
361 return 0;
362}
363
364void
365OksMethod::add_implementation(const std::string& language, const std::string& prototype, const std::string& body)
366{
367 if(find_implementation(language)) {
368 std::ostringstream text;
369 text << "Cannot add implementation on language \"" << language << "\" since it already exists.";
370 throw oks::SetOperationFailed("OksMethod::add_implementation", text.str());
371 }
372
373 if(p_class) p_class->lock_file("OksMethod::add_implementation");
374
375 if(!p_implementations) {
376 p_implementations = new std::list<OksMethodImplementation *>();
377 }
378
379 OksMethodImplementation * i = new OksMethodImplementation(language, prototype, body);
380
381 p_implementations->push_back(i);
382 i->p_method = this;
383
385}
386
387void
388OksMethod::remove_implementation(const std::string& language)
389{
391
392 if(i == 0) {
393 std::ostringstream text;
394 text << "Cannot remove implementation on language \"" << language << "\" since it does not exist.";
395 throw oks::SetOperationFailed("OksMethod::remove_implementation", text.str());
396 }
397
398 if(p_class) p_class->lock_file("OksMethod::remove_implementation");
399
400 p_implementations->remove(i);
401
402 if(p_implementations->empty()) {
403 delete p_implementations;
405 }
406
408}
409
410
411void
412OksMethod::set_description(const std::string& desc)
413{
414 if(p_description != desc) {
415 if(p_class) p_class->lock_file("OksMethod::set_description");
416
417 p_description = desc;
418
420 }
421}
422
423void
425{
426 if(p_language != s) {
427 if(p_method) {
428 if(p_method->find_implementation(s) != 0) {
429 std::ostringstream text;
430 text << "cannot rename \"" << p_method->p_name << "\" method implementation to language \"" << s << "\" "
431 "since the method already has implementation with such language.";
432 throw oks::SetOperationFailed("OksMethodImplementation::set_language", text.str());
433 }
434
435 try {
436 oks::validate_not_empty(s, "language");
437 }
438 catch(std::exception& ex) {
439 throw oks::SetOperationFailed("OksMethodImplementation::set_language", ex.what());
440 }
441
442 if(p_method->p_class) p_method->p_class->lock_file("OksMethodImplementation::set_language");
443 }
444
445 p_language = s;
446
447 if(p_method && p_method->p_class) {
449 }
450 }
451}
452
453void
455{
456 if(p_prototype != s) {
457 try {
458 oks::validate_not_empty(s, "prototype");
459 }
460 catch(std::exception& ex) {
461 throw oks::SetOperationFailed("OksMethodImplementation::set_prototype", ex.what());
462 }
463
464 if(p_method && p_method->p_class) p_method->p_class->lock_file("OksMethodImplementation::set_prototype");
465
466 p_prototype = s;
467
468 if(p_method && p_method->p_class) {
470 }
471 }
472}
473
474void
476{
477 if(p_body != s) {
478 if(p_method && p_method->p_class) p_method->p_class->lock_file("OksMethodImplementation::set_body");
479
480 p_body = s;
481
482 if(p_method && p_method->p_class) {
484 }
485 }
486}
487
488} // namespace oks
489} // namespace dunedaq
The OKS class.
Definition class.hpp:200
OksMethod * find_method(const std::string &name) const noexcept
Find method (search in this and base classes).
Definition class.cpp:1341
void registrate_class_change(ChangeType, const void *, bool=true)
Definition class.cpp:2035
const std::string & get_name() const noexcept
Definition class.hpp:363
void lock_file(const char *)
Definition class.cpp:766
OksMethod * find_direct_method(const std::string &name) const noexcept
Find direct method.
Definition class.cpp:1330
OKS method implementation class.
Definition method.hpp:35
const std::string & get_body() const noexcept
Definition method.hpp:99
OksMethodImplementation(const std::string &language, const std::string &prototype, const std::string &body, OksMethod *p=nullptr)
OKS method implementation constructor.
Definition method.cpp:24
const std::string & get_language() const noexcept
Definition method.hpp:63
void set_prototype(const std::string &prototype)
Set method implementation prototype.
Definition method.cpp:454
const std::string & get_prototype() const noexcept
Definition method.hpp:82
void set_language(const std::string &language)
Set method implementation language.
Definition method.cpp:424
bool operator==(const class OksMethodImplementation &) const
Definition method.cpp:35
static const char prototype_xml_attr[]
Definition method.hpp:133
void save(OksXmlOutputStream &) const
Definition method.cpp:56
static const char language_xml_attr[]
Definition method.hpp:132
void set_body(const std::string &body)
Set method implementation body.
Definition method.cpp:475
static const char body_xml_attr[]
Definition method.hpp:134
static const char method_impl_xml_tag[]
Definition method.hpp:131
OKS method class.
Definition method.hpp:153
void set_name(const std::string &name)
Set method name.
Definition method.cpp:298
static const char name_xml_attr[]
Definition method.hpp:292
static const char description_xml_attr[]
Definition method.hpp:293
static const char method_xml_tag[]
Definition method.hpp:291
void set_description(const std::string &description)
Set method description.
Definition method.cpp:412
void add_implementation(const std::string &language, const std::string &prototype, const std::string &body)
Add method implementation.
Definition method.cpp:365
void remove_implementation(const std::string &language)
Remove method implementation.
Definition method.cpp:388
bool operator==(const class OksMethod &) const
Definition method.cpp:145
friend class OksMethodImplementation
Definition method.hpp:156
OksMethodImplementation * find_implementation(const std::string &language) const
Find method implementation.
Definition method.cpp:354
std::list< OksMethodImplementation * > * p_implementations
Definition method.hpp:280
void save(OksXmlOutputStream &) const
Definition method.cpp:204
std::string p_description
Definition method.hpp:279
OksMethod(const std::string &name, OksClass *p=nullptr)
OKS method constructor.
Definition method.cpp:108
static std::ostream & error_msg(const char *)
Definition kernel.cpp:556
virtual const char * what() const noexcept
bool cmp_str8(const char *s1, const char s2[9])
Definition cstring.hpp:61
bool cmp_str1(const char *s1, const char s2[2])
Definition cstring.hpp:9
bool cmp_str4(const char *s1, const char s2[5])
Definition cstring.hpp:29
bool cmp_str9(const char *s1, const char s2[10])
Definition cstring.hpp:69
void validate_not_empty(const std::string &value, const char *name)
std::ostream & operator<<(std::ostream &s, const oks::exception &ex)
bool cmp_str11(const char *s1, const char s2[12])
Definition cstring.hpp:77
bool cmp_str7(const char *s1, const char s2[8])
Definition cstring.hpp:53
Including Qt Headers.
Definition __init__.py:1
size_t value_len() const
Definition xml.hpp:304