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/ReferenceMap.h"
43
44//#include "drain/util/Cloner.h"
45#include "Context.h"
46
47namespace drain {
48
50
53class Command : public Contextual {
54
55public:
56
57
58 inline
59 Command(): section(0){}; //
60
61 inline
62 Command(const Command & cmd) : section(cmd.section), lastParameters(cmd.lastParameters){
63 // setParameters(cmd.getParameters()); they do not exist yet!
64 }
65
66 virtual inline
67 ~Command(){};
68
69
71
74 virtual
75 const std::string & getName() const = 0;
76
77 virtual
78 const std::string & getDescription() const = 0;
79
80 virtual
81 const ReferenceMap & getParameters() const = 0;
82
83 static
84 const SprinterLayout cmdArgLayout; // = {",", "?", "=", ""};
85
86
87 virtual
88 void setParameters(const std::string & args) final;
89
90 // TODO: make this a loop calling set(key,val) - but then no
91 template <class T>
92 void setParameters(const T & args){
93 // TODO: set parameter X=Y ?
94 ReferenceMap & parameters = getParameters();
95 std::stringstream sstr;
96 char separator = 0;
97 for (const auto & entry: args){
98 parameters[entry.first] = entry.second;
99 // setParameter(entry.first, entry.second);
100 if (separator)
101 sstr << separator;
102 else
103 separator = ',';
104 sstr << entry.first << '=' << entry.second;
105 }
106 lastParameters = sstr.str();
107
108 }
109
111
115 template <class T>
116 void setParameter(const std::string & key, const T & value){
117 getParameters()[key] = value;
118 std::stringstream sstr;
119 sstr << key << '=' << value;
120 lastParameters = sstr.str();
121 }
122
123
124
125 // Could also need/replace void setParameters(const std::map<std::string,T> & p)
126
127 inline
128 bool hasParameters() const {
129
130 Logger mout(__FILE__, __FUNCTION__);
131
132 const ReferenceMap & params = this->getParameters();
133 //mout.warn(params );
134
135 const ReferenceMap::const_iterator it = params.begin();
136 if (it == params.end()) // empty
137 return false;
138 else
139 return it->second.getType() != typeid(void); // ???
140 };
141
143 /*
144 virtual inline
145 const std::string & getType() const {
146 static const std::string empty;
147 return empty;
148 };
149 */
150
151
153
156 virtual inline
157 void run(const std::string & params = "") final {
158 setParameters(params);
159 update();
160 exec();
161 }
162
164
167 virtual
168 void update(){
169 }
170
172 virtual inline
173 void exec() const {};
174
175
176 // Optional bit(s) marking the command type (compare with manual page sections)
180 typedef int cmd_section_type;
181 cmd_section_type section = 1;
182
183 inline
184 Command & addSection(int i){ // drain::FlaggerBase<>::ivalue_t
185 section |= i;
186 return *this;
187 }
188
189 inline
190 const std::string & getLastParameters() const {
191 return lastParameters;
192 };
193
194
195 //virtual
196 // void help(std::ostream & ostr = std::cout, bool DETAILED=false) const final;
197
198 virtual
199 void getRelatedCommands(std::ostream & ostr = std::cout) const;
200
201
203
209 /*
210 template <class C, class ...CC>
211 Command & linkRelatedCommands(const C & cmd, const CC & ... cmds){
212 relatedCommands.insert(cmd);
213 linkRelatedCommands(cmds...);
214 return *this;
215 };
216 */
217
218 inline
219 void linkRelated(const std::string & cmdKey) const {
220 relatedCommands.insert(cmdKey);
221 };
222
224
229 virtual
230 void parametersToStream(std::ostream & ostr, const std::string & indent= " ") const;
231
232 virtual inline
233 void parameterKeysToStream(std::ostream & ostr) const {
234 parameterKeysToStream(ostr, getParameters().getKeyList(), getParameters().separator);
235 };
236
237 void parameterKeysToStream(std::ostream & ostr, const std::list<std::string> & list, char sep=',') const;
238
239
240protected:
241
242 mutable
243 std::set<std::string> relatedCommands;
244
245 // Terminal
246 /*
247 inline
248 Command & linkRelatedCommands(){
249 return *this;
250 };
251 */
252
253 // Why protected?
254 virtual
255 ReferenceMap & getParameters() = 0;
256
257 // Clumsy but useful
258 std::string lastParameters;
259
260};
261
262inline
263std::ostream & operator<<(std::ostream & ostr, const Command &cmd){
264 ostr << cmd.getName();
265 if (cmd.hasParameters()){
266 ostr << ' ' << cmd.getParameters(); // << ' ';
267 }
268 return ostr;
269}
270
271// See new implementations in CommandBank, CommandUtils.
272//typedef std::list<std::pair<Command &, std::string> > Script; // TODO: move
273
274
276/*
277template <class B>
278class BeanerCommand : public Command {
279
280public:
281
282 typedef B bean_t;
283
284 // Main
285 virtual
286 const bean_t & getBean() const = 0;
287
288 // Main
289 virtual
290 bean_t & getBean() = 0;
291
292
293
294
295 inline
296 const std::string & getName() const final {
297 return getBean().getName();
298 };
299
300 inline
301 const std::string & getDescription() const final {
302 return getBean().getDescription();
303 };
304
305 virtual inline
306 const drain::ReferenceMap & getParameters() const final {
307 return getBean().getParameters();
308 };
309
310protected:
311
312 virtual inline
313 drain::ReferenceMap & getParameters() final {
314 return getBean().getParameters();
315 };
316
317};
318*/
319
321
327template <class B, class B2=B>
328class BeanCommand : public Command {
329// class BeanCommand : public BeanerCommand<B> { // public Command {
330
331public:
332
333 BeanCommand(){
334 };
335
336 BeanCommand(const std::string & name, const std::string & description) : bean(name, description){
337 };
338
339
340 BeanCommand(const BeanCommand & cmd) : Command(cmd), bean(cmd.bean) {
341 // WARNING: this may have undesired beaviour:
342 // If B2 is (Bean &), also new instance of beanCmd.bean -> cmd.bean
343 };
344
345 BeanCommand(B & b) : bean(b) {
346 };
347
348 typedef B bean_t;
349
350// Consider private:
351 B2 bean;
352
353
354 virtual inline
355 const bean_t & getBean() const { // final
356 return bean;
357 };
358
359 // Main
360 virtual inline
361 bean_t & getBean() { // final
362 return bean;
363 };
364
365
366
367 inline
368 const std::string & getName() const final {
369 return getBean().getName();
370 };
371
372 inline
373 const std::string & getDescription() const final {
374 return getBean().getDescription();
375 };
376
377 virtual inline
378 const drain::ReferenceMap & getParameters() const { // final
379 return getBean().getParameters();
380 };
381
382protected:
383
384 virtual inline
385 drain::ReferenceMap & getParameters() final {
386 return getBean().getParameters();
387 };
388
389
390 /*
391 virtual
392 void setAllParameters(const std::string & args) override {
393
394 Context & ctx = this->template getContext<>();
395 drain::Logger mout(ctx.log, __FUNCTION__, this->bean.getName() );
396
397 bean.setParameters(args,'=');
398 //mout.note() = "updating";
399 //this->update();
400 }
401 */
402
404 //virtual
405 /*
406 void setParameters(const VariableMap & params){
407 bean.setParameters(params);
408 // this->update();
409 }
410 */
411
412};
413
414
415
416template <class B>
417class BeanRefCommand : public drain::BeanCommand<B, B&> {
418
419public:
420
422 }
423
424 BeanRefCommand(const B & bean) : drain::BeanCommand<B,B&>(bean){
425 }
426
427 BeanRefCommand(const BeanRefCommand<B> & beanRefCmd) : drain::BeanCommand<B,B&>(beanRefCmd.bean){
428 }
429
430
431};
432
433
434
435
437
443class BasicCommand : public BeanCommand<BeanLike> { // Todo consider BeanLike
444
445public:
446
447 BasicCommand(const std::string & name, const std::string & description);
448
449 inline
450 //BasicCommand(const BasicCommand & cmd): Command(cmd), name(cmd.name), description(cmd.description) {
452 // remember to call importParameters()
453 }
454
455};
456
457
458//typedef BeanCommand<BeanLike> BasicCommand;
459
460
461
463
466template <class T = std::string>
468
469public:
470
471 T value;
472
473 SimpleCommand(const std::string & name, const std::string & description,
474 const std::string & key="value", const T & initValue = T(), const std::string & unit = "") : BasicCommand(name, description) {
475
476 getParameters().separator = '\0';
477 getParameters().link(key, value = initValue, unit);
478
479 if (key.empty()){
480 Context & ctx = getContext<Context>();
481 drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
482 mout.warn("Empty value key in command ", name, " (", description, ")");
483 }
484
485
486 };
487
489 template <class S>
490 SimpleCommand(const std::string & name, const std::string & description,
491 const std::string & key, std::initializer_list<S> l , const std::string & unit = "") : BasicCommand(name, description) {
492 // parameters.separator = '\0';
493 value = l;
494 getParameters().link(key, value);
495
496 if (key.empty()){
497 Context & ctx = getContext<Context>();
498 drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
499 mout.warn("Empty value key in command ", name, " (", description, ")");
500 }
501 };
502
503
504 SimpleCommand(const SimpleCommand & cmd): BasicCommand(cmd) {
505 getParameters().separator = '\0';
506 getParameters().copyStruct(cmd.getParameters(), cmd, *this);
507 /*
508 parameters.separator = '\0';
509 parameters.copyStruct(cmd.getParameters(), cmd, *this);
510 */
511 };
512
513 /*
514 void setParameters(const std::string & args){
515 const std::string & key = parameters.begin()->first;
516 Variable v(typeid(T));
517 if (key.empty()){
518 v = args;
519 }
520 else {
521 const std::string assignment = key+"=";
522 const size_t n = assignment.length();
523 if (args.compare(0,n,key)==0){
524 v = args.substr(n);
525 }
526 else
527 v = args;
528 }
529 value = v;
530 }
531 */
532
533
534
535};
536
538
541/*
542class DynamicCommand : public drain::Command {
543
544public:
545
546 virtual
547 void exec() const {
548 Context & ctx = getContext<Context>();
549 drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
550 mout.note("I am " , getName() , ", invoked as " , key );
551 }
552
553 virtual
554 void setKey(const std::string & cmdKey) const {
555 key = cmdKey;
556 }
557
558protected:
559
560 mutable
561 std::string key;
562
563};
564*/
565
566
567
568
569} // drain::
570
571#endif /* DRAINLET_H_ */
Simple implementation of Command: adds name , description and parameters .
Definition Command.h:443
Retrieves bean dynamically for each call.
Definition Command.h:328
const std::string & getName() const final
Returns the class name of this command, like "CmdVerbose".
Definition Command.h:368
Definition Command.h:417
Base class for commands: typically actions taking parameters but also plain variable assignments and ...
Definition Command.h:53
int cmd_section_type
Definition Command.h:180
void linkRelated(const std::string &cmdKey) const
Add related command(s), to appear in help after "See-also:" phrase.
Definition Command.h:219
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:157
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:173
void setParameter(const std::string &key, const T &value)
Set a value to a single parameter.
Definition Command.h:116
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:168
Definition Context.h:54
Definition Context.h:245
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:313
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:431
Definition ReferenceMap.h:215
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:415
A single-parameter command.
Definition Command.h:467
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:490
char separator
Default character used for splitting input and output. See setValues.
Definition SmartMap.h:81
Definition DataSelector.cpp:1277
Definition Sprinter.h:136