libdap++  Updated for version 3.13.3
ConstraintEvaluator.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2002,2003 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 #include "config.h"
26 
27 //#define DODS_DEBUG
28 
29 #include "ServerFunctionsList.h"
30 #include "ConstraintEvaluator.h"
31 #include "Clause.h"
32 #include "DataDDS.h"
33 
34 #include "ce_parser.h"
35 #include "debug.h"
36 #include "parser.h"
37 #include "expr.h"
38 
39 struct yy_buffer_state;
40 
42 
43 // Glue routines declared in expr.lex
44 void ce_expr_switch_to_buffer(void *new_buffer);
45 void ce_expr_delete_buffer(void * buffer);
46 void *ce_expr_string(const char *yy_str);
47 
48 extern int ce_exprdebug;
49 
50 namespace libdap {
51 
53 {
54  // Functions are now held in BES modules. jhrg 1/30/13
55 
56  // modules load functions to this list; this class searches the list
57  // instead of having it's own copy. This is very similar to the BES'
58  // various List classes, but this one is part of libdap and not the
59  // BES. The List class is a singleton, so each function module can
60  // register it's functions to the list object.
61  d_functions_list = ServerFunctionsList::TheList();
62 }
63 
65 {
66  // delete all the constants created by the parser for CE evaluation
67  for (Constants_iter j = constants.begin(); j != constants.end(); j++) {
68  BaseType *btp = *j;
69  delete btp;
70  btp = 0;
71  }
72 
73  for (Clause_iter k = expr.begin(); k != expr.end(); k++) {
74  Clause *cp = *k;
75  delete cp;
76  cp = 0;
77  }
78 }
79 
82 {
83  return expr.begin();
84 }
85 
89 {
90  return expr.end();
91 }
92 
95 bool ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
96 {
97  if (expr.empty())
98  throw InternalErr(__FILE__, __LINE__, "There are no CE clauses for *this* DDS object.");
99 
100  return (*iter)->value(dds);
101 }
102 
116 {
117  Clause *clause = new Clause(op, arg1, arg2);
118 
119  expr.push_back(clause);
120 }
121 
132 {
133  Clause *clause = new Clause(func, args);
134 
135  expr.push_back(clause);
136 }
137 
148 {
149  Clause *clause = new Clause(func, args);
150 
151  expr.push_back(clause);
152 }
153 
162 {
163  constants.push_back(btp);
164 }
165 
167 bool ConstraintEvaluator::find_function(const string &name, bool_func *f) const
168 {
169  return d_functions_list->find_function(name, f);
170 }
171 
173 bool ConstraintEvaluator::find_function(const string &name, btp_func *f) const
174 {
175  return d_functions_list->find_function(name, f);
176 }
177 
179 bool ConstraintEvaluator::find_function(const string &name, proj_func *f) const
180 {
181  return d_functions_list->find_function(name, f);
182 }
184 
194 {
195  if (expr.empty())
196  return false;
197 
198  Clause *cp = expr[0];
199  return cp->value_clause();
200 }
201 
205 BaseType *
207 {
208  if (expr.size() != 1)
209  throw InternalErr(__FILE__, __LINE__, "The length of the list of CE clauses is not 1.");
210 
211  Clause *cp = expr[0];
212  BaseType *result;
213  if (cp->value(dds, &result))
214  return result;
215  else
216  return NULL;
217 }
218 
229 {
230  if (expr.empty())
231  return false;
232 
233  for (unsigned int i = 0; i < expr.size(); ++i) {
234  Clause *cp = expr[i];
235  if (!cp->value_clause())
236  return false;
237  }
238 
239  return true;
240 }
241 
257 DDS *
259 {
260  if (expr.empty())
261  throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
262 
263  DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
264  for (unsigned int i = 0; i < expr.size(); ++i) {
265  Clause *cp = expr[i];
266  BaseType *result;
267  if (cp->value(dds, &result)) {
268  // This is correct: The function must allocate the memory for the result
269  // variable. 11/30/12 jhrg
270  fdds->add_var_nocopy(result);
271  }
272  else {
273  delete fdds;
274  throw Error("A function was called but failed to return a value.");
275  }
276  }
277 
278  return fdds;
279 }
280 
286 DataDDS *
288 {
289  if (expr.empty())
290  throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
291 
292  DataDDS *fdds = new DataDDS(dds.get_factory(), "function_result_" + dds.get_dataset_name(), dds.get_version(),
293  dds.get_protocol());
294 
295  for (unsigned int i = 0; i < expr.size(); ++i) {
296  Clause *cp = expr[i];
297  BaseType *result;
298  if (cp->value(dds, &result)) {
299  fdds->add_var_nocopy(result);
300  }
301  else {
302  delete fdds;
303  throw Error("A function was called but failed to return a value.");
304  }
305  }
306 
307  return fdds;
308 }
309 
312 {
313  if (expr.empty())
314  return false;
315 
316  bool boolean = true;
317  for (Clause_iter i = expr.begin(); i != expr.end(); i++) {
318  boolean = boolean && (*i)->boolean_clause();
319  }
320 
321  return boolean;
322 }
323 
331 bool ConstraintEvaluator::eval_selection(DDS &dds, const string &)
332 {
333  if (expr.empty()) {
334  DBG(cerr << "No selection recorded" << endl);
335  return true;
336  }
337 
338  DBG(cerr << "Eval selection" << endl);
339 
340  // A CE is made up of zero or more clauses, each of which has a boolean
341  // value. The value of the CE is the logical AND of the clause
342  // values. See ConstraintEvaluator::clause::value(...) for information on logical ORs in
343  // CEs.
344  bool result = true;
345  for (Clause_iter i = expr.begin(); i != expr.end() && result; i++) {
346  // A selection expression *must* contain only boolean clauses!
347  if (!((*i)->boolean_clause()))
348  throw InternalErr(__FILE__, __LINE__, "A selection expression must contain only boolean clauses.");
349  result = result && (*i)->value(dds);
350  }
351 
352  return result;
353 }
354 
365 void ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
366 {
367  void *buffer = ce_expr_string(constraint.c_str());
368 
369  // Toggle this to debug the parser. A last resort...
370  ce_exprdebug = false;
371 
372  ce_expr_switch_to_buffer(buffer);
373 
374  ce_parser_arg arg(this, &dds);
375 
376  // For all errors, exprparse will throw Error.
377  try {
378  ce_exprparse(&arg);
379  ce_expr_delete_buffer(buffer);
380  }
381  catch (...) {
382  // Make sure to remove the buffer when there's an error
383  ce_expr_delete_buffer(buffer);
384  throw;
385  }
386 }
387 
388 } // namespace libdap
void ce_expr_delete_buffer(void *buffer)
static ServerFunctionsList * TheList()
std::vector< rvalue * > rvalue_list
Definition: RValue.h:67
bool boolean_expression()
Does the current constraint expression return a boolean value?
BaseType * eval_function(DDS &dds, const string &dataset)
Evaluate a function-valued constraint expression.
void parse_constraint(const string &constraint, DDS &dds)
Parse the constraint expression given the current DDS.
void add_var_nocopy(BaseType *bt)
Adds the variable to the DDS.
Definition: DDS.cc:583
void * ce_expr_string(const char *yy_str)
A class for software fault reporting.
Definition: InternalErr.h:64
bool eval_selection(DDS &dds, const string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator ans is called ...
bool value(DDS &dds)
Evaluate a clause which returns a boolean value This method must only be evaluated for clauses with r...
Definition: Clause.cc:157
int ce_exprdebug
#define DBG(x)
Definition: debug.h:58
DDS * eval_function_clauses(DDS &dds)
Evaluate a function-valued constraint expression that contains several function calls.
void ce_expr_switch_to_buffer(void *new_buffer)
string get_version() const
Get the server version string, unparsed.
Definition: DataDDS.h:109
std::vector< BaseType * >::iterator Constants_iter
BaseTypeFactory * get_factory() const
Definition: DDS.h:239
bool functional_expression()
Does the current constraint expression return a BaseType pointer? This method does not evaluate the c...
The basic data type for the DODS DAP types.
Definition: BaseType.h:199
void append_constant(BaseType *btp)
bool clause_value(Clause_iter &i, DDS &dds)
string get_protocol() const
Definition: DataDDS.h:129
Holds a fragment of a constraint expression.
Definition: Clause.h:90
bool function_clauses()
Does the current constraint expression contain function clauses.
A class for error processing.
Definition: Error.h:90
string get_dataset_name() const
Definition: DDS.cc:326
bool value_clause()
Return true if the clause returns a value in a BaseType pointer.
Definition: Clause.cc:139
std::vector< Clause * >::iterator Clause_iter
Holds a DAP2 DDS.
Definition: DataDDS.h:77
int ce_exprparse(libdap::ce_parser_arg *arg)
void append_clause(int op, rvalue *arg1, rvalue_list *arg2)
Add a clause to a constraint expression.
virtual bool find_function(const std::string &name, libdap::bool_func *f) const
bool find_function(const string &name, bool_func *f) const
Find a Boolean function with a given name in the function list.