libdap  Updated for version 3.17.0
ConstraintEvaluator.cc
00001 // -*- mode: c++; c-basic-offset:4 -*-
00002 
00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00004 // Access Protocol.
00005 
00006 // Copyright (c) 2002,2003 OPeNDAP, Inc.
00007 // Author: James Gallagher <jgallagher@opendap.org>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022 //
00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00024 
00025 #include "config.h"
00026 
00027 //#define DODS_DEBUG
00028 
00029 #include "ServerFunctionsList.h"
00030 #include "ConstraintEvaluator.h"
00031 #include "Clause.h"
00032 #include "DataDDS.h"
00033 
00034 #include "ce_parser.h"
00035 #include "debug.h"
00036 #include "parser.h"
00037 #include "expr.h"
00038 
00039 struct yy_buffer_state;
00040 
00041 int ce_exprparse(libdap::ce_parser_arg *arg);
00042 
00043 // Glue routines declared in expr.lex
00044 void ce_expr_switch_to_buffer(void *new_buffer);
00045 void ce_expr_delete_buffer(void * buffer);
00046 void *ce_expr_string(const char *yy_str);
00047 
00048 extern int ce_exprdebug;
00049 
00050 namespace libdap {
00051 
00052 ConstraintEvaluator::ConstraintEvaluator()
00053 {
00054     // Functions are now held in BES modules. jhrg 1/30/13
00055 
00056     // modules load functions to this list; this class searches the list
00057     // instead of having it's own copy. This is very similar to the BES'
00058     // various List classes, but this one is part of libdap and not the
00059     // BES. The List class is a singleton, so each function module can
00060     // register it's functions to the list object.
00061     d_functions_list = ServerFunctionsList::TheList();
00062 }
00063 
00064 ConstraintEvaluator::~ConstraintEvaluator()
00065 {
00066     // delete all the constants created by the parser for CE evaluation
00067     for (Constants_iter j = constants.begin(); j != constants.end(); j++) {
00068         BaseType *btp = *j;
00069         delete btp;
00070         btp = 0;
00071     }
00072 
00073     for (Clause_iter k = expr.begin(); k != expr.end(); k++) {
00074         Clause *cp = *k;
00075         delete cp;
00076         cp = 0;
00077     }
00078 }
00079 
00081 ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_begin()
00082 {
00083     return expr.begin();
00084 }
00085 
00088 ConstraintEvaluator::Clause_iter ConstraintEvaluator::clause_end()
00089 {
00090     return expr.end();
00091 }
00092 
00095 bool ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
00096 {
00097     if (expr.empty())
00098         throw InternalErr(__FILE__, __LINE__, "There are no CE clauses for *this* DDS object.");
00099 
00100     return (*iter)->value(dds);
00101 }
00102 
00115 void ConstraintEvaluator::append_clause(int op, rvalue *arg1, rvalue_list *arg2)
00116 {
00117     Clause *clause = new Clause(op, arg1, arg2);
00118 
00119     expr.push_back(clause);
00120 }
00121 
00131 void ConstraintEvaluator::append_clause(bool_func func, rvalue_list *args)
00132 {
00133     Clause *clause = new Clause(func, args);
00134 
00135     expr.push_back(clause);
00136 }
00137 
00147 void ConstraintEvaluator::append_clause(btp_func func, rvalue_list *args)
00148 {
00149     Clause *clause = new Clause(func, args);
00150 
00151     expr.push_back(clause);
00152 }
00153 
00161 void ConstraintEvaluator::append_constant(BaseType *btp)
00162 {
00163     constants.push_back(btp);
00164 }
00165 
00167 bool ConstraintEvaluator::find_function(const string &name, bool_func *f) const
00168 {
00169     return d_functions_list->find_function(name, f);
00170 }
00171 
00173 bool ConstraintEvaluator::find_function(const string &name, btp_func *f) const
00174 {
00175     return d_functions_list->find_function(name, f);
00176 }
00177 
00179 bool ConstraintEvaluator::find_function(const string &name, proj_func *f) const
00180 {
00181     return d_functions_list->find_function(name, f);
00182 }
00184 
00193 bool ConstraintEvaluator::functional_expression()
00194 {
00195     if (expr.empty())
00196         return false;
00197 
00198     Clause *cp = expr[0];
00199     return cp->value_clause();
00200 }
00201 
00205 BaseType *
00206 ConstraintEvaluator::eval_function(DDS &dds, const string &)
00207 {
00208     if (expr.size() != 1)
00209         throw InternalErr(__FILE__, __LINE__, "The length of the list of CE clauses is not 1.");
00210 
00211     Clause *cp = expr[0];
00212     BaseType *result;
00213     if (cp->value(dds, &result))
00214         return result;
00215     else
00216         return NULL;
00217 }
00218 
00228 bool ConstraintEvaluator::function_clauses()
00229 {
00230     if (expr.empty())
00231         return false;
00232 
00233     for (unsigned int i = 0; i < expr.size(); ++i) {
00234         Clause *cp = expr[i];
00235         if (!cp->value_clause())
00236             return false;
00237     }
00238 
00239     return true;
00240 }
00241 
00257 DDS *
00258 ConstraintEvaluator::eval_function_clauses(DDS &dds)
00259 {
00260     if (expr.empty())
00261         throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
00262 
00263     DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
00264     for (unsigned int i = 0; i < expr.size(); ++i) {
00265         Clause *cp = expr[i];
00266         BaseType *result;
00267         if (cp->value(dds, &result)) {
00268             // This is correct: The function must allocate the memory for the result
00269             // variable. 11/30/12 jhrg
00270             fdds->add_var_nocopy(result);
00271         }
00272         else {
00273             delete fdds;
00274             throw Error(internal_error, "A function was called but failed to return a value.");
00275         }
00276     }
00277 
00278     return fdds;
00279 }
00280 
00286 DataDDS *
00287 ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
00288 {
00289     if (expr.empty())
00290         throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
00291 
00292     DataDDS *fdds = new DataDDS(dds.get_factory(), "function_result_" + dds.get_dataset_name(), dds.get_version(),
00293             dds.get_protocol());
00294 
00295     for (unsigned int i = 0; i < expr.size(); ++i) {
00296         Clause *cp = expr[i];
00297         BaseType *result;
00298         if (cp->value(dds, &result)) {
00299             fdds->add_var_nocopy(result);
00300         }
00301         else {
00302             delete fdds;
00303             throw Error(internal_error, "A function was called but failed to return a value.");
00304         }
00305     }
00306 
00307     return fdds;
00308 }
00309 
00311 bool ConstraintEvaluator::boolean_expression()
00312 {
00313     if (expr.empty())
00314         return false;
00315 
00316     bool boolean = true;
00317     for (Clause_iter i = expr.begin(); i != expr.end(); i++) {
00318         boolean = boolean && (*i)->boolean_clause();
00319     }
00320 
00321     return boolean;
00322 }
00323 
00331 bool ConstraintEvaluator::eval_selection(DDS &dds, const string &)
00332 {
00333     if (expr.empty()) {
00334         DBG(cerr << "No selection recorded" << endl);
00335         return true;
00336     }
00337 
00338     DBG(cerr << "Eval selection" << endl);
00339 
00340     // A CE is made up of zero or more clauses, each of which has a boolean
00341     // value. The value of the CE is the logical AND of the clause
00342     // values. See ConstraintEvaluator::clause::value(...) for information on logical ORs in
00343     // CEs.
00344     bool result = true;
00345     for (Clause_iter i = expr.begin(); i != expr.end() && result; i++) {
00346         // A selection expression *must* contain only boolean clauses!
00347         if (!((*i)->boolean_clause()))
00348             throw InternalErr(__FILE__, __LINE__, "A selection expression must contain only boolean clauses.");
00349         result = result && (*i)->value(dds);
00350     }
00351 
00352     return result;
00353 }
00354 
00365 void ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
00366 {
00367     void *buffer = ce_expr_string(constraint.c_str());
00368 
00369     // Toggle this to debug the parser. A last resort...
00370     ce_exprdebug = false;
00371 
00372     ce_expr_switch_to_buffer(buffer);
00373 
00374     ce_parser_arg arg(this, &dds);
00375 
00376     // For all errors, exprparse will throw Error.
00377     try {
00378         ce_exprparse(&arg);
00379         ce_expr_delete_buffer(buffer);
00380     }
00381     catch (...) {
00382         // Make sure to remove the buffer when there's an error
00383         ce_expr_delete_buffer(buffer);
00384         throw;
00385     }
00386 }
00387 
00388 } // namespace libdap