libdap++  Updated for version 3.8.2
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 =
28  {"$Id: ConstraintEvaluator.cc 24370 2011-03-28 16:21:32Z jimg $"
29  };
30 
31 #include "ConstraintEvaluator.h"
32 
33 #include "ce_functions.h"
34 #include "parser.h"
35 #include "ce_parser.h"
36 #include "debug.h"
37 
38 struct yy_buffer_state;
39 yy_buffer_state *ce_expr_scan_string(const char *str);
40 int ce_exprparse(void *arg);
41 
42 // Glue routines declared in expr.lex
43 void ce_expr_switch_to_buffer(void *new_buffer);
44 void ce_expr_delete_buffer(void * buffer);
45 void *ce_expr_string(const char *yy_str);
46 
47 namespace libdap {
48 
50 {
51  register_functions(*this);
52 }
53 
55 {
56  // delete all the constants created by the parser for CE evaluation
57  for (Constants_iter j = constants.begin(); j != constants.end(); j++) {
58  BaseType *btp = *j ;
59  delete btp ; btp = 0;
60  }
61 
62  for (Clause_iter k = expr.begin(); k != expr.end(); k++) {
63  Clause *cp = *k ;
64  delete cp ; cp = 0;
65  }
66 }
67 
71 {
72  return expr.begin() ;
73 }
74 
79 {
80  return expr.end() ;
81 }
82 
85 bool
86 ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
87 {
88  if (expr.empty())
89  throw InternalErr(__FILE__, __LINE__,
90  "There are no CE clauses for *this* DDS object.");
91 
92  return (*iter)->value(dds);
93 }
94 
107 void
109 {
110  Clause *clause = new Clause(op, arg1, arg2);
111 
112  expr.push_back(clause);
113 }
114 
124 void
126 {
127  Clause *clause = new Clause(func, args);
128 
129  expr.push_back(clause);
130 }
131 
141 void
143 {
144  Clause *clause = new Clause(func, args);
145 
146  expr.push_back(clause);
147 }
148 
156 void
158 {
159  constants.push_back(btp);
160 }
161 
162 class func_name_is
163 {
164 private:
165  const string d_name;
166 
167 public:
168  func_name_is(const string &name): d_name(name)
169  {}
170  bool operator()(const ConstraintEvaluator::function f)
171  {
172  return f.name == d_name;
173  }
174 };
175 
196 void
197 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
206 ConstraintEvaluator::add_function(const string &name, btp_func f)
207 {
208  functions.remove_if(func_name_is(name));
209  function func(name, f);
210  functions.push_back(func);
211 }
212 
214 void
215 ConstraintEvaluator::add_function(const string &name, proj_func f)
216 {
217  functions.remove_if(func_name_is(name));
218  function func(name, f);
219  functions.push_back(func);
220 }
221 
223 bool
224 ConstraintEvaluator::find_function(const string &name, bool_func *f) const
225 {
226  if (functions.empty())
227  return false;
228 
229  for (Functions_citer i = functions.begin(); i != functions.end(); i++) {
230  if (name == (*i).name && (*f = (*i).b_func)) {
231  return true;
232  }
233  }
234 
235  return false;
236 }
237 
239 bool
240 ConstraintEvaluator::find_function(const string &name, btp_func *f) const
241 {
242  if (functions.empty())
243  return false;
244 
245  for (Functions_citer i = functions.begin(); i != functions.end(); i++) {
246  if (name == (*i).name && (*f = (*i).bt_func)) {
247  return true;
248  }
249  }
250 
251  return false;
252 }
253 
255 bool
256 ConstraintEvaluator::find_function(const string &name, proj_func *f) const
257 {
258  if (functions.empty())
259  return false;
260 
261  for (Functions_citer i = functions.begin(); i != functions.end(); i++)
262  if (name == (*i).name && (*f = (*i).p_func)) {
263  return true;
264  }
265 
266  return false;
267 }
269 
276 bool
278 {
279  if (expr.empty())
280  return false;
281 
282  Clause *cp = expr[0] ;
283  return cp->value_clause();
284 }
285 
287 BaseType *
289 {
290  if (expr.size() != 1)
291  throw InternalErr(__FILE__, __LINE__,
292  "The length of the list of CE clauses is not 1.");
293 
294  Clause *cp = expr[0] ;
295  BaseType *result;
296  if (cp->value(dds, &result))
297  return result;
298  else
299  return NULL;
300 }
301 
312 {
313  if (expr.empty())
314  return false;
315 
316  for (unsigned int i = 0; i < expr.size(); ++i) {
317  Clause *cp = expr[i];
318  if (!cp->value_clause())
319  return false;
320  }
321 
322  return true;
323 }
324 
340 DDS *
342 {
343  if (expr.empty())
344  throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
345 
346  DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
347  for (unsigned int i = 0; i < expr.size(); ++i) {
348  Clause *cp = expr[i];
349  BaseType *result;
350  if (cp->value(dds, &result)) {
351  result->set_send_p(true);
352  fdds->add_var(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 
368 DataDDS *
370 {
371  if (expr.empty())
372  throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
373 
374  DataDDS *fdds = new DataDDS(dds.get_factory(),
375  "function_result_" + dds.get_dataset_name(),
376  dds.get_version(), dds.get_protocol());
377 
378  for (unsigned int i = 0; i < expr.size(); ++i) {
379  Clause *cp = expr[i];
380  BaseType *result;
381  if (cp->value(dds, &result)) {
382  result->set_send_p(true);
383  fdds->add_var(result);
384  }
385  else {
386  delete fdds;
387  throw Error("A function was called but failed to return a value.");
388  }
389  }
390 
391  return fdds;
392 }
393 
395 bool
397 {
398  if (expr.empty())
399  return false;
400 
401  bool boolean = true;
402  for (Clause_iter i = expr.begin(); i != expr.end(); i++) {
403  boolean = boolean && (*i)->boolean_clause();
404  }
405 
406  return boolean;
407 }
408 
409 
417 bool
419 {
420  if (expr.empty()) {
421  DBG(cerr << "No selection recorded" << endl);
422  return true;
423  }
424 
425  DBG(cerr << "Eval selection" << endl);
426 
427  // A CE is made up of zero or more clauses, each of which has a boolean
428  // value. The value of the CE is the logical AND of the clause
429  // values. See ConstraintEvaluator::clause::value(...) for information on logical ORs in
430  // CEs.
431  bool result = true;
432  for (Clause_iter i = expr.begin(); i != expr.end() && result; i++) {
433  // A selection expression *must* contain only boolean clauses!
434  if (!((*i)->boolean_clause()))
435  throw InternalErr(__FILE__, __LINE__,
436  "A selection expression must contain only boolean clauses.");
437  result = result && (*i)->value(dds);
438  }
439 
440  return result;
441 }
442 
453 void
454 ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
455 {
456  void *buffer = ce_expr_string(constraint.c_str());
457  ce_expr_switch_to_buffer(buffer);
458 
459  ce_parser_arg arg(this, &dds);
460 
461  // For all errors, exprparse will throw Error.
462  ce_exprparse((void *)&arg);
463 
464  ce_expr_delete_buffer(buffer);
465 }
466 
467 } // namespace libdap