OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
TabularSequence.cc
Go to the documentation of this file.
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) 2015 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@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 <algorithm>
28 #include <string>
29 #include <sstream>
30 
31 //#define DODS_DEBUG
32 
33 #include <BaseType.h>
34 #include <Byte.h>
35 #include <Int16.h>
36 #include <Int32.h>
37 #include <UInt16.h>
38 #include <UInt32.h>
39 #include <Float32.h>
40 #include <Float64.h>
41 #include <Str.h>
42 #include <Url.h>
43 
44 #include <DDS.h>
45 #include <ConstraintEvaluator.h>
46 #include <Marshaller.h>
47 #include <UnMarshaller.h>
48 #include <debug.h>
49 
50 #include "TabularSequence.h"
51 
52 using namespace std;
53 
54 namespace libdap {
55 
56 // static constants and functions copied from the parent class. These
57 // should never have been static... hindsight
58 
59 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101
60 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010
61 
62 static void
63 write_end_of_sequence(Marshaller &m)
64 {
65  m.put_opaque( (char *)&end_of_sequence, 1 ) ;
66 }
67 
68 static void
69 write_start_of_instance(Marshaller &m)
70 {
71  m.put_opaque( (char *)&start_of_instance, 1 ) ;
72 }
73 
74 void TabularSequence::load_prototypes_with_values(BaseTypeRow &btr, bool safe)
75 {
76  // For each of the prototype variables in the Sequence, load it
77  // with a values from the BaseType* vector. The order should match.
78  // Test the type, but assume if that matches, the value is correct
79  // for the variable.
80  Vars_iter i = d_vars.begin(), e = d_vars.end();
81  for (BaseTypeRow::iterator vi = btr.begin(), ve = btr.end(); vi != ve; ++vi) {
82 
83  if (safe && (i == e || ((*i)->type() != (*vi)->var()->type())))
84  throw InternalErr(__FILE__, __LINE__, "Expected number and types to match when loading values for selection expression evaluation.");
85 
86  // Ugly... but faster than the generic code that allocates storage for each scalar?
87  switch ((*i)->type()) {
88  case dods_byte_c:
89  static_cast<Byte*>(*i++)->set_value(static_cast<Byte*>(*vi)->value());
90  break;
91  case dods_int16_c:
92  static_cast<Int16*>(*i++)->set_value(static_cast<Int16*>((*vi))->value());
93  break;
94  case dods_int32_c:
95  static_cast<Int32*>(*i++)->set_value(static_cast<Int32*>((*vi))->value());
96  break;
97  case dods_uint16_c:
98  static_cast<UInt16*>(*i++)->set_value(static_cast<UInt16*>((*vi))->value());
99  break;
100  case dods_uint32_c:
101  static_cast<UInt32*>(*i++)->set_value(static_cast<UInt32*>((*vi))->value());
102  break;
103  case dods_float32_c:
104  static_cast<Float32*>(*i++)->set_value(static_cast<Float32*>((*vi))->value());
105  break;
106  case dods_float64_c:
107  static_cast<Float64*>(*i++)->set_value(static_cast<Float64*>((*vi))->value());
108  break;
109  case dods_str_c:
110  static_cast<Str*>(*i++)->set_value(static_cast<Str*>((*vi))->value());
111  break;
112  case dods_url_c:
113  static_cast<Url*>(*i++)->set_value(static_cast<Url*>((*vi))->value());
114  break;
115  default:
116  throw InternalErr(__FILE__, __LINE__, "Expected a scalar type when loading values for selection expression evaluation.");
117  }
118  }
119 }
120 
121 // Public member functions
122 #if 0
123 
131 TabularSequence::TabularSequence(const string &n) : Sequence(n)
132 {
133 }
134 
145 TabularSequence::TabularSequence(const string &n, const string &d)
146  : Sequence(n, d)
147 {}
148 
150 TabularSequence::TabularSequence(const TabularSequence &rhs) : Sequence(rhs)
151 {
152 }
153 
154 BaseType *
156 {
157  return new TabularSequence(*this);
158 }
159 
160 
162 {
163 
164 }
165 
166 TabularSequence &
167 TabularSequence::operator=(const TabularSequence &rhs)
168 {
169  if (this == &rhs)
170  return *this;
171 
172  dynamic_cast<Sequence &>(*this) = rhs; // run Sequence=
173 
174  return *this;
175 }
176 #endif
177 
194 bool
195 TabularSequence::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval /* true */)
196 {
197  DBG(cerr << "Entering TabularSequence::serialize for " << name() << endl);
198 
199  SequenceValues values = value();
200  //ce_eval = true; Commented out here and changed in BESDapResponseBuilder. jhrg 3/10/15
201 
202  for (SequenceValues::iterator i = values.begin(), e = values.end(); i != e; ++i) {
203 
204  BaseTypeRow &btr = **i;
205 
206  // Transfer values of the current row into the Seq's prototypes so the CE
207  // evaluator will find the values.
208 #if 1
209  load_prototypes_with_values(btr, false);
210 #else
211  int j = 0;
212  for (BaseTypeRow::iterator vi = btr.begin(), ve = btr.end(); vi != ve; ++vi) {
213  void *val = 0;
214  (*vi)->buf2val(&val);
215  d_vars.at(j++)->val2buf(val);
216  }
217 #endif
218  // Evaluate the CE against this row; continue (skipping this row) if it fails
219  if (ce_eval && !eval.eval_selection(dds, dataset()))
220  continue;
221 
222  // Write out this row of values
223  write_start_of_instance(m);
224 
225  // In this loop serialize will signal an error with an exception.
226  for (BaseTypeRow::iterator vi = btr.begin(), ve = btr.end(); vi != ve; ++vi) {
227  if ((*vi)->send_p()) {
228  (*vi)->serialize(eval, dds, m, false);
229  }
230  }
231  }
232 
233  write_end_of_sequence(m);
234 
235  return true; // Signal errors with exceptions.
236 }
237 
247 void TabularSequence::intern_data(ConstraintEvaluator &eval, DDS &dds)
248 {
249  DBG(cerr << "Entering TabularSequence::intern_data" << endl);
250 
251  // FIXME Special case when there are no selection clauses
252  // FIXME Use a destructive copy to move values from 'values' to
253  // result? Or pop values - find a way to not copy all the values
254  // after doing some profiling to see if this code can be meaningfully
255  // optimized
256 #if 1
257  SequenceValues result; // These values satisfy the CE
258  SequenceValues &values = value_ref();
259 
260  for (SequenceValues::iterator i = values.begin(), e = values.end(); i != e; ++i) {
261 
262  BaseTypeRow &btr = **i;
263 
264  // Transfer values of the current row into the Seq's prototypes so the CE
265  // evaluator will find the values.
266  load_prototypes_with_values(btr, false /* safe */);
267 #if 0
268  int j = 0;
269  for (BaseTypeRow::iterator vi = btr.begin(), ve = btr.end(); vi != ve; ++vi) {
270  // TODO check this for efficiency - is the switch-based version in Sequence.cc faster?
271  void *val = 0;
272  (*vi)->buf2val(&val);
273  d_vars.at(j++)->val2buf(val);
274  }
275 #endif
276  // Evaluate the CE against this row; continue (skipping this row) if it fails
277  if (!eval.eval_selection(dds, dataset()))
278  continue;
279 
280  BaseTypeRow *result_row = new BaseTypeRow();
281  // In this loop serialize will signal an error with an exception.
282  for (BaseTypeRow::iterator vi = btr.begin(), ve = btr.end(); vi != ve; ++vi) {
283  if ((*vi)->send_p()) {
284  result_row->push_back(*vi);
285  }
286  }
287 
288  result.push_back(result_row);
289  }
290 
291  set_value(result);
292 
293 #endif
294  DBG(cerr << "Leaving TabularSequence::intern_data" << endl);
295 }
296 
305 void
306 TabularSequence::dump(ostream &strm) const
307 {
308  strm << DapIndent::LMarg << "TabularSequence::dump - (" << (void *)this << ")" << endl ;
309  DapIndent::Indent() ;
310  Sequence::dump(strm) ;
311  DapIndent::UnIndent() ;
312 }
313 
314 } // namespace libdap
315 
TabularSequence(const string &n)
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Specialized version of Sequence::serialize() for tables that already hold their data.
virtual BaseType * ptr_duplicate()
virtual void dump(ostream &strm) const
dumps information about this object
STL namespace.
static class NCMLUtil overview
TabularSequence & operator=(const TabularSequence &rhs)
virtual void intern_data(ConstraintEvaluator &eval, DDS &dds)
Specialized intern_data().
void load_prototypes_with_values(BaseTypeRow &btr, bool safe=true)