libdap Updated for version 3.20.10
libdap4 is an implementation of OPeNDAP's DAP protocol.
ConstraintEvaluator.cc
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
39struct yy_buffer_state;
40
41int ce_exprparse(libdap::ce_parser_arg *arg);
42
43// Glue routines declared in expr.lex
44void ce_expr_switch_to_buffer(void *new_buffer);
45void ce_expr_delete_buffer(void * buffer);
46void *ce_expr_string(const char *yy_str);
47
48namespace libdap {
49
50ConstraintEvaluator::ConstraintEvaluator()
51{
52 // Functions are now held in BES modules. jhrg 1/30/13
53
54 // modules load functions to this list; this class searches the list
55 // instead of having it's own copy. This is very similar to the BES'
56 // various List classes, but this one is part of libdap and not the
57 // BES. The List class is a singleton, so each function module can
58 // register it's functions to the list object.
59 d_functions_list = ServerFunctionsList::TheList();
60}
61
62ConstraintEvaluator::~ConstraintEvaluator()
63{
64 // delete all the constants created by the parser for CE evaluation
65 for (Constants_iter j = constants.begin(); j != constants.end(); j++) {
66 BaseType *btp = *j;
67 delete btp;
68 btp = 0;
69 }
70
71 for (Clause_iter k = expr.begin(); k != expr.end(); k++) {
72 Clause *cp = *k;
73 delete cp;
74 cp = 0;
75 }
76}
77
79ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_begin()
80{
81 return expr.begin();
82}
83
86ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_end()
87{
88 return expr.end();
89}
90
93bool ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
94{
95 if (expr.empty())
96 throw InternalErr(__FILE__, __LINE__, "There are no CE clauses for *this* DDS object.");
97
98 return (*iter)->value(dds);
99}
100
113void ConstraintEvaluator::append_clause(int op, rvalue *arg1, rvalue_list *arg2)
114{
115 Clause *clause = new Clause(op, arg1, arg2);
116
117 expr.push_back(clause);
118}
119
129void ConstraintEvaluator::append_clause(bool_func func, rvalue_list *args)
130{
131 Clause *clause = new Clause(func, args);
132
133 expr.push_back(clause);
134}
135
145void ConstraintEvaluator::append_clause(btp_func func, rvalue_list *args)
146{
147 Clause *clause = new Clause(func, args);
148
149 expr.push_back(clause);
150}
151
160{
161 constants.push_back(btp);
162}
163
165bool ConstraintEvaluator::find_function(const string &name, bool_func *f) const
166{
167 return d_functions_list->find_function(name, f);
168}
169
171bool ConstraintEvaluator::find_function(const string &name, btp_func *f) const
172{
173 return d_functions_list->find_function(name, f);
174}
175
177bool ConstraintEvaluator::find_function(const string &name, proj_func *f) const
178{
179 return d_functions_list->find_function(name, f);
180}
182
192{
193 if (expr.empty())
194 return false;
195
196 Clause *cp = expr[0];
197 return cp->value_clause();
198}
199
203BaseType *
205{
206 if (expr.size() != 1)
207 throw InternalErr(__FILE__, __LINE__, "The length of the list of CE clauses is not 1.");
208
209 Clause *cp = expr[0];
210 BaseType *result;
211 if (cp->value(dds, &result))
212 return result;
213 else
214 return NULL;
215}
216
227{
228 if (expr.empty())
229 return false;
230
231 for (unsigned int i = 0; i < expr.size(); ++i) {
232 Clause *cp = expr[i];
233 if (!cp->value_clause())
234 return false;
235 }
236
237 return true;
238}
239
255DDS *
257{
258 if (expr.empty())
259 throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
260
261 DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
262 for (unsigned int i = 0; i < expr.size(); ++i) {
263 Clause *cp = expr[i];
264 BaseType *result;
265 if (cp->value(dds, &result)) {
266 // This is correct: The function must allocate the memory for the result
267 // variable. 11/30/12 jhrg
268 fdds->add_var_nocopy(result);
269 }
270 else {
271 delete fdds;
272 throw Error(internal_error, "A function was called but failed to return a value.");
273 }
274 }
275
276 return fdds;
277}
278
284DataDDS *
286{
287 if (expr.empty())
288 throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
289
290 DataDDS *fdds = new DataDDS(dds.get_factory(), "function_result_" + dds.get_dataset_name(), dds.get_version(),
291 dds.get_protocol());
292
293 for (unsigned int i = 0; i < expr.size(); ++i) {
294 Clause *cp = expr[i];
295 BaseType *result;
296 if (cp->value(dds, &result)) {
297 fdds->add_var_nocopy(result);
298 }
299 else {
300 delete fdds;
301 throw Error(internal_error, "A function was called but failed to return a value.");
302 }
303 }
304
305 return fdds;
306}
307
310{
311 if (expr.empty())
312 return false;
313
314 bool boolean = true;
315 for (Clause_iter i = expr.begin(); i != expr.end(); i++) {
316 boolean = boolean && (*i)->boolean_clause();
317 }
318
319 return boolean;
320}
321
329bool ConstraintEvaluator::eval_selection(DDS &dds, const string &)
330{
331 if (expr.empty()) {
332 DBG(cerr << "No selection recorded" << endl);
333 return true;
334 }
335
336 DBG(cerr << "Eval selection" << endl);
337
338 // A CE is made up of zero or more clauses, each of which has a boolean
339 // value. The value of the CE is the logical AND of the clause
340 // values. See ConstraintEvaluator::clause::value(...) for information on logical ORs in
341 // CEs.
342 bool result = true;
343 for (Clause_iter i = expr.begin(); i != expr.end() && result; i++) {
344 // A selection expression *must* contain only boolean clauses!
345 if (!((*i)->boolean_clause()))
346 throw InternalErr(__FILE__, __LINE__, "A selection expression must contain only boolean clauses.");
347 result = result && (*i)->value(dds);
348 }
349
350 return result;
351}
352
363void ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
364{
365 void *buffer = ce_expr_string(constraint.c_str());
366
367 ce_expr_switch_to_buffer(buffer);
368
369 ce_parser_arg arg(this, &dds);
370
371 // For all errors, exprparse will throw Error.
372 try {
373 ce_exprparse(&arg);
374 ce_expr_delete_buffer(buffer);
375 }
376 catch (...) {
377 // Make sure to remove the buffer when there's an error
378 ce_expr_delete_buffer(buffer);
379 throw;
380 }
381}
382
383} // namespace libdap
The basic data type for the DODS DAP types.
Definition BaseType.h:118
bool boolean_expression()
Does the current constraint expression return a boolean value?
bool eval_selection(DDS &dds, const std::string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator and is called ...
bool find_function(const std::string &name, bool_func *f) const
Find a Boolean function with a given name in the function list.
bool clause_value(Clause_iter &i, DDS &dds)
void parse_constraint(const std::string &constraint, DDS &dds)
Parse the constraint expression given the current DDS.
void append_clause(int op, rvalue *arg1, rvalue_list *arg2)
Add a clause to a constraint expression.
BaseType * eval_function(DDS &dds, const std::string &dataset)
Evaluate a function-valued constraint expression.
bool function_clauses()
Does the current constraint expression contain function clauses.
DDS * eval_function_clauses(DDS &dds)
Evaluate a function-valued constraint expression that contains several function calls.
bool functional_expression()
Does the current constraint expression return a BaseType pointer? This method does not evaluate the c...
string get_dataset_name() const
Definition DDS.cc:285
BaseTypeFactory * get_factory() const
Definition DDS.h:233
Holds a DAP2 DDS.
Definition DataDDS.h:78
string get_version() const
Get the server version string, unparsed.
Definition DataDDS.h:109
A class for error processing.
Definition Error.h:94
A class for software fault reporting.
Definition InternalErr.h:65
virtual bool find_function(const std::string &name, bool_func *f) const
Find a boolean function with a given name in the function list.
top level DAP object to house generic methods
Holds a fragment of a constraint expression.
Definition Clause.h:91