bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
GSEClause.cc
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 1999
27// Please read the full copyright statement in the file COPYRIGHT_URI.
28//
29// Authors:
30// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
31
32// The Grid Selection Expression Clause class.
33
34
35#include "config.h"
36
37#include <iostream>
38#include <sstream>
39
40#include <libdap/Array.h>
41#include <libdap/Grid.h>
42#include <libdap/D4Maps.h>
43#include <libdap/dods-datatypes.h>
44//#include <libdap/Error.h>
45//#include <libdap/InternalErr.h>
46#include <libdap/debug.h>
47
48#include "BESInternalError.h"
49
50#include "GSEClause.h"
51#include <libdap/parser.h>
52#include "gse.tab.hh"
53
54using namespace std;
55using namespace libdap;
56
57namespace functions {
58
59// For the comparisons here, we should use an epsilon to catch issues
60// with floating point values. jhrg 01/12/06
61template<class T>
62static bool
63compare(T elem, relop op, double value)
64{
65 switch (op) {
66 case dods_greater_op:
67 return elem > value;
68 case dods_greater_equal_op:
69 return elem >= value;
70 case dods_less_op:
71 return elem < value;
72 case dods_less_equal_op:
73 return elem <= value;
74 case dods_equal_op:
75 return elem == value;
76 case dods_not_equal_op:
77 return elem != value;
78 case dods_nop_op:
79 throw Error(malformed_expr, "Attempt to use NOP in Grid selection.");
80 default:
81 throw Error(malformed_expr, "Unknown relational operator in Grid selection.");
82 }
83}
84
85// These values are used in error messages, hence the strings.
86template<class T>
87void
88GSEClause::set_map_min_max_value(T min, T max)
89{
90 DBG(cerr << "Inside set map min max value " << min << ", " << max << endl);
91 std::ostringstream oss1;
92 oss1 << min;
93 d_map_min_value = oss1.str();
94
95 std::ostringstream oss2;
96 oss2 << max;
97 d_map_max_value = oss2.str();
98}
99
100// Read the map array, scan, set start and stop.
101//
102// I switched to vals.at(x) instead of vals[x] because sonar scan was
103// complaining about access beyond the end of memory. The 'at()' method
104// is much more complex, so if we can go back to the
105template<class T>
106void
107GSEClause::set_start_stop()
108{
109 vector<T> vals(d_map->length());
110 d_map->value(vals.data());
111
112 if (!((unsigned long)d_start < vals.size() && (unsigned long)d_stop < vals.size()))
113 throw BESInternalError("Access beyond the bounds of a Grid Map.", __FILE__, __LINE__);
114
115 // Set the map's max and min values for use in error messages (it's a lot
116 // easier to do here, now, than later... 9/20/2001 jhrg)
117 set_map_min_max_value<T>(vals[d_start], vals[d_stop]);
118
119 // Starting at the current start point in the map (initially index position
120 // zero), scan forward until the comparison is true. Set the new value
121 // of d_start to that location. Note that each clause applies to exactly
122 // one map. The 'i <= end' test keeps us from setting start _past_ the
123 // end ;-)
124 int i = d_start;
125 int end = d_stop;
126 while (i <= end && !compare<T>(vals[i], d_op1, d_value1))
127 ++i;
128 d_start = i;
129
130 // Now scan backward from the end. We scan all the way to the actual start,
131 // although it would probably work to stop at 'i >= d_start'.
132 i = end;
133 while (i >= 0 && !compare<T>(vals[i], d_op1, d_value1))
134 --i;
135 d_stop = i;
136
137 // Every clause must have one operator but the second is optional since
138 // the more complex form of a clause is optional. That is, the above two
139 // loops took care of constraints like 'x < 7' but we need the following
140 // for ones like '3 < x < 7'.
141 if (d_op2 != dods_nop_op) {
142 i = d_start;
143 end = d_stop;
144 while (i <= end && !compare<T>(vals[i], d_op2, d_value2))
145 ++i;
146
147 d_start = i;
148
149 i = end;
150 while (i >= 0 && !compare<T>(vals[i], d_op2, d_value2))
151 --i;
152
153 d_stop = i;
154 }
155}
156
157void
158GSEClause::compute_indices()
159{
160 switch (d_map->var()->type()) {
161 case dods_byte_c:
162 set_start_stop<dods_byte>();
163 break;
164 case dods_int16_c:
165 set_start_stop<dods_int16>();
166 break;
167 case dods_uint16_c:
168 set_start_stop<dods_uint16>();
169 break;
170 case dods_int32_c:
171 set_start_stop<dods_int32>();
172 break;
173 case dods_uint32_c:
174 set_start_stop<dods_uint32>();
175 break;
176 case dods_float32_c:
177 set_start_stop<dods_float32>();
178 break;
179 case dods_float64_c:
180 set_start_stop<dods_float64>();
181 break;
182 default:
183 throw Error(malformed_expr,
184 "Grid selection using non-numeric map vectors is not supported");
185 }
186
187}
188
189// Public methods
190
192GSEClause::GSEClause(Grid *grid, const string &map, const double value,
193 const relop op)
194 : d_map(0),
195 d_value1(value), d_value2(0), d_op1(op), d_op2(dods_nop_op),
196 d_map_min_value(""), d_map_max_value("")
197{
198 d_map = dynamic_cast<Array *>(grid->var(map));
199 if (!d_map)
200 throw Error(string("The map variable '") + map
201 + string("' does not exist in the grid '")
202 + grid->name() + string("'."));
203
204 DBG(cerr << d_map->toString());
205
206 // Initialize the start and stop indices.
207 Array::Dim_iter iter = d_map->dim_begin();
208 d_start = d_map->dimension_start(iter);
209 d_stop = d_map->dimension_stop(iter);
210
211 compute_indices();
212}
213
215GSEClause::GSEClause(Grid *grid, const string &map, const double value1,
216 const relop op1, const double value2, const relop op2)
217 : d_map(0),
218 d_value1(value1), d_value2(value2), d_op1(op1), d_op2(op2),
219 d_map_min_value(""), d_map_max_value("")
220{
221 d_map = dynamic_cast<Array *>(grid->var(map));
222 if (!d_map)
223 throw Error(string("The map variable '") + map
224 + string("' does not exist in the grid '")
225 + grid->name() + string("'."));
226
227 DBG(cerr << d_map->toString());
228
229 // Initialize the start and stop indices.
230 Array::Dim_iter iter = d_map->dim_begin();
231 d_start = d_map->dimension_start(iter);
232 d_stop = d_map->dimension_stop(iter);
233
234 compute_indices();
235}
236
238GSEClause::GSEClause(Array *coverage, const string &map, const double value, const relop op)
239 : d_map(0),
240 d_value1(value), d_value2(0), d_op1(op), d_op2(dods_nop_op),
241 d_map_min_value(""), d_map_max_value("")
242{
243 if (!coverage->is_dap2_grid())
244 throw Error(string("The grid function cannot be applied to the array variable '")
245 + coverage->name() + string("'."));
246
247 // Process the Map Arrays.
248 bool mapFound = false;
249 D4Maps *d4_maps = coverage->maps();
250 D4Maps::D4MapsIter miter = d4_maps->map_begin();
251 D4Maps::D4MapsIter end = d4_maps->map_end();
252 for (; miter != end; miter++) {
253 D4Map *d4_map = (*miter);
254 if (d4_map->name() == map) {
255 mapFound = true;
256 d_map = const_cast<Array *>(d4_map->array());
257 break;
258 }
259 }
260
261 if (!mapFound)
262 throw Error(string("The map variable '") + map
263 + string("' does not exist in the array '")
264 + coverage->name() + string("'."));
265
266 DBG(cerr << d_map->toString());
267
268 // Initialize the start and stop indices.
269 Array::Dim_iter iter = d_map->dim_begin();
270 d_start = d_map->dimension_start(iter);
271 d_stop = d_map->dimension_stop(iter);
272
273 compute_indices();
274}
275
277
278GSEClause::GSEClause(Array *coverage, const string &map, const double value1,
279 const relop op1, const double value2, const relop op2)
280 : d_map(0),
281 d_value1(value1), d_value2(value2), d_op1(op1), d_op2(op2),
282 d_map_min_value(""), d_map_max_value("")
283{
284
285 if (!coverage->is_dap2_grid())
286 throw Error(string("The grid function cannot be applied to the array variable '")
287 + coverage->name() + string("'."));
288
289 // Process the Map Arrays.
290 bool mapFound = false;
291 D4Maps *d4_maps = coverage->maps();
292 D4Maps::D4MapsIter miter = d4_maps->map_begin();
293 D4Maps::D4MapsIter end = d4_maps->map_end();
294 for (; miter != end; miter++) {
295 D4Map *d4_map = (*miter);
296 if (d4_map->name() == map) {
297 mapFound = true;
298 d_map = const_cast<Array *>(d4_map->array());
299 break;
300 }
301 }
302
303 if (!mapFound)
304 throw Error(string("The map variable '") + map
305 + string("' does not exist in the array '")
306 + coverage->name() + string("'."));
307
308 DBG(cerr << d_map->toString());
309
310 // Initialize the start and stop indices.
311 Array::Dim_iter iter = d_map->dim_begin();
312 d_start = d_map->dimension_start(iter);
313 d_stop = d_map->dimension_stop(iter);
314
315 compute_indices();
316}
317
318GSEClause::~GSEClause()
319{
320 delete d_map;
321}
322
325bool
327{
328 if (!d_map)
329 return false;
330
331 // More ...
332
333 return true;
334}
335
338Array *
340{
341 return d_map;
342}
343
348void
350{
351 d_map = map;
352}
353
356string
358{
359 return d_map->name();
360}
361
365int
367{
368 return d_start;
369}
370
373void
375{
376 d_start = start;
377}
378
382int
384{
385 DBG(cerr << "Returning stop index value of: " << d_stop << endl);
386 return d_stop;
387}
388
391void
393{
394 d_stop = stop;
395}
396
401string
403{
404 return d_map_min_value;
405}
406
411string
413{
414 return d_map_max_value;
415}
416
417} // namespace functions
418
string get_map_name() const
Get the name of the map variable constrained by this clause.
Definition GSEClause.cc:357
libdap::Array * get_map() const
Get a pointer to the map variable constrained by this clause.
Definition GSEClause.cc:339
void set_stop(int stop)
Set the stopping index.
Definition GSEClause.cc:392
int get_stop() const
Get the stopping index of the clause's map variable as constrained by this clause.
Definition GSEClause.cc:383
void set_start(int start)
Set the starting index.
Definition GSEClause.cc:374
string get_map_max_value() const
Get the maximum map vector value.
Definition GSEClause.cc:412
int get_start() const
Get the starting index of the clause's map variable as constrained by this clause.
Definition GSEClause.cc:366
string get_map_min_value() const
Get the minimum map vector value.
Definition GSEClause.cc:402
void set_map(libdap::Array *map)
Set the pointer to the map vector contrained by this clause.
Definition GSEClause.cc:349