Command.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood 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 
49 namespace drain {
50 
52 
55 class Command : public Contextual {
56 
57 public:
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  // TODO: getFullName(), the "C++ name" of this (derived) class.
72  // Typically not same as the command line command.
73 
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 public:
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  virtual inline
146  const std::string & getType() const {
147  static const std::string empty;
148  return empty;
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 protected:
195 
196  virtual
197  ReferenceMap & getParameters() = 0;
198 
199  // Clumsy but useful
200  std::string lastParameters;
201 
202 };
203 
204 inline
205 std::ostream & operator<<(std::ostream & ostr, const Command &cmd){
206  ostr << cmd.getName();
207  if (cmd.hasParameters()){
208  ostr << ' ' << cmd.getParameters(); // << ' ';
209  }
210  return ostr;
211 }
212 
213 // See new implementations in CommandBank, CommandUtils.
214 //typedef std::list<std::pair<Command &, std::string> > Script; // TODO: move
215 
216 
218 /*
219 template <class B>
220 class BeanerCommand : public Command {
221 
222 public:
223 
224  typedef B bean_t;
225 
226  // Main
227  virtual
228  const bean_t & getBean() const = 0;
229 
230  // Main
231  virtual
232  bean_t & getBean() = 0;
233 
234 
235 
236 
237  inline
238  const std::string & getName() const final {
239  return getBean().getName();
240  };
241 
242  inline
243  const std::string & getDescription() const final {
244  return getBean().getDescription();
245  };
246 
247  virtual inline
248  const drain::ReferenceMap & getParameters() const final {
249  return getBean().getParameters();
250  };
251 
252 protected:
253 
254  virtual inline
255  drain::ReferenceMap & getParameters() final {
256  return getBean().getParameters();
257  };
258 
259 };
260 */
261 
263 
269 template <class B, class B2=B>
270 class BeanCommand : public Command {
271 // class BeanCommand : public BeanerCommand<B> { // public Command {
272 
273 public:
274 
275  BeanCommand(){
276  };
277 
278  BeanCommand(const std::string & name, const std::string & description) : bean(name, description){
279  };
280 
281 
282  BeanCommand(const BeanCommand & cmd) : Command(cmd), bean(cmd.bean) {
283  // WARNING: this may have undesired beaviour:
284  // If B2 is (Bean &), also new instance of beanCmd.bean -> cmd.bean
285  };
286 
287  BeanCommand(B & b) : bean(b) {
288  };
289 
290  typedef B bean_t;
291 
292 // Consider private:
293  B2 bean;
294 
295 
296  virtual inline
297  const bean_t & getBean() const { // final
298  return bean;
299  };
300 
301  // Main
302  virtual inline
303  bean_t & getBean() { // final
304  return bean;
305  };
306 
307 
308 
309  inline
310  const std::string & getName() const final {
311  return getBean().getName();
312  };
313 
314  inline
315  const std::string & getDescription() const final {
316  return getBean().getDescription();
317  };
318 
319  virtual inline
320  const drain::ReferenceMap & getParameters() const final {
321  return getBean().getParameters();
322  };
323 
324 protected:
325 
326  virtual inline
327  drain::ReferenceMap & getParameters() final {
328  return getBean().getParameters();
329  };
330 
331 
332  /*
333  virtual
334  void setAllParameters(const std::string & args) override {
335 
336  Context & ctx = this->template getContext<>();
337  drain::Logger mout(ctx.log, __FUNCTION__, this->bean.getName() );
338 
339  bean.setParameters(args,'=');
340  //mout.note() = "updating";
341  //this->update();
342  }
343  */
344 
346  //virtual
347  /*
348  void setParameters(const VariableMap & params){
349  bean.setParameters(params);
350  // this->update();
351  }
352  */
353 
354 };
355 
356 
357 
358 template <class B>
359 class BeanRefCommand : public drain::BeanCommand<B, B&> {
360 
361 public:
362 
363  BeanRefCommand(B & bean) : drain::BeanCommand<B,B&>(bean){
364  }
365 
366  BeanRefCommand(const B & bean) : drain::BeanCommand<B,B&>(bean){
367  }
368 
369  BeanRefCommand(const BeanRefCommand<B> & beanRefCmd) : drain::BeanCommand<B,B&>(beanRefCmd.bean){
370  }
371 
372 
373 };
374 
375 
376 
377 
379 
385 class BasicCommand : public BeanCommand<BeanLike> { // Todo consider BeanLike
386 
387 public:
388 
389  BasicCommand(const std::string & name, const std::string & description);
390 
391  inline
392  //BasicCommand(const BasicCommand & cmd): Command(cmd), name(cmd.name), description(cmd.description) {
393  BasicCommand(const BasicCommand & cmd): BeanCommand<BeanLike>(cmd) {
394  // remember to call importParameters()
395  }
396 
397 };
398 
399 
400 //typedef BeanCommand<BeanLike> BasicCommand;
401 
402 
403 
405 
408 template <class T = std::string>
409 class SimpleCommand : public BasicCommand {
410 
411 public:
412 
413  T value;
414 
415  SimpleCommand(const std::string & name, const std::string & description,
416  const std::string & key="value", const T & initValue = T(), const std::string & unit = "") : BasicCommand(name, description) {
417 
418  getParameters().separator = '\0';
419  getParameters().link(key, value = initValue, unit);
420 
421  if (key.empty()){
422  Context & ctx = getContext<Context>();
423  drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
424  mout.warn("Empty value key in command ", name, " (", description, ")");
425  }
426 
427 
428  };
429 
431  template <class S>
432  SimpleCommand(const std::string & name, const std::string & description,
433  const std::string & key, std::initializer_list<S> l , const std::string & unit = "") : BasicCommand(name, description) {
434  // parameters.separator = '\0';
435  value = l;
436  getParameters().link(key, value);
437 
438  if (key.empty()){
439  Context & ctx = getContext<Context>();
440  drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
441  mout.warn("Empty value key in command ", name, " (", description, ")");
442  }
443  };
444 
445 
446  SimpleCommand(const SimpleCommand & cmd): BasicCommand(cmd) {
447  getParameters().separator = '\0';
448  getParameters().copyStruct(cmd.getParameters(), cmd, *this);
449  /*
450  parameters.separator = '\0';
451  parameters.copyStruct(cmd.getParameters(), cmd, *this);
452  */
453  };
454 
455  /*
456  void setParameters(const std::string & args){
457  const std::string & key = parameters.begin()->first;
458  Variable v(typeid(T));
459  if (key.empty()){
460  v = args;
461  }
462  else {
463  const std::string assignment = key+"=";
464  const size_t n = assignment.length();
465  if (args.compare(0,n,key)==0){
466  v = args.substr(n);
467  }
468  else
469  v = args;
470  }
471  value = v;
472  }
473  */
474 
475 
476 
477 };
478 
480 
483 /*
484 class DynamicCommand : public drain::Command {
485 
486 public:
487 
488  virtual
489  void exec() const {
490  Context & ctx = getContext<Context>();
491  drain::Logger mout(ctx.log,__FILE__, __FUNCTION__);
492  mout.note("I am " , getName() , ", invoked as " , key );
493  }
494 
495  virtual
496  void setKey(const std::string & cmdKey) const {
497  key = cmdKey;
498  }
499 
500 protected:
501 
502  mutable
503  std::string key;
504 
505 };
506 */
507 
508 
509 
510 
511 } // drain::
512 
513 #endif /* DRAINLET_H_ */
Simple implementation of Command: adds name , description and parameters .
Definition: Command.h:385
Retrieves bean dynamically for each call.
Definition: Command.h:270
Definition: Command.h:359
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:173
virtual void run(const std::string &params="") final
Convenience. Sets parameters and executes the command.
Definition: Command.h:157
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:118
virtual const std::string & getType() const
Description of result, comparable to a return type of a function. ?
Definition: Command.h:146
virtual void update()
Optional method for preparing command to execution.
Definition: Command.h:168
Definition: Context.h:57
Definition: Context.h:252
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:310
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:428
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:409
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:432
char separator
Default character used for splitting input and output. See setValues.
Definition: SmartMap.h:85
Definition: DataSelector.cpp:1277
Definition: Sprinter.h:137