bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
grid_utils.cc
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4// Access Protocol.
5
6// Copyright (c) 2002,2003 OPeNDAP, Inc.
7// Author: Nathan Potter <npotter@opendap.org>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24
25#include "config.h"
26
27#include <libdap/BaseType.h>
28#include <libdap/Structure.h>
29#include <libdap/Grid.h>
30#include <libdap/Array.h>
31#include <libdap/D4Maps.h>
32#include <libdap/D4Group.h>
33#include <libdap/DMR.h>
34#include <libdap/util.h>
35
36#include <BESDebug.h>
37
38#include "grid_utils.h"
39#include "gse_parser.h"
40#include "GSEClause.h"
41#include "GridGeoConstraint.h"
42
43using namespace libdap;
44
45int gse_parse(functions::gse_arg *arg);
46void gse_restart(FILE * in);
47
48// Glue routines declared in gse.lex
49void gse_delete_buffer(void *buffer);
50void *gse_string(const char *yy_str);
51
52namespace functions {
53
60void get_grids(BaseType *bt, vector<Grid *> *grids)
61{
62 switch (bt->type()) {
63
64 case dods_grid_c: {
65 // Yay! It's a Grid!
66 grids->push_back(static_cast<Grid*>(bt));
67 break;
68 }
69 case dods_structure_c: {
70 // It's an Structure - but of what? Check each variable in the Structure.
71 Structure &s = static_cast<Structure&>(*bt);
72 for (Structure::Vars_iter i = s.var_begin(); i != s.var_begin(); i++) {
73 get_grids(*i, grids);
74 }
75 break;
76 }
77 // Grids cannot be members of Array or Sequence in DAP2. jhrg 6/10/13
78 case dods_array_c:
79 case dods_sequence_c:
80 default:
81 break;
82 }
83}
84
91void get_grids(DDS &dds, vector<Grid *> *grids)
92{
93 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++) {
94 get_grids(*i, grids);
95 }
96}
97
107bool is_geo_grid(Grid *grid)
108{
109 try {
110 GridGeoConstraint gc(grid);
111 }
112 catch (Error *e) {
113 return false;
114 }
115
116 return true;
117}
118
119void parse_gse_expression(gse_arg *arg, BaseType *expr)
120{
121 gse_restart(0); // Restart the scanner.
122 void *cls = gse_string(extract_string_argument(expr).c_str());
123 // gse_switch_to_buffer(cls); // Get set to scan the string.
124 bool status = gse_parse(arg) == 0;
125 gse_delete_buffer(cls);
126 if (!status)
127 throw Error(malformed_expr, "Error parsing grid selection.");
128}
129
130static void apply_grid_selection_expr(Grid *grid, GSEClause *clause)
131{
132 // Basic plan: For each map, look at each clause and set start and stop
133 // to be the intersection of the ranges in those clauses.
134 Grid::Map_iter map_i = grid->map_begin();
135 while (map_i != grid->map_end() && (*map_i)->name() != clause->get_map_name())
136 ++map_i;
137
138 if (map_i == grid->map_end())
139 throw Error(malformed_expr,"The map vector '" + clause->get_map_name()
140 + "' is not in the grid '" + grid->name() + "'.");
141
142 // Use pointer arith & the rule that map order must match array dim order
143 Array::Dim_iter grid_dim = (grid->get_array()->dim_begin() + (map_i - grid->map_begin()));
144
145 Array *map = dynamic_cast < Array * >((*map_i));
146 if (!map)
147 throw InternalErr(__FILE__, __LINE__, "Expected an Array");
148 int start = max(map->dimension_start(map->dim_begin()), clause->get_start());
149 int stop = min(map->dimension_stop(map->dim_begin()), clause->get_stop());
150
151 if (start > stop) {
152 ostringstream msg;
153 msg
154 << "The expressions passed to grid() do not result in an inclusive \n"
155 << "subset of '" << clause->get_map_name()
156 << "'. The map's values range " << "from "
157 << clause->get_map_min_value() << " to "
158 << clause->get_map_max_value() << ".";
159 throw Error(malformed_expr,msg.str());
160 }
161
162 BESDEBUG("GeoGrid", "Setting constraint on " << map->name() << "[" << start << ":" << stop << "]" << endl);
163
164 // Stride is always one.
165 map->add_constraint(map->dim_begin(), start, 1, stop);
166 grid->get_array()->add_constraint(grid_dim, start, 1, stop);
167}
168
169void apply_grid_selection_expressions(Grid * grid, vector < GSEClause * >clauses)
170{
171 vector < GSEClause * >::iterator clause_i = clauses.begin();
172 while (clause_i != clauses.end())
173 apply_grid_selection_expr(grid, *clause_i++);
174
175 grid->set_read_p(false);
176}
177
184void get_coverages(BaseType *bt, vector<Array *> *coverages)
185{
186 switch (bt->type()) {
187
188 case dods_array_c: {
189 if ( static_cast<Array *>(bt)->is_dap2_grid() ) {
190 // Yay! It's a Grid!
191 coverages->push_back(static_cast<Array *>(bt));
192 }
193 break;
194 }
195 case dods_structure_c: {
196 // It's a Structure - but of what? Check each variable in the Structure.
197 Structure &s = static_cast<Structure&>(*bt);
198 for (Structure::Vars_iter i = s.var_begin(); i != s.var_begin(); i++) {
199 get_coverages(*i, coverages);
200 }
201 break;
202 }
203
204 case dods_group_c: {
205 // It's a Group - but of what? Check each variable in the Group.
206 D4Group &g = static_cast<D4Group&>(*bt);
207 for (D4Group::Vars_iter i = g.var_begin(); i != g.var_begin(); i++) {
208 get_coverages(*i, coverages);
209 }
210 break;
211 }
212
213 // Only an Array can be a Coverage in DAP4.
214 default:
215 break;
216 }
217}
218
225void get_coverages(DMR &dmr, vector<Array *> *coverages)
226{
227 D4Group *root = dmr.root();
228
229 // variables
230 Constructor::Vars_iter v = root->var_begin();
231 while (v != root->var_end()) {
232 get_coverages(*v, coverages);
233 ++v;
234 }
235 // groups
236 D4Group::groupsIter g = root->grp_begin();
237 while (g != root->grp_end())
238 get_coverages((*g++),coverages);
239}
240
241static void apply_grid_selection_expr(Array *coverage, GSEClause *clause)
242{
243 // Basic plan: For each map, look at each clause and set start and stop
244 // to be the intersection of the ranges in those clauses.
245 D4Maps *d4_maps = coverage->maps();
246 D4Maps::D4MapsIter miter = d4_maps->map_begin();
247 while (miter != d4_maps->map_end() && (*miter)->name() != clause->get_map()->FQN())
248 ++miter;
249
250 if (miter == d4_maps->map_end())
251 throw Error(malformed_expr,"The map vector '" + clause->get_map_name()
252 + "' is not in the array '" + coverage->name() + "'.");
253
254 D4Map *d4_map = (*miter);
255
256 // Use pointer arith & the rule that map order must match array dim order
257
258 Array::Dim_iter dim_i = coverage->dim_begin();
259 while (dim_i != coverage->dim_end() && coverage->dimension_D4dim(dim_i)->fully_qualified_name() != clause->get_map()->FQN())
260 ++dim_i;
261
262 if (dim_i == coverage->dim_end())
263 throw Error(malformed_expr,"The map vector '" + clause->get_map_name()
264 + "' is not a dimension in the array '" + coverage->name() + "'.");
265
266 Array::Dim_iter coverage_dim = (coverage->dim_begin() + (dim_i - coverage->dim_begin()));
267
268 Array *map = const_cast<Array *>(d4_map->array());
269 if (!map)
270 throw InternalErr(__FILE__, __LINE__, "Expected an Array");
271 int start = max(map->dimension_start(map->dim_begin()), clause->get_start());
272 int stop = min(map->dimension_stop(map->dim_begin()), clause->get_stop());
273
274 if (start > stop) {
275 ostringstream msg;
276 msg
277 << "The expressions passed to grid() do not result in an inclusive \n"
278 << "subset of '" << clause->get_map_name()
279 << "'. The map's values range " << "from "
280 << clause->get_map_min_value() << " to "
281 << clause->get_map_max_value() << ".";
282 throw Error(malformed_expr,msg.str());
283 }
284
285 BESDEBUG("GeoGrid", "Setting constraint on " << map->name() << "[" << start << ":" << stop << "]" << endl);
286
287 // Stride is always one.
288 map->add_constraint(map->dim_begin(), start, 1, stop);
289
290 coverage->dimension_D4dim(coverage_dim)->set_constraint(start, 1, stop);
291 coverage->add_constraint(coverage_dim,coverage->dimension_D4dim(coverage_dim));
292}
293
294void apply_grid_selection_expressions(Array * coverage, vector < GSEClause * >clauses)
295{
296 vector < GSEClause * >::iterator clause_i = clauses.begin();
297 while (clause_i != clauses.end())
298 apply_grid_selection_expr(coverage, *clause_i++);
299
300 coverage->set_read_p(false);
301}
302
303} //namespace libdap