Loading...
Searching...
No Matches
Command.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31
32#ifndef DRAINLET_H_
33#define DRAINLET_H_
34
35//#include <map>
36//#include <set>
37//#include "drain/util/Debug.h"
38//#include "drain/util/ReferenceMap.h"
39
40#include <drain/Log.h>
41#include "drain/util/BeanLike.h"
42#include "drain/util/Flags.h"
43#include "drain/util/ReferenceMap.h"
44#include "drain/util/VariableMap.h"
45
46//#include "drain/util/Cloner.h"
47#include "Context.h"
48
49namespace drain {
50
52
55class Command : public Contextual {
56
57public:
58
59
60 inline
61 Command(): section(0){}; //
62
63 inline
64 Command(const Command & cmd) : section(cmd.section), lastParameters(cmd.lastParameters){
65 // setParameters(cmd.getParameters()); they do not exist yet!
66 }
67
68 virtual inline
69 ~Command(){};
70
71
73
76 virtual
77 const std::string & getName() const = 0;
78
79 virtual
80 const std::string & getDescription() const = 0;
81
82 virtual
83 const ReferenceMap & getParameters() const = 0;
84
85 static
86 const SprinterLayout cmdArgLayout; // = {",", "?", "=", ""};
87
88
89 virtual
90 void setParameters(const std::string & args) final;
91
92 // TODO: make this a loop calling set(key,val) - but then no
93 template <class T>
94 void setParameters(const T & args){
95 // TODO: set parameter X=Y ?
96 ReferenceMap & parameters = getParameters();
97 std::stringstream sstr;
98 char separator = 0;
99 for (const auto & entry: args){
100 parameters[entry.first] = entry.second;
101 // setParameter(entry.first, entry.second);
102 if (separator)
103 sstr << separator;
104 else
105 separator = ',';
106 sstr << entry.first << '=' << entry.second;
107 }
108 lastParameters = sstr.str();
109
110 }
111
113
117 template <class T>
118 void setParameter(const std::string & key, const T & value){
119 getParameters()[key] = value;
120 std::stringstream sstr;
121 sstr << key << '=' << value;
122 lastParameters = sstr.str();
123 }
124
125
126
127 // Could also need/replace void setParameters(const std::map<std::string,T> & p)
128
129 inline
130 bool hasParameters() const {
131
132 Logger mout(__FILE__, __FUNCTION__);
133
134 const ReferenceMap & params = this->getParameters();
135 //mout.warn(params );
136
137 const ReferenceMap::const_iterator it = params.begin();
138 if (it == params.end()) // empty
139 return false;
140 else
141 return it->second.getType() != typeid(void); // ???
142 };
143
145 /*
146 virtual inline
147 const std::string & getType() const {
148 static const std::string empty;
149 return empty;
150 };
151 */
152
153
155
158 virtual inline
159 void run(const std::string & params = "") final {
160 setParameters(params);
161 update();
162 exec();
163 }
164
166
169 virtual
170 void update(){
171 }
172
174 virtual inline
175 void exec() const {};
176
177
178 // Optional bit(s) marking the command type (compare with manual page sections)
182 typedef int cmd_section_type;
183 cmd_section_type section = 1;
184
185 inline
186 Command & addSection(int i){ // drain::FlaggerBase<>::ivalue_t
187 section |= i;
188 return *this;
189 }
190
191 inline
192 const std::string & getLastParameters() const {
193 return lastParameters;
194 };
195
196
197 //virtual
198 // void help(std::ostream & ostr = std::cout, bool DETAILED=false) const final;
199
200 virtual
201 void getRelatedCommands(std::ostream & ostr = std::cout) const;
202
203
205
211 /*
212 template <class C, class ...CC>
213 Command & linkRelatedCommands(const C & cmd, const CC & ... cmds){
214 relatedCommands.insert(cmd);
215 linkRelatedCommands(cmds...);
216 return *this;
217 };
218 */
219
220 inline
221 void linkRelated(const std::string & cmdKey) const {
222 relatedCommands.insert(cmdKey);
223 };
224
226
231 virtual
232 void parametersToStream(std::ostream & ostr, const std::string & indent= " ") const;
233
234 virtual inline
235 void parameterKeysToStream(std::ostream & ostr) const {
236 parameterKeysToStream(ostr, getParameters().getKeyList(), getParameters().separator);
237 };
238
239 void parameterKeysToStream(std::ostream & ostr, const std::list<std::string> & list, char sep=',') const;
240
241
242protected:
243
244 mutable
245 std::set<std::string> relatedCommands;
246
247 // Terminal
248 /*
249 inline
250 Command & linkRelatedCommands(){
251 return *this;
252 };
253 */
254
255 // Why protected?
256 virtual
257 ReferenceMap & getParameters() = 0;
258
259 // Clumsy but useful
260 std::string lastParameters;
261
262};
263
264inline
265std::ostream & operator<<(std::ostream & ostr, const Command &cmd){
266 ostr << cmd.getName();
267 if (cmd.hasParameters()){
268 ostr << ' ' << cmd.getParameters(); // << ' ';
269 }
270 return ostr;
271}
272
273// See new implementations in CommandBank, CommandUtils.
274//typedef std::list<std::pair<Command &, std::string> > Script; // TODO: move
275
276
278/*
279template <class B>
280class BeanerCommand : public Command {
281
282public:
283
284 typedef B bean_t;
285
286 // Main
287 virtual
288 const bean_t & getBean() const = 0;
289
290 // Main
291 virtual
292 bean_t & getBean() = 0;
293
294
295
296
297 inline
298 const std::string & getName() const final {
299 return getBean().getName();
300 };
301
302 inline
303 const std::string & getDescription() const final {
304 return getBean().getDescription();
305 };
306
307 virtual inline
308 const drain::ReferenceMap & getParameters() const final {
309 return getBean().getParameters();
310 };
311
312protected:
313
314 virtual inline
315 drain::ReferenceMap & getParameters() final {
316 return getBean().getParameters();
317 };
318
319};
320*/
321
323
329template <class B, class B2=B>
330class BeanCommand : public Command {
331// class BeanCommand : public BeanerCommand<B> { // public Command {
332
333public:
334
335 BeanCommand(){
336 };
337
338 BeanCommand(const std::string & name, const std::string & description) : bean(name, description){
339 };
340
341
342 BeanCommand(const BeanCommand & cmd) : Command(cmd), bean(cmd.bean) {
343 // WARNING: this may have undesired beaviour:
344 // If B2 is (Bean &), also new instance of beanCmd.bean -> cmd.bean
345 };
346
347 BeanCommand(B & b) : bean(b) {
348 };
349
350 typedef B bean_t;
351
352// Consider private:
353 B2 bean;
354
355
356 virtual inline
357 const bean_t & getBean() const { // final
358 return bean;
359 };
360
361 // Main
362 virtual inline
363 bean_t & getBean() { // final
364 return bean;
365 };
366
367
368
369 inline
370 const std::string & getName() const final {
371 return getBean().getName();
372 };
373
374 inline
375 const std::string & getDescription() const final {
376 return getBean().getDescription();
377 };
378
379 virtual inline
380 const drain::ReferenceMap & getParameters() const { // final
381 return getBean().getParameters();
382 };
383
384protected:
385
386 virtual inline
387 drain::ReferenceMap & getParameters() final {
388 return getBean().getParameters();
389 };
390
391
392 /*
393 virtual
394 void setAllParameters(const std::string & args) override {
395
396 Context & ctx = this->template getContext<>();
397 drain::Logger mout(ctx.log, __FUNCTION__, this->bean.getName() );
398
399 bean.setParameters(args,'=');
400 //mout.note() = "updating";
401 //this->update();
402 }
403 */
404
406 //virtual
407 /*
408 void setParameters(const VariableMap & params){
409 bean.setParameters(params);
410 // this->update();
411 }
412 */
413
414};
415
416
417
418template <class B>
419class BeanRefCommand : public drain::BeanCommand<B, B&> {
420
421public:
422
424 }
425
426 BeanRefCommand(const B & bean) : drain::BeanCommand<B,B&>(bean){
427 }
428
429 BeanRefCommand(const BeanRefCommand<B> & beanRefCmd) : drain::BeanCommand<B,B&>(beanRefCmd.bean){
430 }
431
432
433};
434
435
436
437
439
445class BasicCommand : public BeanCommand<BeanLike> { // Todo consider BeanLike
446
447public:
448
449 BasicCommand(const std::string & name, const std::string & description);
450
451 inline
452 //BasicCommand(const BasicCommand & cmd): Command(cmd), name(cmd.name), description(cmd.description) {
454 // remember to call importParameters()
455 }
456
457};
458
459
460//typedef BeanCommand<BeanLike> BasicCommand;
461
462
463
465
468template <class T = std::string>
470
471public:
472
473 T value;
474
475 SimpleCommand(const std::string & name, const std::string & description,
476 const std::string & key="value", const T & initValue = T(), const std::string & unit = "") : BasicCommand(name, description) {
477
478 getParameters().separator = '\0';
479 getParameters().link(key, value = initValue, unit);
480
481 if (key.empty()){
482 Context & ctx = getContext<Context>();
483 drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
484 mout.warn("Empty value key in command ", name, " (", description, ")");
485 }
486
487
488 };
489
491 template <class S>
492 SimpleCommand(const std::string & name, const std::string & description,
493 const std::string & key, std::initializer_list<S> l , const std::string & unit = "") : BasicCommand(name, description) {
494 // parameters.separator = '\0';
495 value = l;
496 getParameters().link(key, value);
497
498 if (key.empty()){
499 Context & ctx = getContext<Context>();
500 drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
501 mout.warn("Empty value key in command ", name, " (", description, ")");
502 }
503 };
504
505
506 SimpleCommand(const SimpleCommand & cmd): BasicCommand(cmd) {
507 getParameters().separator = '\0';
508 getParameters().copyStruct(cmd.getParameters(), cmd, *this);
509 /*
510 parameters.separator = '\0';
511 parameters.copyStruct(cmd.getParameters(), cmd, *this);
512 */
513 };
514
515 /*
516 void setParameters(const std::string & args){
517 const std::string & key = parameters.begin()->first;
518 Variable v(typeid(T));
519 if (key.empty()){
520 v = args;
521 }
522 else {
523 const std::string assignment = key+"=";
524 const size_t n = assignment.length();
525 if (args.compare(0,n,key)==0){
526 v = args.substr(n);
527 }
528 else
529 v = args;
530 }
531 value = v;
532 }
533 */
534
535
536
537};
538
540
543/*
544class DynamicCommand : public drain::Command {
545
546public:
547
548 virtual
549 void exec() const {
550 Context & ctx = getContext<Context>();
551 drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
552 mout.note("I am " , getName() , ", invoked as " , key );
553 }
554
555 virtual
556 void setKey(const std::string & cmdKey) const {
557 key = cmdKey;
558 }
559
560protected:
561
562 mutable
563 std::string key;
564
565};
566*/
567
568
569
570
571} // drain::
572
573#endif /* DRAINLET_H_ */
Simple implementation of Command: adds name , description and parameters .
Definition Command.h:445
Retrieves bean dynamically for each call.
Definition Command.h:330
const std::string & getName() const final
Returns the class name of this command, like "CmdVerbose".
Definition Command.h:370
Definition Command.h:419
Base class for commands: typically actions taking parameters but also plain variable assignments and ...
Definition Command.h:55
int cmd_section_type
Definition Command.h:182
void linkRelated(const std::string &cmdKey) const
Add related command(s), to appear in help after "See-also:" phrase.
Definition Command.h:221
virtual const std::string & getName() const =0
Returns the class name of this command, like "CmdVerbose".
virtual void run(const std::string &params="") final
Description of result, comparable to a return type of a function. ?
Definition Command.h:159
virtual void parametersToStream(std::ostream &ostr, const std::string &indent=" ") const
By default, the "true", technical parameters.
Definition Command.cpp:132
virtual void exec() const
Run the command with current parameter values.
Definition Command.h:175
void setParameter(const std::string &key, const T &value)
Set a value to a single parameter.
Definition Command.h:118
virtual void setParameters(const std::string &args) final
Definition Command.cpp:40
virtual void update()
Optional method for preparing command to execution.
Definition Command.h:170
Definition Context.h:57
Definition Context.h:246
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:312
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:430
Definition ReferenceMap.h:207
void copyStruct(const ReferenceMap &m, const T &src, T &dst, extLinkPolicy policy=RESERVE)
Experimental. Copies references and values of a structure to another.
Definition ReferenceMap.h:407
A single-parameter command.
Definition Command.h:469
SimpleCommand(const std::string &name, const std::string &description, const std::string &key, std::initializer_list< S > l, const std::string &unit="")
Constuctor designer for SimpleCommand<Unituple<> > .
Definition Command.h:492
char separator
Default character used for splitting input and output. See setValues.
Definition SmartMap.h:85
Definition DataSelector.cpp:1277
Definition Sprinter.h:137