libdap++  Updated for version 3.11.7
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 #include "config.h"
26 
27 static char rcsid[] not_used = { "$Id: ConstraintEvaluator.cc 25915 2012-10-24 00:14:58Z jimg $" };
28 
29 //#define DODS_DEBUG
30 
31 #include "ConstraintEvaluator.h"
32 
33 //FIXME
34 #include "BaseType.h"
35 #include "Array.h"
36 #include "Grid.h"
37 
38 
39 #include "ce_functions.h"
40 #include "parser.h"
41 #include "ce_parser.h"
42 #include "debug.h"
43 
44 struct yy_buffer_state;
45 yy_buffer_state *ce_expr_scan_string(const char *str);
46 int ce_exprparse(void *arg);
47 
48 // Glue routines declared in expr.lex
49 void ce_expr_switch_to_buffer(void *new_buffer);
50 void ce_expr_delete_buffer(void * buffer);
51 void *ce_expr_string(const char *yy_str);
52 
53 namespace libdap {
54 
56 {
57  register_functions(*this);
58 }
59 
61 {
62  // delete all the constants created by the parser for CE evaluation
63  for (Constants_iter j = constants.begin(); j != constants.end(); j++) {
64  BaseType *btp = *j;
65  delete btp;
66  btp = 0;
67  }
68 
69  for (Clause_iter k = expr.begin(); k != expr.end(); k++) {
70  Clause *cp = *k;
71  delete cp;
72  cp = 0;
73  }
74 }
75 
78 {
79  return expr.begin();
80 }
81 
85 {
86  return expr.end();
87 }
88 
91 bool ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
92 {
93  if (expr.empty())
94  throw InternalErr(__FILE__, __LINE__, "There are no CE clauses for *this* DDS object.");
95 
96  return (*iter)->value(dds);
97 }
98 
112 {
113  Clause *clause = new Clause(op, arg1, arg2);
114 
115  expr.push_back(clause);
116 }
117 
128 {
129  Clause *clause = new Clause(func, args);
130 
131  expr.push_back(clause);
132 }
133 
144 {
145  Clause *clause = new Clause(func, args);
146 
147  expr.push_back(clause);
148 }
149 
158 {
159  constants.push_back(btp);
160 }
161 
162 class func_name_is {
163 private:
164  const string d_name;
165 
166 public:
167  func_name_is(const string &name) :
168  d_name(name)
169  {
170  }
171  bool operator()(const ConstraintEvaluator::function f)
172  {
173  return f.name == d_name;
174  }
175 };
176 
197 void ConstraintEvaluator::add_function(const string &name, bool_func f)
198 {
199  functions.remove_if(func_name_is(name));
200  function func(name, f);
201  functions.push_back(func);
202 }
203 
205 void ConstraintEvaluator::add_function(const string &name, btp_func f)
206 {
207  functions.remove_if(func_name_is(name));
208  function func(name, f);
209  functions.push_back(func);
210 }
211 
213 void ConstraintEvaluator::add_function(const string &name, proj_func f)
214 {
215  functions.remove_if(func_name_is(name));
216  function func(name, f);
217  functions.push_back(func);
218 }
219 
221 bool ConstraintEvaluator::find_function(const string &name, bool_func *f) const
222 {
223  if (functions.empty())
224  return false;
225 
226  for (Functions_citer i = functions.begin(); i != functions.end(); i++) {
227  if (name == (*i).name && (*f = (*i).b_func)) {
228  return true;
229  }
230  }
231 
232  return false;
233 }
234 
236 bool ConstraintEvaluator::find_function(const string &name, btp_func *f) const
237 {
238  if (functions.empty())
239  return false;
240 
241  for (Functions_citer i = functions.begin(); i != functions.end(); i++) {
242  if (name == (*i).name && (*f = (*i).bt_func)) {
243  return true;
244  }
245  }
246 
247  return false;
248 }
249 
251 bool ConstraintEvaluator::find_function(const string &name, proj_func *f) const
252 {
253  if (functions.empty())
254  return false;
255 
256  for (Functions_citer i = functions.begin(); i != functions.end(); i++)
257  if (name == (*i).name && (*f = (*i).p_func)) {
258  return true;
259  }
260 
261  return false;
262 }
264 
274 {
275  if (expr.empty())
276  return false;
277 
278  Clause *cp = expr[0];
279  return cp->value_clause();
280 }
281 
285 BaseType *
287 {
288  if (expr.size() != 1)
289  throw InternalErr(__FILE__, __LINE__, "The length of the list of CE clauses is not 1.");
290 
291  Clause *cp = expr[0];
292  BaseType *result;
293  if (cp->value(dds, &result))
294  return result;
295  else
296  return NULL;
297 }
298 
309 {
310  if (expr.empty())
311  return false;
312 
313  for (unsigned int i = 0; i < expr.size(); ++i) {
314  Clause *cp = expr[i];
315  if (!cp->value_clause())
316  return false;
317  }
318 
319  return true;
320 }
321 
337 DDS *
339 {
340  if (expr.empty())
341  throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
342 
343  DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
344  for (unsigned int i = 0; i < expr.size(); ++i) {
345  Clause *cp = expr[i];
346  BaseType *result;
347  if (cp->value(dds, &result)) {
348  // FIXME result->set_send_p(true);
349  // FIXME Check on using nocopy here
350  DBG(cerr << "In CE 1 Grid send_p: " << result->send_p() << endl);
351  DBG(cerr << "In CE 1 Grid Array send_p: " << static_cast<Grid*>(result)->get_array()->send_p() << endl);
352  fdds->add_var_nocopy(result);
353  }
354  else {
355  delete fdds;
356  throw Error("A function was called but failed to return a value.");
357  }
358  }
359 
360  return fdds;
361 }
362 
377 DataDDS *
379 {
380  if (expr.empty())
381  throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
382 
383  DataDDS *fdds = new DataDDS(dds.get_factory(), "function_result_" + dds.get_dataset_name(), dds.get_version(),
384  dds.get_protocol());
385 
386  for (unsigned int i = 0; i < expr.size(); ++i) {
387  Clause *cp = expr[i];
388  BaseType *result;
389  if (cp->value(dds, &result)) {
390  //result->set_send_p(true);
391  DBG(cerr << "In CE 2 Grid send_p: " << result->send_p() << endl);
392  DBG(cerr << "In CE 2 Grid Array send_p: " << static_cast<Grid*>(result)->get_array()->send_p() << endl);
393 
394  fdds->add_var_nocopy(result);
395  }
396  else {
397  delete fdds;
398  throw Error("A function was called but failed to return a value.");
399  }
400  }
401 
402  return fdds;
403 }
404 
407 {
408  if (expr.empty())
409  return false;
410 
411  bool boolean = true;
412  for (Clause_iter i = expr.begin(); i != expr.end(); i++) {
413  boolean = boolean && (*i)->boolean_clause();
414  }
415 
416  return boolean;
417 }
418 
426 bool ConstraintEvaluator::eval_selection(DDS &dds, const string &)
427 {
428  if (expr.empty()) {
429  DBG(cerr << "No selection recorded" << endl);
430  return true;
431  }
432 
433  DBG(cerr << "Eval selection" << endl);
434 
435  // A CE is made up of zero or more clauses, each of which has a boolean
436  // value. The value of the CE is the logical AND of the clause
437  // values. See ConstraintEvaluator::clause::value(...) for information on logical ORs in
438  // CEs.
439  bool result = true;
440  for (Clause_iter i = expr.begin(); i != expr.end() && result; i++) {
441  // A selection expression *must* contain only boolean clauses!
442  if (!((*i)->boolean_clause()))
443  throw InternalErr(__FILE__, __LINE__, "A selection expression must contain only boolean clauses.");
444  result = result && (*i)->value(dds);
445  }
446 
447  return result;
448 }
449 
460 void ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
461 {
462  void *buffer = ce_expr_string(constraint.c_str());
463  ce_expr_switch_to_buffer(buffer);
464 
465  ce_parser_arg arg(this, &dds);
466 
467  // For all errors, exprparse will throw Error.
468  ce_exprparse((void *) &arg);
469 
470  ce_expr_delete_buffer(buffer);
471 }
472 
473 } // namespace libdap