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;
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
225
226protected:
227
228 mutable
229 std::set<std::string> relatedCommands;
230
231 // Terminal
232 /*
233 inline
234 Command & linkRelatedCommands(){
235 return *this;
236 };
237 */
238
239 // Why protected?
240 virtual
241 ReferenceMap & getParameters() = 0;
242
243 // Clumsy but useful
244 std::string lastParameters;
245
246};
247
248inline
249std::ostream & operator<<(std::ostream & ostr, const Command &cmd){
250 ostr << cmd.getName();
251 if (cmd.hasParameters()){
252 ostr << ' ' << cmd.getParameters(); // << ' ';
253 }
254 return ostr;
255}
256
257// See new implementations in CommandBank, CommandUtils.
258//typedef std::list<std::pair<Command &, std::string> > Script; // TODO: move
259
260
262/*
263template <class B>
264class BeanerCommand : public Command {
265
266public:
267
268 typedef B bean_t;
269
270 // Main
271 virtual
272 const bean_t & getBean() const = 0;
273
274 // Main
275 virtual
276 bean_t & getBean() = 0;
277
278
279
280
281 inline
282 const std::string & getName() const final {
283 return getBean().getName();
284 };
285
286 inline
287 const std::string & getDescription() const final {
288 return getBean().getDescription();
289 };
290
291 virtual inline
292 const drain::ReferenceMap & getParameters() const final {
293 return getBean().getParameters();
294 };
295
296protected:
297
298 virtual inline
299 drain::ReferenceMap & getParameters() final {
300 return getBean().getParameters();
301 };
302
303};
304*/
305
307
313template <class B, class B2=B>
314class BeanCommand : public Command {
315// class BeanCommand : public BeanerCommand<B> { // public Command {
316
317public:
318
319 BeanCommand(){
320 };
321
322 BeanCommand(const std::string & name, const std::string & description) : bean(name, description){
323 };
324
325
326 BeanCommand(const BeanCommand & cmd) : Command(cmd), bean(cmd.bean) {
327 // WARNING: this may have undesired beaviour:
328 // If B2 is (Bean &), also new instance of beanCmd.bean -> cmd.bean
329 };
330
331 BeanCommand(B & b) : bean(b) {
332 };
333
334 typedef B bean_t;
335
336// Consider private:
337 B2 bean;
338
339
340 virtual inline
341 const bean_t & getBean() const { // final
342 return bean;
343 };
344
345 // Main
346 virtual inline
347 bean_t & getBean() { // final
348 return bean;
349 };
350
351
352
353 inline
354 const std::string & getName() const final {
355 return getBean().getName();
356 };
357
358 inline
359 const std::string & getDescription() const final {
360 return getBean().getDescription();
361 };
362
363 virtual inline
364 const drain::ReferenceMap & getParameters() const final {
365 return getBean().getParameters();
366 };
367
368protected:
369
370 virtual inline
371 drain::ReferenceMap & getParameters() final {
372 return getBean().getParameters();
373 };
374
375
376 /*
377 virtual
378 void setAllParameters(const std::string & args) override {
379
380 Context & ctx = this->template getContext<>();
381 drain::Logger mout(ctx.log, __FUNCTION__, this->bean.getName() );
382
383 bean.setParameters(args,'=');
384 //mout.note() = "updating";
385 //this->update();
386 }
387 */
388
390 //virtual
391 /*
392 void setParameters(const VariableMap & params){
393 bean.setParameters(params);
394 // this->update();
395 }
396 */
397
398};
399
400
401
402template <class B>
403class BeanRefCommand : public drain::BeanCommand<B, B&> {
404
405public:
406
408 }
409
410 BeanRefCommand(const B & bean) : drain::BeanCommand<B,B&>(bean){
411 }
412
413 BeanRefCommand(const BeanRefCommand<B> & beanRefCmd) : drain::BeanCommand<B,B&>(beanRefCmd.bean){
414 }
415
416
417};
418
419
420
421
423
429class BasicCommand : public BeanCommand<BeanLike> { // Todo consider BeanLike
430
431public:
432
433 BasicCommand(const std::string & name, const std::string & description);
434
435 inline
436 //BasicCommand(const BasicCommand & cmd): Command(cmd), name(cmd.name), description(cmd.description) {
438 // remember to call importParameters()
439 }
440
441};
442
443
444//typedef BeanCommand<BeanLike> BasicCommand;
445
446
447
449
452template <class T = std::string>
454
455public:
456
457 T value;
458
459 SimpleCommand(const std::string & name, const std::string & description,
460 const std::string & key="value", const T & initValue = T(), const std::string & unit = "") : BasicCommand(name, description) {
461
462 getParameters().separator = '\0';
463 getParameters().link(key, value = initValue, unit);
464
465 if (key.empty()){
466 Context & ctx = getContext<Context>();
467 drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
468 mout.warn("Empty value key in command ", name, " (", description, ")");
469 }
470
471
472 };
473
475 template <class S>
476 SimpleCommand(const std::string & name, const std::string & description,
477 const std::string & key, std::initializer_list<S> l , const std::string & unit = "") : BasicCommand(name, description) {
478 // parameters.separator = '\0';
479 value = l;
480 getParameters().link(key, value);
481
482 if (key.empty()){
483 Context & ctx = getContext<Context>();
484 drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
485 mout.warn("Empty value key in command ", name, " (", description, ")");
486 }
487 };
488
489
490 SimpleCommand(const SimpleCommand & cmd): BasicCommand(cmd) {
491 getParameters().separator = '\0';
492 getParameters().copyStruct(cmd.getParameters(), cmd, *this);
493 /*
494 parameters.separator = '\0';
495 parameters.copyStruct(cmd.getParameters(), cmd, *this);
496 */
497 };
498
499 /*
500 void setParameters(const std::string & args){
501 const std::string & key = parameters.begin()->first;
502 Variable v(typeid(T));
503 if (key.empty()){
504 v = args;
505 }
506 else {
507 const std::string assignment = key+"=";
508 const size_t n = assignment.length();
509 if (args.compare(0,n,key)==0){
510 v = args.substr(n);
511 }
512 else
513 v = args;
514 }
515 value = v;
516 }
517 */
518
519
520
521};
522
524
527/*
528class DynamicCommand : public drain::Command {
529
530public:
531
532 virtual
533 void exec() const {
534 Context & ctx = getContext<Context>();
535 drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
536 mout.note("I am " , getName() , ", invoked as " , key );
537 }
538
539 virtual
540 void setKey(const std::string & cmdKey) const {
541 key = cmdKey;
542 }
543
544protected:
545
546 mutable
547 std::string key;
548
549};
550*/
551
552
553
554
555} // drain::
556
557#endif /* DRAINLET_H_ */
Simple implementation of Command: adds name , description and parameters .
Definition Command.h:429
Retrieves bean dynamically for each call.
Definition Command.h:314
const std::string & getName() const final
Returns the class name of this command, like "CmdVerbose".
Definition Command.h:354
Definition Command.h:403
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 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:399
A single-parameter command.
Definition Command.h:453
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:476
char separator
Default character used for splitting input and output. See setValues.
Definition SmartMap.h:85
Definition DataSelector.cpp:1277
Definition Sprinter.h:137