1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
5 // Access Protocol.
6 
7 // Copyright (c) 2002,2003 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 // (c) COPYRIGHT URI/MIT 1996,1998,1999
27 // Please first read the full copyright statement in the file COPYRIGHT_URI.
28 //
29 // Authors:
30 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
31 
32 // Implementation for the CE Clause class.
33 
34 
35 #include "config.h"
36 
37 #include "D4RValue.h"
38 #include "D4FilterClause.h"
39 
40 using namespace std;
41 
42 namespace libdap {
43 
44 void
m_duplicate(const D4FilterClauseList & src)45 D4FilterClauseList::m_duplicate(const D4FilterClauseList &src)
46 {
47     //D4FilterClauseList &non_c_src = const_cast<D4FilterClauseList &>(src);
48 
49     for (D4FilterClauseList::citer i = src.cbegin(), e = src.cend(); i != e; ++i) {
50         D4FilterClause *fc = *i;
51         d_clauses.push_back(new D4FilterClause(*fc));
52     }
53 }
54 
~D4FilterClauseList()55 D4FilterClauseList::~D4FilterClauseList()
56 {
57     for (D4FilterClauseList::iter i = d_clauses.begin(), e = d_clauses.end(); i != e; ++i) {
58         delete *i;
59     }
60 }
61 
62 /**
63  * @brief Evaluate the list of clauses
64  *
65  * Evaluate the list of clauses and return false when/if one is found to be false.
66  * This evaluates the clauses in the order they are stored and stops evaluation a
67  * the first false clause.
68  *
69  * @param dmr Use this DMR when evaluating clauses - for clauses that contain functions,
70  * not currently in the DAP4 specification.
71  * @return True if each of the clauses' value is true, otherwise false
72  */
73 bool
value(DMR & dmr)74 D4FilterClauseList::value(DMR &dmr)
75 {
76     for (D4FilterClauseList::iter i = d_clauses.begin(), e = d_clauses.end(); i != e; ++i) {
77         if ((*i)->value(dmr) == false)
78             return false;
79     }
80 
81     return true;
82 }
83 
84 /**
85  * @brief Evaluate the list of clauses
86  *
87  * This version of value() does not need a DMR parameter (but will not work
88  * if the clauses contain a function call (which is not currently supported
89  * by the spec).
90  *
91  * @return True if each clauses' value is true, false otherwise
92  * @see D4FilterClauseList::value(DMR &dmr)
93  */
94 bool
value()95 D4FilterClauseList::value()
96 {
97     for (D4FilterClauseList::iter i = d_clauses.begin(), e = d_clauses.end(); i != e; ++i) {
98         if ((*i)->value() == false)
99             return false;
100     }
101 
102     return true;
103 }
104 
m_duplicate(const D4FilterClause & rhs)105 void D4FilterClause::m_duplicate(const D4FilterClause &rhs) {
106     d_op = rhs.d_op;
107 
108     d_arg1 = new D4RValue(*rhs.d_arg1);
109     d_arg2 = new D4RValue(*rhs.d_arg2);
110 
111 #if 0
112     // Copy the D4RValue pointer if the 'value_kind' is a basetype,
113     // but build a new D4RValue if it is a constant (because the
114     // basetype is a weak pointer.
115     switch (rhs.d_arg1->get_kind()) {
116     case D4RValue::basetype:
117         d_arg1 = rhs.d_arg1;
118         break;
119     case D4RValue::constant:
120         d_arg1 = new D4RValue(*(rhs.d_arg1));
121         break;
122     default:
123         throw Error(malformed_expr, "found a filter clause with a function call.");
124     }
125 
126     switch (rhs.d_arg2->get_kind()) {
127     case D4RValue::basetype:
128         d_arg2 = rhs.d_arg2;
129         break;
130     case D4RValue::constant:
131         d_arg2 = new D4RValue(*(rhs.d_arg2));
132         break;
133     default:
134         throw Error(malformed_expr, "found a filter clause with a function call.");
135     }
136 #endif
137 }
138 
139 /**
140  * @brief Get the value of this relational expression.
141  * This version of value() works for function clauses, although that's
142  * not supported by the syntax at this time.
143  * @param dmr The DMR to use when evaluating a function
144  * @return True if the clause is true, false otherwise.
145  */
value(DMR & dmr)146 bool D4FilterClause::value(DMR &dmr)
147 {
148 	switch (d_op) {
149 	case null:
150 		throw InternalErr(__FILE__, __LINE__, "While evaluating a constraint filter clause: Found a null operator");
151 
152 	case less:
153 	case greater:
154 	case less_equal:
155 	case greater_equal:
156 	case equal:
157 	case not_equal:
158 	case match:
159 		return cmp(d_op, d_arg1->value(dmr), d_arg2->value(dmr));
160 
161 	case ND:
162 	case map:
163 		throw InternalErr(__FILE__, __LINE__, "While evaluating a constraint filter clause: Filter operator not implemented");
164 
165 	default:
166 		throw InternalErr(__FILE__, __LINE__, "While evaluating a constraint filter clause: Unrecognized operator");
167 	}
168 }
169 
170 /**
171  * @brief Get the value of this relational expression.
172  * This version of value() will not work for clauses where one of the
173  * rvalues is a function call. This is not currently supported by the
174  * DAP4 specification, so it's probably no great loss.
175  * @return True if the clause is true, false otherwise.
176  */
value()177 bool D4FilterClause::value()
178 {
179     switch (d_op) {
180     case null:
181         throw InternalErr(__FILE__, __LINE__, "While evaluating a constraint filter clause: Found a null operator");
182 
183     case less:
184     case greater:
185     case less_equal:
186     case greater_equal:
187     case equal:
188     case not_equal:
189     case match:
190         return cmp(d_op, d_arg1->value(), d_arg2->value());
191 
192     case ND:
193     case map:
194         throw InternalErr(__FILE__, __LINE__, "While evaluating a constraint filter clause: Filter operator not implemented");
195 
196     default:
197         throw InternalErr(__FILE__, __LINE__, "While evaluating a constraint filter clause: Unrecognized operator");
198     }
199 }
200 
201 // It may be better to use the code in the Byte, ..., classes that was
202 // impl'd for DAP2 (with extensions). For now, test this and build the
203 // rest of the filter implementation. But there is certainly a more _compact_
204 // way to code this!
205 //
206 // Optimize the extraction of constant values.
cmp(ops op,BaseType * arg1,BaseType * arg2)207 bool D4FilterClause::cmp(ops op, BaseType *arg1, BaseType *arg2)
208 {
209     return arg1->d4_ops(arg2, op);
210 }
211 
212 } // namespace libdap
213