libdap++ Updated for version 3.8.2

ConstraintEvaluator.cc

Go to the documentation of this file.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00024 
00025 #include "config.h"
00026 
00027 static char rcsid[] not_used =
00028     {"$Id: ConstraintEvaluator.cc 23555 2010-09-14 16:43:59Z jimg $"
00029     };
00030 
00031 #include "ConstraintEvaluator.h"
00032 
00033 #include "ce_functions.h"
00034 #include "parser.h"
00035 #include "ce_parser.h"
00036 #include "debug.h"
00037 
00038 struct yy_buffer_state;
00039 yy_buffer_state *ce_expr_scan_string(const char *str);
00040 int ce_exprparse(void *arg);
00041 
00042 // Glue routines declared in expr.lex
00043 void ce_expr_switch_to_buffer(void *new_buffer);
00044 void ce_expr_delete_buffer(void * buffer);
00045 void *ce_expr_string(const char *yy_str);
00046 
00047 namespace libdap {
00048 
00049 ConstraintEvaluator::ConstraintEvaluator()
00050 {
00051     register_functions(*this);
00052 }
00053 
00054 ConstraintEvaluator::~ConstraintEvaluator()
00055 {
00056     // delete all the constants created by the parser for CE evaluation
00057     for (Constants_iter j = constants.begin(); j != constants.end(); j++) {
00058         BaseType *btp = *j ;
00059         delete btp ; btp = 0;
00060     }
00061 
00062     for (Clause_iter k = expr.begin(); k != expr.end(); k++) {
00063         Clause *cp = *k ;
00064         delete cp ; cp = 0;
00065     }
00066 }
00067 
00069 ConstraintEvaluator::Clause_iter
00070 ConstraintEvaluator::clause_begin()
00071 {
00072     return expr.begin() ;
00073 }
00074 
00077 ConstraintEvaluator::Clause_iter
00078 ConstraintEvaluator::clause_end()
00079 {
00080     return expr.end() ;
00081 }
00082 
00085 bool
00086 ConstraintEvaluator::clause_value(Clause_iter &iter, DDS &dds/*, const string &***/)
00087 {
00088     if (expr.empty())
00089         throw InternalErr(__FILE__, __LINE__,
00090                           "There are no CE clauses for *this* DDS object.");
00091 
00092     return (*iter)->value(dds);
00093 }
00094 
00107 void
00108 ConstraintEvaluator::append_clause(int op, rvalue *arg1, rvalue_list *arg2)
00109 {
00110     Clause *clause = new Clause(op, arg1, arg2);
00111 
00112     expr.push_back(clause);
00113 }
00114 
00124 void
00125 ConstraintEvaluator::append_clause(bool_func func, rvalue_list *args)
00126 {
00127     Clause *clause = new Clause(func, args);
00128 
00129     expr.push_back(clause);
00130 }
00131 
00141 void
00142 ConstraintEvaluator::append_clause(btp_func func, rvalue_list *args)
00143 {
00144     Clause *clause = new Clause(func, args);
00145 
00146     expr.push_back(clause);
00147 }
00148 
00156 void
00157 ConstraintEvaluator::append_constant(BaseType *btp)
00158 {
00159     constants.push_back(btp);
00160 }
00161 
00162 class func_name_is
00163 {
00164 private:
00165     const string d_name;
00166 
00167 public:
00168     func_name_is(const string &name): d_name(name)
00169     {}
00170     bool operator()(const ConstraintEvaluator::function f)
00171     {
00172         return f.name == d_name;
00173     }
00174 };
00175 
00196 void
00197 ConstraintEvaluator::add_function(const string &name, bool_func f)
00198 {
00199     functions.remove_if(func_name_is(name));
00200     function func(name, f);
00201     functions.push_back(func);
00202 }
00203 
00205 void
00206 ConstraintEvaluator::add_function(const string &name, btp_func f)
00207 {
00208     functions.remove_if(func_name_is(name));
00209     function func(name, f);
00210     functions.push_back(func);
00211 }
00212 
00214 void
00215 ConstraintEvaluator::add_function(const string &name, proj_func f)
00216 {
00217     functions.remove_if(func_name_is(name));
00218     function func(name, f);
00219     functions.push_back(func);
00220 }
00221 
00223 bool
00224 ConstraintEvaluator::find_function(const string &name, bool_func *f) const
00225 {
00226     if (functions.empty())
00227         return false;
00228 
00229     for (Functions_citer i = functions.begin(); i != functions.end(); i++) {
00230         if (name == (*i).name && (*f = (*i).b_func)) {
00231             return true;
00232         }
00233     }
00234 
00235     return false;
00236 }
00237 
00239 bool
00240 ConstraintEvaluator::find_function(const string &name, btp_func *f) const
00241 {
00242     if (functions.empty())
00243         return false;
00244 
00245     for (Functions_citer i = functions.begin(); i != functions.end(); i++) {
00246         if (name == (*i).name && (*f = (*i).bt_func)) {
00247             return true;
00248         }
00249     }
00250 
00251     return false;
00252 }
00253 
00255 bool
00256 ConstraintEvaluator::find_function(const string &name, proj_func *f) const
00257 {
00258     if (functions.empty())
00259         return false;
00260 
00261     for (Functions_citer i = functions.begin(); i != functions.end(); i++)
00262         if (name == (*i).name && (*f = (*i).p_func)) {
00263             return true;
00264         }
00265 
00266     return false;
00267 }
00269 
00276 bool
00277 ConstraintEvaluator::functional_expression()
00278 {
00279     if (expr.empty())
00280         return false;
00281 
00282     Clause *cp = expr[0] ;
00283     return cp->value_clause();
00284 }
00285 
00287 BaseType *
00288 ConstraintEvaluator::eval_function(DDS &dds, const string &)
00289 {
00290     if (expr.size() != 1)
00291         throw InternalErr(__FILE__, __LINE__,
00292                           "The length of the list of CE clauses is not 1.");
00293 
00294     Clause *cp = expr[0] ;
00295     BaseType *result;
00296     if (cp->value(dds, &result))
00297         return result;
00298     else
00299         return NULL;
00300 }
00301 
00311 bool ConstraintEvaluator::function_clauses()
00312 {
00313     if (expr.empty())
00314         return false;
00315 
00316     for (unsigned int i = 0; i < expr.size(); ++i) {
00317         Clause *cp = expr[i];
00318         if (!cp->value_clause())
00319             return false;
00320     }
00321 
00322     return true;
00323 }
00324 
00340 DDS *
00341 ConstraintEvaluator::eval_function_clauses(DDS &dds)
00342 {
00343     if (expr.empty())
00344         throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
00345 
00346     DDS *fdds = new DDS(dds.get_factory(), "function_result_" + dds.get_dataset_name());
00347     for (unsigned int i = 0; i < expr.size(); ++i) {
00348         Clause *cp = expr[i];
00349         BaseType *result;
00350         if (cp->value(dds, &result)) {
00351             result->set_send_p(true);
00352             fdds->add_var(result);
00353         }
00354         else
00355             throw Error("A function was called but failed to return a value.");
00356     }
00357 
00358     return fdds;
00359 }
00360 
00366 DataDDS *
00367 ConstraintEvaluator::eval_function_clauses(DataDDS &dds)
00368 {
00369     if (expr.empty())
00370         throw InternalErr(__FILE__, __LINE__, "The constraint expression is empty.");
00371 
00372     DataDDS *fdds = new DataDDS(dds.get_factory(),
00373                                 "function_result_" + dds.get_dataset_name(),
00374                                 dds.get_version(), dds.get_protocol());
00375 
00376     for (unsigned int i = 0; i < expr.size(); ++i) {
00377         Clause *cp = expr[i];
00378         BaseType *result;
00379         if (cp->value(dds, &result)) {
00380             result->set_send_p(true);
00381             fdds->add_var(result);
00382         }
00383         else
00384             throw Error("A function was called but failed to return a value.");
00385     }
00386 
00387     return fdds;
00388 }
00389 
00391 bool
00392 ConstraintEvaluator::boolean_expression()
00393 {
00394     if (expr.empty())
00395         return false;
00396 
00397     bool boolean = true;
00398     for (Clause_iter i = expr.begin(); i != expr.end(); i++) {
00399         boolean = boolean && (*i)->boolean_clause();
00400     }
00401 
00402     return boolean;
00403 }
00404 
00405 
00413 bool
00414 ConstraintEvaluator::eval_selection(DDS &dds, const string &)
00415 {
00416     if (expr.empty()) {
00417         DBG(cerr << "No selection recorded" << endl);
00418         return true;
00419     }
00420 
00421     DBG(cerr << "Eval selection" << endl);
00422 
00423     // A CE is made up of zero or more clauses, each of which has a boolean
00424     // value. The value of the CE is the logical AND of the clause
00425     // values. See ConstraintEvaluator::clause::value(...) for information on logical ORs in
00426     // CEs.
00427     bool result = true;
00428     for (Clause_iter i = expr.begin(); i != expr.end() && result; i++) {
00429         // A selection expression *must* contain only boolean clauses!
00430         if (!((*i)->boolean_clause()))
00431             throw InternalErr(__FILE__, __LINE__,
00432                               "A selection expression must contain only boolean clauses.");
00433         result = result && (*i)->value(dds);
00434     }
00435 
00436     return result;
00437 }
00438 
00449 void
00450 ConstraintEvaluator::parse_constraint(const string &constraint, DDS &dds)
00451 {
00452     void *buffer = ce_expr_string(constraint.c_str());
00453     ce_expr_switch_to_buffer(buffer);
00454 
00455     ce_parser_arg arg(this, &dds);
00456 
00457     // For all errors, exprparse will throw Error.
00458     ce_exprparse((void *)&arg);
00459 
00460     ce_expr_delete_buffer(buffer);
00461 }
00462 
00463 } // namespace libdap