OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
NCStructure.cc
Go to the documentation of this file.
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of nc_handler, a data handler for the OPeNDAP data
5 // server.
6 
7 // Copyright (c) 2002,2003 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This is free software; you can redistribute it and/or modify it under the
11 // terms of the GNU Lesser General Public License as published by the Free
12 // Software Foundation; either version 2.1 of the License, or (at your
13 // option) any later version.
14 //
15 // This software is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 // 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 
27 // (c) COPYRIGHT URI/MIT 1994-1996
28 // Please read the full copyright statement in the file COPYRIGHT.
29 //
30 // Authors:
31 // reza Reza Nekovei (reza@intcomm.net)
32 
33 // netCDF sub-class implementation for NCByte,...NCGrid.
34 // The files are patterned after the subcalssing examples
35 // Test<type>.c,h files.
36 //
37 // ReZa 1/12/95
38 
39 #include "config_nc.h"
40 
41 static char rcsid[] not_used ={"$Id$"};
42 
43 #include <vector>
44 #include <algorithm>
45 
46 #include <netcdf.h>
47 
48 #include <D4Attributes.h>
49 #include <util.h>
50 #include <InternalErr.h>
51 
52 #include "nc_util.h"
53 #include "NCStructure.h"
54 #include "NCArray.h"
55 
56 BaseType *
58 {
59  return new NCStructure(*this);
60 }
61 
62 NCStructure::NCStructure(const string &n, const string &d) : Structure(n, d)
63 {
64 }
65 
66 NCStructure::NCStructure(const NCStructure &rhs) : Structure(rhs)
67 {
68 }
69 
71 {
72 }
73 
76 {
77  if (this == &rhs)
78  return *this;
79 
80  dynamic_cast<Structure&>(*this) = rhs; // run Structure assignment
81 
82  return *this;
83 }
84 
88 class AddAttribute: public unary_function<BaseType *, void> {
89 
90 public:
91  AddAttribute() {}
92 
93  void operator()(BaseType *a) {
94  AttrTable *at;
95  AttrTable::Attr_iter aiter;
96  a->get_attr_table().find("translation", &at, &aiter);
97  if (a->get_attr_table().attr_end() == aiter) {
98  a->get_attr_table().append_attr("translation", "String",
99  "\"flatten\"");
100  }
101  }
102 };
103 
125 {
126  if (at) {
127  Vars_iter var = var_begin();
128  while (var != var_end()) {
129  (*var)->transfer_attributes(at);
130  var++;
131  }
132  }
133 }
134 
147 BaseType *
148 NCStructure::transform_to_dap4(D4Group *root, Constructor *container)
149 {
150  Structure *dest = new NCStructure(name(), dataset());
151 
152  Constructor::transform_to_dap4(root, dest);
153  dest->set_parent(container);
154 
155  return dest;
156 }
157 
158 void NCStructure::do_structure_read(int ncid, int varid, nc_type datatype,
159  vector<char> &values, bool has_values, int values_offset)
160 {
161 #if NETCDF_VERSION >= 4
162  if (is_user_defined_type(ncid, datatype)) {
163  char type_name[NC_MAX_NAME+1];
164  size_t size;
165  nc_type base_type;
166  size_t nfields;
167  int class_type;
168  int errstat = nc_inq_user_type(ncid, datatype, type_name, &size, &base_type, &nfields, &class_type);
169  if (errstat != NC_NOERR)
170  throw InternalErr(__FILE__, __LINE__, "Could not get information about a user-defined type (" + long_to_string(errstat) + ").");
171 
172  switch (class_type) {
173  case NC_COMPOUND: {
174  if (!has_values) {
175  values.resize(size);
176  int errstat = nc_get_var(ncid, varid, &values[0] /*&values[0]*/);
177  if (errstat != NC_NOERR)
178  throw Error(errstat, string("Could not get the value for variable '") + name() + string("'"));
179  has_values = true;
180  }
181 
182  for (size_t i = 0; i < nfields; ++i) {
183  char field_name[NC_MAX_NAME+1];
184  nc_type field_typeid;
185  size_t field_offset;
186  int field_ndims;
187  nc_inq_compound_field(ncid, datatype, i, field_name, &field_offset, &field_typeid, &field_ndims, 0);
188  if (is_user_defined_type(ncid, field_typeid)) {
189  // Interior user defined types have names, but not field_names
190  // so use the type name as the field name (matches the
191  // behavior of the ncdds.cc code).
192  nc_inq_compound_name(ncid, field_typeid, field_name);
193  NCStructure &ncs = dynamic_cast<NCStructure&>(*var(field_name));
194  ncs.do_structure_read(ncid, varid, field_typeid, values, has_values, field_offset + values_offset);
195  }
196  else if (var(field_name)->is_vector_type()) {
197  // Because the netcdf api reads data 'atomically' from
198  // compounds, this call works for both cardinal and
199  // array variables.
200  NCArray &child_array = dynamic_cast<NCArray&>(*var(field_name));
201  vector<size_t> cor(field_ndims);
202  vector<size_t> edg(field_ndims);
203  vector<ptrdiff_t> step(field_ndims);
204  bool has_stride;
205  long nels = child_array.format_constraint(&cor[0], &step[0], &edg[0], &has_stride);
206  child_array.do_array_read(ncid, varid, field_typeid,
207  values, has_values, field_offset + values_offset,
208  nels, &cor[0], &edg[0], &step[0], has_stride);
209  }
210  else if (var(field_name)->is_simple_type()) {
211  var(field_name)->val2buf(&values[0] + field_offset + values_offset);
212  }
213  else {
214  throw InternalErr(__FILE__, __LINE__, "Expecting a netcdf user defined type or an array or a scalar.");
215  }
216 
217  var(field_name)->set_read_p(true);
218  }
219  break;
220  }
221 
222  case NC_VLEN:
223  cerr << "in build_user_defined; found a vlen." << endl;
224  break;
225  case NC_OPAQUE:
226  cerr << "in build_user_defined; found a opaque." << endl;
227  break;
228  case NC_ENUM:
229  cerr << "in build_user_defined; found a enum." << endl;
230  break;
231  default:
232  throw InternalErr(__FILE__, __LINE__, "Expected one of NC_COMPOUND, NC_VLEN, NC_OPAQUE or NC_ENUM");
233  }
234  }
235  else
236  throw InternalErr(__FILE__, __LINE__, "Found a DAP Structure bound to a non-user-defined type in the netcdf file " + dataset());
237 #else
238  throw InternalErr(__FILE__, __LINE__, "Found a DAP Structure bound to a non-user-defined type in the netcdf file " + dataset());
239 #endif
240 }
241 
243 {
244  if (read_p()) // nothing to do
245  return true;
246 
247  int ncid;
248  int errstat = nc_open(dataset().c_str(), NC_NOWRITE, &ncid); /* netCDF id */
249  if (errstat != NC_NOERR)
250  throw Error(errstat, "Could not open the dataset's file (" + dataset() + ")");
251 
252  int varid; /* variable Id */
253  errstat = nc_inq_varid(ncid, name().c_str(), &varid);
254  if (errstat != NC_NOERR)
255  throw InternalErr(__FILE__, __LINE__, "Could not get variable ID for: " + name() + ". (error: " + long_to_string(errstat) + ").");
256 
257  nc_type datatype; /* variable data type */
258  errstat = nc_inq_vartype(ncid, varid, &datatype);
259  if (errstat != NC_NOERR)
260  throw Error(errstat, "Could not read data type information about : " + name() + ". (error: " + long_to_string(errstat) + ").");
261 
262  // For Compound types, netcdf's nc_get_var() reads all of the structure's
263  // values in one shot, including values for nested structures. Pass the
264  // (reference to the) space for these in at the start of what may be a
265  // series of recursive calls.
266  vector<char> values;
267  do_structure_read(ncid, varid, datatype, values, false /*has_values*/, 0 /*values_offset*/);
268 
269  set_read_p(true);
270 
271  if (nc_close(ncid) != NC_NOERR)
272  throw InternalErr(__FILE__, __LINE__, "Could not close the dataset!");
273 
274  return true;
275 }
276 
277 
#define not_used
Definition: config.h:315
virtual BaseType * transform_to_dap4(D4Group *root, Constructor *container)
Custom version of the transform_to_dap4() method.
Definition: NCStructure.cc:148
virtual void transfer_attributes(AttrTable *at)
Transfer attributes from a separately built DAS to the DDS.
Definition: NCStructure.cc:124
virtual ~NCStructure()
Definition: NCStructure.cc:70
virtual bool read()
Definition: NCStructure.cc:242
NCStructure & operator=(const NCStructure &rhs)
Definition: NCStructure.cc:75
NCStructure(const string &n, const string &d)
bool is_user_defined_type(int ncid, int type)
Definition: nc_util.cc:33
virtual BaseType * ptr_duplicate()
Definition: NCStructure.cc:57