ConstraintEvaluator.cc
// -*- mode: c++; c-basic-offset:4 -*-
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.
// Copyright (c) 2002,2003 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
#include "config.h"
//#define DODS_DEBUG
#include "ServerFunctionsList.h"
#include "ConstraintEvaluator.h"
#include "Clause.h"
#include "DataDDS.h"
#include "ce_parser.h"
#include "debug.h"
#include "parser.h"
#include "expr.h"
struct yy_buffer_state;
int ce_exprparse(libdap::ce_parser_arg *arg);
// Glue routines declared in expr.lex
void ce_expr_switch_to_buffer(void *new_buffer);
void ce_expr_delete_buffer(void * buffer);
void *ce_expr_string(const char *yy_str);
extern int ce_exprdebug;
namespace libdap {
ConstraintEvaluator::ConstraintEvaluator()
{
// Functions are now held in BES modules. jhrg 1/30/13
// modules load functions to this list; this class searches the list
// instead of having it's own copy. This is very similar to the BES'
// various List classes, but this one is part of libdap and not the
// BES. The List class is a singleton, so each function module can
// register it's functions to the list object.
d_functions_list = ServerFunctionsList::TheList();
}
ConstraintEvaluator::~ConstraintEvaluator()
{
// delete all the constants created by the parser for CE evaluation
for (Constants_iter j = constants.begin(); j != constants.end(); j++) {
BaseType *btp = *j;
delete btp;
btp = 0;
}
for (Clause_iter k = expr.begin(); k != expr.end(); k++) {
Clause *cp = *k;
delete cp;
cp = 0;
}
}
ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_begin()
{
return expr.begin();
}
ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_end()
{
return expr.end();
}
bool ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
{
if (expr.empty())
throw InternalErr(__FILE__, __LINE__, "There are no CE clauses for *this* DDS object.");
return (*iter)->value(dds);
}
void ConstraintEvaluator::append_clause(int op, rvalue *arg1, rvalue_list *arg2)
{
Clause *clause = new Clause(op, arg1, arg2);
expr.push_back(clause);
}
void ConstraintEvaluator::append_clause(bool_func func, rvalue_list *args)
{
Clause *clause = new Clause(func, args);
expr.push_back(clause);
}
void ConstraintEvaluator::append_clause(btp_func func, rvalue_list *args)
{
Clause *clause = new Clause(func, args);
expr.push_back(clause);
}
void ConstraintEvaluator::append_constant(BaseType *btp)
{
constants.push_back(btp);
}
bool ConstraintEvaluator::find_function(const string &name, bool_func *f) const
{
return d_functions_list->find_function(name, f);
}
bool ConstraintEvaluator::find_function(const string &name, btp_func *f) const
{
return d_functions_list->find_function(name, f);
}
bool ConstraintEvaluator::find_function(const string &name, proj_func *f) const
{
return d_functions_list->find_function(name, f);
}
bool ConstraintEvaluator::functional_expression()
{
if (expr.empty())
return false;
Clause *cp = expr[0];
return cp->value_clause();
}
BaseType *
ConstraintEvaluator::eval_function(DDS &dds, const string &)
{
if (expr.size() != 1)
throw InternalErr(__FILE__, __LINE__, "The length of the list of CE clauses is not 1.");
Clause *cp = expr[0];
BaseType *result;
if (cp->value(dds, &result))
return result;
else
return NULL;
}
bool ConstraintEvaluator::function_clauses()
{
if (expr.empty())
return false;
for (unsigned int i = 0; i < expr.size(); ++i) {
Clause *cp = expr[i];
if (!cp->value_clause())
return false;
}
return true;
}
DDS *
ConstraintEvaluator::eval_function_clauses(DDS &dds)
{
if (expr.empty())
throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
for (unsigned int i = 0; i < expr.size(); ++i) {
Clause *cp = expr[i];
BaseType *result;
if (cp->value(dds, &result)) {
// This is correct: The function must allocate the memory for the result
// variable. 11/30/12 jhrg
fdds->add_var_nocopy(result);
}
else {
delete fdds;
throw Error(internal_error, "A function was called but failed to return a value.");
}
}
return fdds;
}
DataDDS *
ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
{
if (expr.empty())
throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
DataDDS *fdds = new DataDDS(dds.get_factory(), "function_result_" + dds.get_dataset_name(), dds.get_version(),
dds.get_protocol());
for (unsigned int i = 0; i < expr.size(); ++i) {
Clause *cp = expr[i];
BaseType *result;
if (cp->value(dds, &result)) {
fdds->add_var_nocopy(result);
}
else {
delete fdds;
throw Error(internal_error, "A function was called but failed to return a value.");
}
}
return fdds;
}
bool ConstraintEvaluator::boolean_expression()
{
if (expr.empty())
return false;
bool boolean = true;
for (Clause_iter i = expr.begin(); i != expr.end(); i++) {
boolean = boolean && (*i)->boolean_clause();
}
return boolean;
}
bool ConstraintEvaluator::eval_selection(DDS &dds, const string &)
{
if (expr.empty()) {
DBG(cerr << "No selection recorded" << endl);
return true;
}
DBG(cerr << "Eval selection" << endl);
// A CE is made up of zero or more clauses, each of which has a boolean
// value. The value of the CE is the logical AND of the clause
// values. See ConstraintEvaluator::clause::value(...) for information on logical ORs in
// CEs.
bool result = true;
for (Clause_iter i = expr.begin(); i != expr.end() && result; i++) {
// A selection expression *must* contain only boolean clauses!
if (!((*i)->boolean_clause()))
throw InternalErr(__FILE__, __LINE__, "A selection expression must contain only boolean clauses.");
result = result && (*i)->value(dds);
}
return result;
}
void ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
{
void *buffer = ce_expr_string(constraint.c_str());
// Toggle this to debug the parser. A last resort...
ce_exprdebug = false;
ce_expr_switch_to_buffer(buffer);
ce_parser_arg arg(this, &dds);
// For all errors, exprparse will throw Error.
try {
ce_exprparse(&arg);
ce_expr_delete_buffer(buffer);
}
catch (...) {
// Make sure to remove the buffer when there's an error
ce_expr_delete_buffer(buffer);
throw;
}
}
} // namespace libdap
libdap::ConstraintEvaluator::find_function
bool find_function(const std::string &name, bool_func *f) const
Find a Boolean function with a given name in the function list.
Definition: ConstraintEvaluator.cc:167
libdap::rvalue
Definition: RValue.h:46
libdap::ServerFunctionsList::find_function
virtual bool find_function(const std::string &name, bool_func *f) const
Find a boolean function with a given name in the function list.
Definition: ServerFunctionsList.cc:129
libdap::Error
A class for error processing.
Definition: Error.h:92
libdap::InternalErr
A class for software fault reporting.
Definition: InternalErr.h:64
libdap::ConstraintEvaluator::eval_function
BaseType * eval_function(DDS &dds, const std::string &dataset)
Evaluate a function-valued constraint expression.
Definition: ConstraintEvaluator.cc:206
libdap::ConstraintEvaluator::clause_end
Clause_iter clause_end()
Definition: ConstraintEvaluator.cc:88
libdap::DataDDS
Holds a DAP2 DDS.
Definition: DataDDS.h:77
libdap
top level DAP object to house generic methods
Definition: AlarmHandler.h:35
libdap::DDS::add_var_nocopy
void add_var_nocopy(BaseType *bt)
Adds the variable to the DDS.
Definition: DDS.cc:613
libdap::Clause::value
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
libdap::ConstraintEvaluator::eval_function_clauses
DDS * eval_function_clauses(DDS &dds)
Evaluate a function-valued constraint expression that contains several function calls.
Definition: ConstraintEvaluator.cc:258
libdap::ConstraintEvaluator::clause_begin
Clause_iter clause_begin()
Definition: ConstraintEvaluator.cc:81
libdap::Clause
Holds a fragment of a constraint expression.
Definition: Clause.h:90
libdap::DDS::get_factory
BaseTypeFactory * get_factory() const
Definition: DDS.h:242
libdap::ConstraintEvaluator::eval_selection
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 ...
Definition: ConstraintEvaluator.cc:331
libdap::ConstraintEvaluator::functional_expression
bool functional_expression()
Does the current constraint expression return a BaseType pointer? This method does not evaluate the c...
Definition: ConstraintEvaluator.cc:193
libdap::DDS::get_dataset_name
string get_dataset_name() const
Definition: DDS.cc:356
libdap::ce_parser_arg
Definition: ce_parser.h:8
libdap::DataDDS::get_version
string get_version() const
Get the server version string, unparsed.
Definition: DataDDS.h:109
libdap::ConstraintEvaluator::parse_constraint
void parse_constraint(const std::string &constraint, DDS &dds)
Parse the constraint expression given the current DDS.
Definition: ConstraintEvaluator.cc:365
libdap::DDS
Definition: DDS.h:183
libdap::ConstraintEvaluator::function_clauses
bool function_clauses()
Does the current constraint expression contain function clauses.
Definition: ConstraintEvaluator.cc:228
libdap::ConstraintEvaluator::append_constant
void append_constant(BaseType *btp)
Definition: ConstraintEvaluator.cc:161
libdap::BaseType
The basic data type for the DODS DAP types.
Definition: BaseType.h:117
libdap::Clause::value_clause
bool value_clause()
Return true if the clause returns a value in a BaseType pointer.
Definition: Clause.cc:139
libdap::ConstraintEvaluator::clause_value
bool clause_value(Clause_iter &i, DDS &dds)
Definition: ConstraintEvaluator.cc:95
libdap::ConstraintEvaluator::boolean_expression
bool boolean_expression()
Does the current constraint expression return a boolean value?
Definition: ConstraintEvaluator.cc:311
libdap::ConstraintEvaluator::append_clause
void append_clause(int op, rvalue *arg1, rvalue_list *arg2)
Add a clause to a constraint expression.
Definition: ConstraintEvaluator.cc:115