libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
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 "Clause.h"
30#include "ConstraintEvaluator.h"
31#include "DataDDS.h"
32#include "ServerFunctionsList.h"
33
34#include "ce_parser.h"
35#include "debug.h"
36#include "expr.h"
37#include "parser.h"
38
39struct yy_buffer_state;
40
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
51 // Functions are now held in BES modules. jhrg 1/30/13
52
53 // modules load functions to this list; this class searches the list
54 // instead of having it's own copy. This is very similar to the BES'
55 // various List classes, but this one is part of libdap and not the
56 // BES. The List class is a singleton, so each function module can
57 // register it's functions to the list object.
58 d_functions_list = ServerFunctionsList::TheList();
59}
60
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
82
85bool ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds /*, const string &***/) {
86 if (expr.empty())
87 throw InternalErr(__FILE__, __LINE__, "There are no CE clauses for *this* DDS object.");
88
89 return (*iter)->value(dds);
90}
91
105 Clause *clause = new Clause(op, arg1, arg2);
106
107 expr.push_back(clause);
108}
109
120 Clause *clause = new Clause(func, args);
121
122 expr.push_back(clause);
123}
124
135 Clause *clause = new Clause(func, args);
136
137 expr.push_back(clause);
138}
139
147void ConstraintEvaluator::append_constant(BaseType *btp) { constants.push_back(btp); }
148
150bool ConstraintEvaluator::find_function(const string &name, bool_func *f) const {
151 return d_functions_list->find_function(name, f);
152}
153
155bool ConstraintEvaluator::find_function(const string &name, btp_func *f) const {
156 return d_functions_list->find_function(name, f);
157}
158
160bool ConstraintEvaluator::find_function(const string &name, proj_func *f) const {
161 return d_functions_list->find_function(name, f);
162}
163
164
174 if (expr.empty())
175 return false;
176
177 Clause *cp = expr[0];
178 return cp->value_clause();
179}
180
185 if (expr.size() != 1)
186 throw InternalErr(__FILE__, __LINE__, "The length of the list of CE clauses is not 1.");
187
188 Clause *cp = expr[0];
189 BaseType *result;
190 if (cp->value(dds, &result))
191 return result;
192 else
193 return NULL;
194}
195
206 if (expr.empty())
207 return false;
208
209 for (unsigned int i = 0; i < expr.size(); ++i) {
210 Clause *cp = expr[i];
211 if (!cp->value_clause())
212 return false;
213 }
214
215 return true;
216}
217
234 if (expr.empty())
235 throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
236
237 DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
238 for (unsigned int i = 0; i < expr.size(); ++i) {
239 Clause *cp = expr[i];
240 BaseType *result;
241 if (cp->value(dds, &result)) {
242 // This is correct: The function must allocate the memory for the result
243 // variable. 11/30/12 jhrg
244 fdds->add_var_nocopy(result);
245 } else {
246 delete fdds;
247 throw Error(internal_error, "A function was called but failed to return a value.");
248 }
249 }
250
251 return fdds;
252}
253
260 if (expr.empty())
261 throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
262
263 DataDDS *fdds = new DataDDS(dds.get_factory(), "function_result_" + dds.get_dataset_name(), dds.get_version(),
264 dds.get_protocol());
265
266 for (unsigned int i = 0; i < expr.size(); ++i) {
267 Clause *cp = expr[i];
268 BaseType *result;
269 if (cp->value(dds, &result)) {
270 fdds->add_var_nocopy(result);
271 } else {
272 delete fdds;
273 throw Error(internal_error, "A function was called but failed to return a value.");
274 }
275 }
276
277 return fdds;
278}
279
282 if (expr.empty())
283 return false;
284
285 bool boolean = true;
286 for (Clause_iter i = expr.begin(); i != expr.end(); i++) {
287 boolean = boolean && (*i)->boolean_clause();
288 }
289
290 return boolean;
291}
292
300bool ConstraintEvaluator::eval_selection(DDS &dds, const string &) {
301 if (expr.empty()) {
302 DBG(cerr << "No selection recorded" << endl);
303 return true;
304 }
305
306 DBG(cerr << "Eval selection" << endl);
307
308 // A CE is made up of zero or more clauses, each of which has a boolean
309 // value. The value of the CE is the logical AND of the clause
310 // values. See ConstraintEvaluator::clause::value(...) for information on logical ORs in
311 // CEs.
312 bool result = true;
313 for (Clause_iter i = expr.begin(); i != expr.end() && result; i++) {
314 // A selection expression *must* contain only boolean clauses!
315 if (!((*i)->boolean_clause()))
316 throw InternalErr(__FILE__, __LINE__, "A selection expression must contain only boolean clauses.");
317 result = result && (*i)->value(dds);
318 }
319
320 return result;
321}
322
333void ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds) {
334 void *buffer = ce_expr_string(constraint.c_str());
335
337
338 ce_parser_arg arg(this, &dds);
339
340 // For all errors, exprparse will throw Error.
341 try {
342 ce_exprparse(&arg);
343 ce_expr_delete_buffer(buffer);
344 } catch (...) {
345 // Make sure to remove the buffer when there's an error
346 ce_expr_delete_buffer(buffer);
347 throw;
348 }
349}
350
351} // namespace libdap
void * ce_expr_string(const char *yy_str)
void ce_expr_delete_buffer(void *buffer)
int ce_exprparse(libdap::ce_parser_arg *arg)
void ce_expr_switch_to_buffer(void *new_buffer)
#define internal_error
Internal server error (500)
Definition Error.h:63
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.
std::vector< BaseType * >::iterator Constants_iter
bool functional_expression()
Does the current constraint expression return a BaseType pointer? This method does not evaluate the c...
std::vector< Clause * >::iterator Clause_iter
void add_var_nocopy(BaseType *bt)
Adds the variable to the DDS.
Definition DDS.cc:504
string get_dataset_name() const
Definition DDS.cc:268
BaseTypeFactory * get_factory() const
Definition DDS.h:231
Holds a DAP2 DDS.
Definition DataDDS.h:76
string get_version() const
Get the server version string, unparsed.
Definition DataDDS.h:104
string get_protocol() const
Definition DataDDS.h:114
A class for error processing.
Definition Error.h:92
A class for software fault reporting.
Definition InternalErr.h:61
static ServerFunctionsList * TheList()
#define DBG(x)
Definition debug.h:58
top level DAP object to house generic methods
Definition AISConnect.cc:30
std::vector< rvalue * > rvalue_list
Definition RValue.h:69
Holds a fragment of a constraint expression.
Definition Clause.h:88
bool value_clause()
Return true if the clause returns a value in a BaseType pointer.
Definition Clause.cc:127
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:143