bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
GridFunction.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,2013 OPeNDAP, Inc.
8// Authors: Nathan Potter <npotter@opendap.org>
9// James Gallagher <jgallagher@opendap.org>
10//
11// This library is free software; you can redistribute it and/or
12// modify it under the terms of the GNU Lesser General Public
13// License as published by the Free Software Foundation; either
14// version 2.1 of the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24//
25// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26
27#include "config.h"
28
29#include <libdap/BaseType.h>
30#include <libdap/Str.h>
31#include <libdap/Array.h>
32#include <libdap/Grid.h>
33#include <libdap/D4Group.h>
34#include <libdap/D4RValue.h>
35#include <libdap/D4Maps.h>
36
37#include <libdap/Error.h>
38#include <libdap/DDS.h>
39#include <libdap/DMR.h>
40#include <libdap/debug.h>
41#include <libdap/util.h>
42
43#include <BESDebug.h>
44
45#include "GridFunction.h"
46#include "gse_parser.h"
47#include "grid_utils.h"
48
49using namespace libdap;
50
51namespace functions {
52
53 string grid_info =
54 string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
55 + "<function name=\"grid\" version=\"1.0b1\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#grid\">\n"
56 + "</function>";
57
58
88void
89function_dap2_grid(int argc, BaseType *argv[], DDS &, BaseType **btpp)
90{
91 DBG(cerr << "Entering function_grid..." << endl);
92 BESDEBUG("function", "function_dap2_grid() BEGIN " << endl);
93
94 if (argc == 0) {
95 Str *response = new Str("info");
96 response->set_value(grid_info);
97 *btpp = response;
98 return;
99 }
100
101 Grid *original_grid = dynamic_cast < Grid * >(argv[0]);
102 if (!original_grid)
103 throw Error(malformed_expr,"The first argument to grid() must be a Grid variable!");
104
105 // Duplicate the grid; ResponseBuilder::send_data() will delete the variable
106 // after serializing it.
107 BaseType *btp = original_grid->ptr_duplicate();
108 Grid *l_grid = dynamic_cast < Grid * >(btp);
109 if (!l_grid) {
110 delete btp;
111 throw InternalErr(__FILE__, __LINE__, "Expected a Grid.");
112 }
113
114 DBG(cerr << "grid: past initialization code" << endl);
115
116 // Read the maps. Do this before calling parse_gse_expression(). Avoid
117 // reading the array until the constraints have been applied because it
118 // might be large.
119
120 BESDEBUG("functions", "original_grid: read_p: " << original_grid->read_p() << endl);
121 BESDEBUG("functions", "l_grid: read_p: " << l_grid->read_p() << endl);
122
123 BESDEBUG("functions", "original_grid->array_(): read_p: " << original_grid->array_var()->read_p() << endl);
124 BESDEBUG("functions", "l_grid->array+var(): read_p: " << l_grid->array_var()->read_p() << endl);
125
126 // This version makes sure to set the send_p flags which is needed for
127 // the hdf4 handler (and is what should be done in general).
128 Grid::Map_iter i = l_grid->map_begin();
129 while (i != l_grid->map_end())
130 (*i++)->set_send_p(true);
131
132 l_grid->read();
133
134 DBG(cerr << "grid: past map read" << endl);
135
136 // argv[1..n] holds strings; each are little expressions to be parsed.
137 // When each expression is parsed, the parser makes a new instance of
138 // GSEClause. GSEClause checks to make sure the named map really exists
139 // in the Grid and that the range of values given makes sense.
140 vector < GSEClause * > clauses;
141 gse_arg *arg = new gse_arg(l_grid); // unique_ptr here
142 for (int i = 1; i < argc; ++i) {
143 parse_gse_expression(arg, argv[i]);
144 clauses.push_back(arg->get_gsec());
145 }
146 delete arg;
147 arg = 0;
148
149 apply_grid_selection_expressions(l_grid, clauses);
150
151 DBG(cerr << "grid: past gse application" << endl);
152
153 l_grid->get_array()->set_send_p(true);
154
155 l_grid->read();
156
157 // Make a new grid here and copy just the parts of the Grid
158 // that are in the current projection - this means reading
159 // the array slicing information, extracting the correct
160 // values and building destination arrays with just those
161 // values.
162
163 *btpp = l_grid;
164 return;
165}
166
173{
174 vector<Grid *> grids;
175 get_grids(dds, &grids);
176
177 return !grids.empty();
178}
179
180
210BaseType *function_dap4_grid(D4RValueList *args, DMR &dmr)
211{
212 BESDEBUG("function", "function_dap4_grid() BEGIN " << endl);
213
214 // DAP4 function porting information: in place of 'argc' use 'args.size()'
215 if (args == 0 || args->size() < 2) {
216 Str *response = new Str("info");
217 response->set_value(grid_info);
218 // DAP4 function porting: return a BaseType* instead of using the value-result parameter
219 return response;
220 }
221
222 BaseType *a_btp = args->get_rvalue(0)->value(dmr);
223 Array *original_array = dynamic_cast < Array * >(a_btp);
224 if (!original_array) {
225 delete a_btp;
226 throw InternalErr(__FILE__, __LINE__, "Expected an Array.");
227 }
228
229 // Duplicate the array; ResponseBuilder::send_data() will delete the variable
230 // after serializing it.
231 BaseType *btp = original_array->ptr_duplicate();
232 Array *l_array = dynamic_cast < Array * >(btp);
233 if (!l_array) {
234 delete btp;
235 throw InternalErr(__FILE__, __LINE__, "Expected an Array.");
236 }
237
238 DBG(cerr << "array: past initialization code" << endl);
239
240 // Read the maps. Do this before calling parse_gse_expression(). Avoid
241 // reading the array until the constraints have been applied because it
242 // might be large.
243
244 BESDEBUG("functions", "original_array: read_p: " << original_array->read_p() << endl);
245 BESDEBUG("functions", "l_array: read_p: " << l_array->read_p() << endl);
246
247 // Basic plan: For each map, set the send_p flag and read the map
248 D4Maps *d4_maps = l_array->maps();
249 D4Maps::D4MapsIter miter = d4_maps->map_begin();
250 while (miter != d4_maps->map_end()) {
251 D4Map *d4_map = (*miter);
252 Array *map = const_cast<Array *>(d4_map->array());
253 map->set_send_p(true);
254 map->read();
255 ++miter;
256 }
257
258 DBG(cerr << "array: past map read" << endl);
259
260 // argv[1..n] holds strings; each are little expressions to be parsed.
261 // When each expression is parsed, the parser makes a new instance of
262 // GSEClause. GSEClause checks to make sure the named map really exists
263 // in the Grid and that the range of values given makes sense.
264 vector < GSEClause * > clauses;
265 gse_arg *arg = new gse_arg(l_array); // unique_ptr here
266 for (unsigned int i = 1; i < args->size(); ++i) {
267 string relop = extract_string_argument(args->get_rvalue(i)->value(dmr));
268 parse_gse_expression(arg, args->get_rvalue(i)->value(dmr));
269 clauses.push_back(arg->get_gsec());
270 }
271 delete arg;
272 arg = 0;
273
274 apply_grid_selection_expressions(l_array, clauses);
275
276 DBG(cerr << "array: past gse application" << endl);
277
278 // Make a new array here and copy just the parts of the Array
279 // that are in the current projection - this means reading
280 // the array slicing information, extracting the correct
281 // values and building destination arrays with just those
282 // values.
283
284 // Build the return value(s) - this means make copies of the Map arrays
285 D4Group *dapResult = new D4Group("grid_result");
286
287 // Set this container's parent ot the root D4Group
288 dapResult->set_parent(dmr.root());
289
290 // Basic plan: Add the new array to the destination D4Group, and clear read_p flag.
291 l_array->set_read_p(false);
292 dapResult->add_var_nocopy(l_array);
293
294 // Basic plan: Add D4Dimensions to the destination D4Group; copy all dims to the parent group.
295 D4Dimensions *grp_d4_dims = dapResult->dims();
296
297 Array *g_array = dynamic_cast<Array *>(dapResult->find_var(l_array->name()));
298 // Basic plan: For each D4Dimension in the array, add it to the destination D4Group
299 Array::Dim_iter dim_i = g_array->dim_begin();
300 while (dim_i != g_array->dim_end()) {
301 D4Dimension *d4_dim = g_array->dimension_D4dim(dim_i);
302 grp_d4_dims->add_dim_nocopy(d4_dim);
303 ++dim_i;
304 }
305
306 // Basic plan: For each map in the array, add it to the destination structure and clear the read_p flag
307 d4_maps = l_array->maps();
308 miter = d4_maps->map_begin();
309 while (miter != d4_maps->map_end()) {
310 D4Map *d4_map = (*miter);
311 Array *map = const_cast<Array *>(d4_map->array());
312 map->set_read_p(false);
313 dapResult->add_var_nocopy(map);
314 ++miter;
315 }
316
317 // Basic plan: Mark the Structure for sending and read the data.
318 dapResult->set_send_p(true);
319 dapResult->read();
320
321 return dapResult;
322}
323
330{
331 vector<Array *> coverages;
332 get_coverages(dmr, &coverages);
333
334 return !coverages.empty();
335}
336
337} // namespace functions
bool canOperateOn(libdap::DDS &dds)
STL class.