OmniSciDB  04ee39c94c
CommandResolutionChain.h
Go to the documentation of this file.
1 #ifndef COMMAND_RESOLUTION_CHAIN_H
2 #define COMMAND_RESOLUTION_CHAIN_H
3 
4 #include "CommandDeterminant.h"
5 #include "InputTokenizers.h"
6 #include "gtest/gtest.h"
7 
8 #include <sstream>
9 #include <vector>
10 
11 template <template <typename> class INPUT_PARSER_TYPE = QuotedInputSupportParser,
12  template <typename> class REGEX_INPUT_PARSER_TYPE = DefaultInputParser>
14  public:
15  FRIEND_TEST(OmniSQLTest, CommandResolutionChain_DefaultTokenizer);
16 
17  using CommandTokenList = std::vector<std::string>;
18  using ParamCountType = CommandTokenList::size_type;
19  using StandardTokenExtractor = INPUT_PARSER_TYPE<CommandTokenList>;
20  using RegexTokenExtractor = REGEX_INPUT_PARSER_TYPE<CommandTokenList>;
21 
23  CommandResolutionChain() = delete;
25 
26  template <typename RESOLUTION_FUNCTOR>
27  CommandResolutionChain(char const* command_line,
28  std::string const& target_command,
29  ParamCountType min_param_count,
30  ParamCountType max_param_count,
31  RESOLUTION_FUNCTOR resolution_op,
32  std::string const& custom_help,
33  std::ostream& output_stream = std::cout)
34  : m_resolved(false), m_output_stream(output_stream) {
35  extractTokens(command_line);
36 
37  resolve_command(target_command,
38  min_param_count,
39  max_param_count,
40  resolution_op,
42  target_command, min_param_count, max_param_count, custom_help));
43  }
44 
45  template <typename RESOLUTION_FUNCTOR>
46  CommandResolutionChain(char const* command_line,
47  std::string const& target_command,
48  ParamCountType min_param_count,
49  ParamCountType max_param_count,
50  RESOLUTION_FUNCTOR resolution_op,
51  std::ostream& output_stream = std::cout)
52  : m_resolved(false), m_output_stream(output_stream) {
53  extractTokens(command_line);
54 
56  target_command,
57  min_param_count,
58  max_param_count,
59  resolution_op,
60  default_help_string(target_command, min_param_count, max_param_count));
61  }
62 
63  template <typename RESOLUTION_FUNCTOR>
64  CommandResolutionChain& operator()(std::string const& target_command,
65  ParamCountType min_param_count,
66  ParamCountType max_param_count,
67  RESOLUTION_FUNCTOR resolution_op,
68  std::string const& custom_help) {
69  if (m_resolved == true) {
70  return (*this);
71  }
72  resolve_command(target_command,
73  min_param_count,
74  max_param_count,
75  resolution_op,
77  target_command, min_param_count, max_param_count, custom_help));
78  return (*this);
79  }
80 
81  template <typename RESOLUTION_FUNCTOR>
82  CommandResolutionChain& operator()(std::string const& target_command,
83  ParamCountType min_param_count,
84  ParamCountType max_param_count,
85  RESOLUTION_FUNCTOR resolution_op) {
86  if (m_resolved == true) {
87  return (*this);
88  }
90  target_command,
91  min_param_count,
92  max_param_count,
93  resolution_op,
94  default_help_string(target_command, min_param_count, max_param_count));
95  return (*this);
96  }
97 
98  bool is_resolved() { return m_resolved; }
99 
100  private:
101  // Tag Dispatching Constructs
102  struct LambdaSelector {};
103  struct FunctorSelector {};
106 
107  void extractTokens(char const* command_line) {
108  m_command_token_list = StandardTokenExtractor().extract_tokens(command_line);
109  m_regex_command_token_list = RegexTokenExtractor().extract_tokens(command_line);
110  }
111 
112  std::string custom_help_string(std::string const& target_command,
113  ParamCountType min_param_count,
114  ParamCountType max_param_count,
115  std::string const& custom_help) {
116  std::ostringstream help_stream;
117  if (min_param_count == max_param_count) {
118  help_stream << target_command << " incorrect number of parameters provided; need "
119  << min_param_count - 1 << " total parameter(s)\n"
120  << custom_help << std::endl;
121  } else {
122  help_stream << target_command
123  << " incorrect number of parameters provided; need between "
124  << min_param_count - 1 << " and " << max_param_count - 1
125  << " total parameter(s)\n"
126  << custom_help << std::endl;
127  }
128  return help_stream.str();
129  }
130 
131  std::string default_help_string(std::string const& target_command,
132  ParamCountType min_param_count,
133  ParamCountType max_param_count) {
134  std::ostringstream help_stream;
135  if (min_param_count == max_param_count) {
136  help_stream << target_command << " incorrect number of parameters provided; need "
137  << min_param_count - 1 << " total parameter(s)" << std::endl;
138  } else {
139  help_stream << target_command
140  << " incorrect number of parameters provided; need between "
141  << min_param_count - 1 << " and " << max_param_count - 1
142  << " total parameter(s)" << std::endl;
143  }
144  return help_stream.str();
145  }
146 
147  template <typename RESOLUTION_MECHANISM>
148  void resolve_command(std::string const& target_command,
149  ParamCountType min_param_count,
150  ParamCountType max_param_count,
151  RESOLUTION_MECHANISM resolution_op,
152  std::string const& help_info) {
153  using SelectorType = typename std::conditional<
154  std::is_base_of<CmdDeterminant, RESOLUTION_MECHANISM>::value,
157 
158  if (m_command_token_list.empty()) {
159  m_resolved = true;
160  } else if (m_command_token_list[0] == target_command) {
161  if (std::is_base_of<RegexCmdDeterminant, RESOLUTION_MECHANISM>::value) {
162  // Regexes have an optional parameter; therefore parameter counts can vary
163  // And we know the count is at least one, in this branch
164  execute_functor_resolution_op(resolution_op, SelectorType());
165  } else {
166  if (m_command_token_list.size() < min_param_count ||
167  m_command_token_list.size() > max_param_count) {
168  m_output_stream << help_info << '\n';
169  } else {
170  execute_functor_resolution_op(resolution_op, SelectorType());
171  }
172  }
173 
174  m_resolved = true;
175  }
176  }
177 
178  template <typename RESOLUTION_LAMBDA>
179  void execute_functor_resolution_op(RESOLUTION_LAMBDA resolution_op,
180  LambdaSelector const&) {
181  resolution_op(m_command_token_list);
182  }
183 
184  template <typename RESOLUTION_FUNCTOR>
185  void execute_functor_resolution_op(RESOLUTION_FUNCTOR resolution_op,
186  FunctorSelector const&) {
187  using CommandSelectorType = typename std::conditional<
188  std::is_base_of<RegexCmdDeterminant, RESOLUTION_FUNCTOR>::value,
191  execute_regex_aware_resolution_op(resolution_op, CommandSelectorType());
192  }
193 
194  template <typename RESOLUTION_FUNCTOR>
195  void execute_regex_aware_resolution_op(RESOLUTION_FUNCTOR resolution_op,
196  RegexCommandSelector const&) {
198  }
199 
200  template <typename RESOLUTION_FUNCTOR>
201  void execute_regex_aware_resolution_op(RESOLUTION_FUNCTOR resolution_op,
202  StandardCommandSelector const&) {
203  resolution_op(m_command_token_list, m_output_stream);
204  }
205 
209  std::ostream& m_output_stream;
210 };
211 
212 #endif
std::string default_help_string(std::string const &target_command, ParamCountType min_param_count, ParamCountType max_param_count)
CommandResolutionChain & operator()(std::string const &target_command, ParamCountType min_param_count, ParamCountType max_param_count, RESOLUTION_FUNCTOR resolution_op, std::string const &custom_help)
void execute_functor_resolution_op(RESOLUTION_LAMBDA resolution_op, LambdaSelector const &)
void extractTokens(char const *command_line)
void resolve_command(std::string const &target_command, ParamCountType min_param_count, ParamCountType max_param_count, RESOLUTION_MECHANISM resolution_op, std::string const &help_info)
CommandResolutionChain(char const *command_line, std::string const &target_command, ParamCountType min_param_count, ParamCountType max_param_count, RESOLUTION_FUNCTOR resolution_op, std::ostream &output_stream=std::cout)
CommandTokenList::size_type ParamCountType
void execute_regex_aware_resolution_op(RESOLUTION_FUNCTOR resolution_op, StandardCommandSelector const &)
CommandTokenList m_command_token_list
CommandResolutionChain()=delete
INPUT_PARSER_TYPE< CommandTokenList > StandardTokenExtractor
CommandResolutionChain & operator()(std::string const &target_command, ParamCountType min_param_count, ParamCountType max_param_count, RESOLUTION_FUNCTOR resolution_op)
CommandResolutionChain(char const *command_line, std::string const &target_command, ParamCountType min_param_count, ParamCountType max_param_count, RESOLUTION_FUNCTOR resolution_op, std::string const &custom_help, std::ostream &output_stream=std::cout)
CommandResolutionChain & operator=(CommandResolutionChain const &)=delete
void execute_functor_resolution_op(RESOLUTION_FUNCTOR resolution_op, FunctorSelector const &)
FRIEND_TEST(OmniSQLTest, CommandResolutionChain_DefaultTokenizer)
REGEX_INPUT_PARSER_TYPE< CommandTokenList > RegexTokenExtractor
std::string custom_help_string(std::string const &target_command, ParamCountType min_param_count, ParamCountType max_param_count, std::string const &custom_help)
CommandTokenList m_regex_command_token_list
void execute_regex_aware_resolution_op(RESOLUTION_FUNCTOR resolution_op, RegexCommandSelector const &)
std::vector< std::string > CommandTokenList