libdap  Updated for version 3.17.0
Sequence.cc
00001 // -*- mode: c++; c-basic-offset:4 -*-
00002 
00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00004 // Access Protocol.
00005 
00006 // Copyright (c) 2002,2003 OPeNDAP, Inc.
00007 // Author: James Gallagher <jgallagher@opendap.org>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022 //
00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00024 
00025 // (c) COPYRIGHT URI/MIT 1994-1999
00026 // Please read the full copyright statement in the file COPYRIGHT_URI.
00027 //
00028 // Authors:
00029 //      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
00030 
00031 // Implementation for the class Structure
00032 //
00033 // jhrg 9/14/94
00034 
00035 //#define DODS_DEBUG
00036 //#define DODS_DEBUG2
00037 
00038 #include "config.h"
00039 
00040 #include <algorithm>
00041 #include <string>
00042 #include <sstream>
00043 
00044 #include "Byte.h"
00045 #include "Int16.h"
00046 #include "UInt16.h"
00047 #include "Int32.h"
00048 #include "UInt32.h"
00049 #include "Float32.h"
00050 #include "Float64.h"
00051 #include "Str.h"
00052 #include "Url.h"
00053 #include "Array.h"
00054 #include "Structure.h"
00055 #include "Sequence.h"
00056 #include "Grid.h"
00057 
00058 #include "Marshaller.h"
00059 #include "UnMarshaller.h"
00060 
00061 #include "debug.h"
00062 #include "Error.h"
00063 #include "InternalErr.h"
00064 #include "Sequence.h"
00065 #include "DDS.h"
00066 #include "DataDDS.h"
00067 #include "util.h"
00068 #include "InternalErr.h"
00069 #include "escaping.h"
00070 
00071 #include "D4Attributes.h"
00072 #include "D4Sequence.h"
00073 #include "D4Group.h"
00074 #include "Constructor.h"
00075 #include "DMR.h"
00076 
00077 #undef CLEAR_LOCAL_DATA
00078 
00079 using namespace std;
00080 
00081 namespace libdap {
00082 
00083 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101
00084 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010
00085 
00086 // Private member functions
00087 
00088 void Sequence::m_duplicate(const Sequence &s)
00089 {
00090     DBG(cerr << "In Sequence::m_duplicate" << endl);
00091 
00092     d_row_number = s.d_row_number;
00093     d_starting_row_number = s.d_starting_row_number;
00094     d_ending_row_number = s.d_ending_row_number;
00095     d_row_stride = s.d_row_stride;
00096     d_leaf_sequence = s.d_leaf_sequence;
00097     d_unsent_data = s.d_unsent_data;
00098     d_wrote_soi = s.d_wrote_soi;
00099     d_top_most = s.d_top_most;
00100 
00101     Sequence &cs = const_cast<Sequence &>(s);
00102 
00103     // Copy the BaseType objects used to hold values.
00104     for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin(); rows_iter != cs.d_values.end(); rows_iter++) {
00105         // Get the current BaseType Row
00106         BaseTypeRow *src_bt_row_ptr = *rows_iter;
00107         // Create a new row.
00108         BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow;
00109         // Copy the BaseType objects from a row to new BaseType objects.
00110         // Push new BaseType objects onto new row.
00111         for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin(); bt_row_iter != src_bt_row_ptr->end();
00112                 bt_row_iter++) {
00113             BaseType *src_bt_ptr = *bt_row_iter;
00114             BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate();
00115             dest_bt_row_ptr->push_back(dest_bt_ptr);
00116         }
00117         // Push new row onto d_values.
00118         d_values.push_back(dest_bt_row_ptr);
00119     }
00120 }
00121 
00122 static void write_end_of_sequence(Marshaller &m)
00123 {
00124     m.put_opaque((char *) &end_of_sequence, 1);
00125 }
00126 
00127 static void write_start_of_instance(Marshaller &m)
00128 {
00129     m.put_opaque((char *) &start_of_instance, 1);
00130 }
00131 
00132 static unsigned char read_marker(UnMarshaller &um)
00133 {
00134     unsigned char marker;
00135     um.get_opaque((char *) &marker, 1);
00136 
00137     return marker;
00138 }
00139 
00140 static bool is_start_of_instance(unsigned char marker)
00141 {
00142     return (marker == start_of_instance);
00143 }
00144 
00145 static bool is_end_of_sequence(unsigned char marker)
00146 {
00147     return (marker == end_of_sequence);
00148 }
00149 
00150 // Public member functions
00151 
00160 Sequence::Sequence(const string &n) :
00161         Constructor(n, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1), d_row_stride(1), d_ending_row_number(
00162                 -1), d_unsent_data(false), d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false)
00163 {
00164 }
00165 
00176 Sequence::Sequence(const string &n, const string &d) :
00177                 Constructor(n, d, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1),
00178                 d_row_stride(1), d_ending_row_number(-1), d_unsent_data(false),
00179                 d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false)
00180 {
00181 }
00182 
00184 Sequence::Sequence(const Sequence &rhs) :
00185         Constructor(rhs)
00186 {
00187     m_duplicate(rhs);
00188 }
00189 
00190 BaseType *
00191 Sequence::ptr_duplicate()
00192 {
00193     return new Sequence(*this);
00194 }
00195 
00210 BaseType *
00211 Sequence::transform_to_dap4(D4Group *root, Constructor *container)
00212 {
00213     D4Sequence *dest = new D4Sequence(name());
00214 
00215     Constructor::transform_to_dap4(root, dest);
00216 
00217     dest->set_length(-1);
00218     dest->set_parent(container);
00219 
00220     return dest;
00221 }
00222 
00223 static inline void delete_bt(BaseType *bt_ptr)
00224 {
00225     delete bt_ptr;
00226     bt_ptr = 0;
00227 }
00228 
00229 static inline void delete_rows(BaseTypeRow *bt_row_ptr)
00230 {
00231     for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
00232 
00233     delete bt_row_ptr;
00234     bt_row_ptr = 0;
00235 }
00236 
00237 Sequence::~Sequence()
00238 {
00239     clear_local_data();
00240 }
00241 
00242 void Sequence::clear_local_data()
00243 {
00244     if (!d_values.empty()) {
00245         for_each(d_values.begin(), d_values.end(), delete_rows);
00246         d_values.resize(0);
00247     }
00248 
00249     set_read_p(false);
00250 }
00251 
00252 Sequence &
00253 Sequence::operator=(const Sequence &rhs)
00254 {
00255     if (this == &rhs) return *this;
00256 
00257     dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
00258 
00259     m_duplicate(rhs);
00260 
00261     return *this;
00262 }
00263 
00267 bool Sequence::is_dap2_only_type()
00268 {
00269     return true;
00270 }
00271 
00272 string Sequence::toString()
00273 {
00274     ostringstream oss;
00275 
00276     oss << BaseType::toString();
00277 
00278     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00279         oss << (*i)->toString();
00280     }
00281 
00282     oss << endl;
00283 
00284     return oss.str();
00285 }
00286 
00287 bool Sequence::is_linear()
00288 {
00289     bool linear = true;
00290     bool seq_found = false;
00291     for (Vars_iter iter = d_vars.begin(); linear && iter != d_vars.end(); iter++) {
00292         if ((*iter)->type() == dods_sequence_c) {
00293             // A linear sequence cannot have more than one child seq. at any
00294             // one level. If we've already found a seq at this level, return
00295             // false.
00296             if (seq_found) {
00297                 linear = false;
00298                 break;
00299             }
00300             seq_found = true;
00301             linear = static_cast<Sequence *>((*iter))->is_linear();
00302         }
00303         else if ((*iter)->type() == dods_structure_c) {
00304             linear = static_cast<Structure*>((*iter))->is_linear();
00305         }
00306         else {
00307             // A linear sequence cannot have Arrays, Lists or Grids.
00308             linear = (*iter)->is_simple_type();
00309         }
00310     }
00311 
00312     return linear;
00313 }
00314 
00319 BaseTypeRow *
00320 Sequence::row_value(size_t row)
00321 {
00322     if (row >= d_values.size()) return 0;
00323     return d_values[row];
00324 }
00325 
00332 void Sequence::set_value(SequenceValues &values)
00333 {
00334     d_values = values;
00335 }
00336 
00339 SequenceValues Sequence::value()
00340 {
00341     return d_values;
00342 }
00343 
00346 SequenceValues &
00347 Sequence::value_ref()
00348 {
00349     return d_values;
00350 }
00351 
00357 BaseType *
00358 Sequence::var_value(size_t row, const string &name)
00359 {
00360     BaseTypeRow *bt_row_ptr = row_value(row);
00361     if (!bt_row_ptr) return 0;
00362 
00363     BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
00364     BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
00365     while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
00366         ++bt_row_iter;
00367 
00368     if (bt_row_iter == bt_row_end)
00369         return 0;
00370     else
00371         return *bt_row_iter;
00372 }
00373 
00379 BaseType *
00380 Sequence::var_value(size_t row, size_t i)
00381 {
00382     BaseTypeRow *bt_row_ptr = row_value(row);
00383     if (!bt_row_ptr) return 0;
00384 
00385     if (i >= bt_row_ptr->size()) return 0;
00386 
00387     return (*bt_row_ptr)[i];
00388 }
00389 
00390 // This version returns -1. Each API-specific subclass should define a more
00391 // reasonable version. jhrg 5/24/96
00392 
00408 int Sequence::length() const
00409 {
00410     return -1;
00411 }
00412 
00413 // Hmmm. how is this different from length()?
00414 int Sequence::number_of_rows() const
00415 {
00416     return d_values.size();
00417 }
00418 
00422 void Sequence::reset_row_number()
00423 {
00424     d_row_number = -1;
00425 }
00426 
00427 #if 0
00428 // written but not used - this was written so that values loaded from
00429 // Arrays into a new ('synthesized') sequence by the 'tablar() server
00430 // function would be properly used during the evaluation of a selection
00431 // expression. But I forgot that tabular() uses a specialized version of
00432 // Sequence: TabularSequence and that has it's own version of serialize().
00433 // To get the returnAs="ascii" to filter values, I also need to specialize
00434 // the intern_data() method of Sequence. jhrg 3/9/15
00435 
00450 void Sequence::load_prototypes_with_values(int row_number)
00451 {
00452     vector<BaseType*> *row = d_values.at(row_number);
00453 
00454     // For each of the prototype variables in the Sequence, load it
00455     // with a values from the BaseType* vector. The order should match.
00456     // Test the type, but assume if that matches, the value is correct
00457     // for the variable.
00458     int pos = 0;
00459     for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i) {
00460         if ((*i)->type() != row->at(pos)->var()->type())
00461             throw InternalErr(__FILE__, __LINE__, "Expected types to match when loading values for selection expression evaluation.");
00462 
00463         // Ugly...
00464         switch ((*i)->type()) {
00465         case dods_byte_c:
00466             static_cast<Byte*>(*i)->set_value(static_cast<Byte*>(row->at(pos++))->value());
00467             break;
00468         case dods_int16_c:
00469             static_cast<Int16*>(*i)->set_value(static_cast<Int16*>(row->at(pos++))->value());
00470             break;
00471         case dods_int32_c:
00472             static_cast<Int32*>(*i)->set_value(static_cast<Int32*>(row->at(pos++))->value());
00473             break;
00474         case dods_uint16_c:
00475             static_cast<UInt16*>(*i)->set_value(static_cast<UInt16*>(row->at(pos++))->value());
00476             break;
00477         case dods_uint32_c:
00478             static_cast<UInt32*>(*i)->set_value(static_cast<UInt32*>(row->at(pos++))->value());
00479             break;
00480         case dods_float32_c:
00481             static_cast<Float32*>(*i)->set_value(static_cast<Float32*>(row->at(pos++))->value());
00482             break;
00483         case dods_float64_c:
00484             static_cast<Float64*>(*i)->set_value(static_cast<Float64*>(row->at(pos++))->value());
00485             break;
00486         case dods_str_c:
00487             static_cast<Str*>(*i)->set_value(static_cast<Str*>(row->at(pos++))->value());
00488             break;
00489         case dods_url_c:
00490             static_cast<Url*>(*i)->set_value(static_cast<Url*>(row->at(pos++))->value());
00491             break;
00492         default:
00493             throw InternalErr(__FILE__, __LINE__, "Expected a scalar type when loading values for selection expression evaluation.");
00494         }
00495     }
00496 }
00497 
00498 #endif
00499 
00500 // Notes:
00501 // Assume that read() is implemented so that, when reading data for a nested
00502 // sequence, only the outer most level is *actually* read.
00503 // This is a consequence of our current (12/7/99) implementation of
00504 // the JGOFS server (which is the only server to actually use nested
00505 // sequences). 12/7/99 jhrg
00506 //
00507 // Stop assuming this. This logic is being moved into the JGOFS server
00508 // itself. 6/1/2001 jhrg
00509 
00510 // The read() function returns a boolean value, with TRUE
00511 // indicating that read() should be called again because there's
00512 // more data to read, and FALSE indicating there's no more data
00513 // to read. Note that this behavior is necessary to properly
00514 // handle variables that contain Sequences. Jose Garcia If an
00515 // error exists while reading, the implementers of the surrogate
00516 // library SHOULD throw an Error object which will propagate
00517 // beyond this point to to the original caller.
00518 // Jose Garcia
00519 
00552 bool Sequence::read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval)
00553 {
00554     DBG2(cerr << "Entering Sequence::read_row for " << name() << endl);
00555     if (row < d_row_number) throw InternalErr("Trying to back up inside a sequence!");
00556 
00557     DBG2(cerr << "read_row: row number " << row << ", current row " << d_row_number << endl);
00558     if (row == d_row_number) {
00559         DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
00560         return false;
00561     }
00562 #if USE_LOCAL_TIMEOUT_SCHEME
00563     dds.timeout_on();
00564 #endif
00565     bool eof = false;  // Start out assuming EOF is false.
00566     while (!eof && d_row_number < row) {
00567         if (!read_p()) {
00568             // jhrg original version from 10/9/13 : eof = (read() == false);
00569             eof = read();
00570         }
00571 #if 0
00572         // A change (3/9/15): I've made the is_synthesized property
00573         // work so that the prototype variables in the Sequence are loaded
00574         // with the scalar values for the ith row so that the eval_selection()
00575         // method will function correctly.
00576 
00577         // See note above
00578 
00579         if (d_is_synthesized) {
00580             load_prototypes_with_values(d_row_number);
00581         }
00582 #endif
00583         // Advance the row number if ce_eval is false (we're not supposed to
00584         // evaluate the selection) or both ce_eval and the selection are
00585         // true.
00586         if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) d_row_number++;
00587 
00588         set_read_p(false); // ...so that the next instance will be read
00589     }
00590 
00591     // Once we finish the above loop, set read_p to true so that the caller
00592     // knows that data *has* been read. This is how the read() methods of the
00593     // elements of the sequence know to not call read() but instead look for
00594     // data values inside themselves.
00595     set_read_p(true);
00596 #if USE_LOCAL_TIMEOUT_SCHEME
00597     dds.timeout_off();
00598 #endif
00599     // Return true if we have valid data, false if we've read to the EOF.
00600     DBG2(cerr << "Leaving Sequence::read_row for " << name() << " with eof: " << eof << endl);
00601     return !eof; // jhrg 10/10/13 was: eof == 0;
00602 }
00603 
00604 // Private. This is used to process constraints on the rows of a sequence.
00605 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
00606 // odd-looking logic first checks if d_ending_row_number is the sentinel
00607 // value of -1. If so, the sequence was not constrained by row number and
00608 // this method should never return true (which indicates that we're at the
00609 // end of a row-number constraint). If d_ending_row_number is not -1, then is
00610 // \e i at the end point? 6/1/2001 jhrg
00611 inline bool Sequence::is_end_of_rows(int i)
00612 {
00613     return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
00614 }
00615 
00676 bool Sequence::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval)
00677 {
00678     DBG2(cerr << "Entering Sequence::serialize for " << name() << endl);
00679 
00680     // Special case leaf sequences!
00681     bool status = false;
00682 
00683     if (is_leaf_sequence())
00684         status = serialize_leaf(dds, eval, m, ce_eval);
00685     else
00686         status = serialize_parent_part_one(dds, eval, m);
00687 
00688 #ifdef CLEAR_LOCAL_DATA
00689     clear_local_data();
00690 #endif
00691 
00692     return status;
00693 }
00694 
00695 // We know this is not a leaf Sequence. That means that this Sequence holds
00696 // another Sequence as one of its fields _and_ that child Sequence triggers
00697 // the actual transmission of values.
00698 
00699 bool Sequence::serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
00700 {
00701     DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
00702 
00703     int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
00704 
00705     // read_row returns true if valid data was read, false if the EOF was
00706     // found. 6/1/2001 jhrg
00707     // Since this is a parent sequence, read the row ignoring the CE (all of
00708     // the CE clauses will be evaluated by the leaf sequence).
00709     bool status = read_row(i, dds, eval, false);
00710     DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
00711 
00712     while (status && !is_end_of_rows(i)) {
00713         i += d_row_stride;
00714 
00715         // DBG(cerr << "Writing Start of Instance marker" << endl);
00716         // write_start_of_instance(sink);
00717 
00718         // In this loop serialize will signal an error with an exception.
00719         for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
00720             // Only call serialize for child Sequences; the leaf sequence
00721             // will trigger the transmission of values for its parents (this
00722             // sequence and maybe others) once it gets some valid data to
00723             // send.
00724             // Note that if the leaf sequence has no variables in the current
00725             // projection, its serialize() method will never be called and that's
00726             // the method that triggers actually sending values. Thus the leaf
00727             // sequence must be the lowest level sequence with values whose send_p
00728             // property is true.
00729             if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) (*iter)->serialize(eval, dds, m);
00730         }
00731 
00732         set_read_p(false); // ...so this will read the next instance
00733 
00734         status = read_row(i, dds, eval, false);
00735         DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
00736     }
00737     // Reset current row number for next nested sequence element.
00738     d_row_number = -1;
00739 
00740     // Always write the EOS marker? 12/23/04 jhrg
00741     // Yes. According to DAP2, a completely empty response is signaled by
00742     // a return value of only the EOS marker for the outermost sequence.
00743     if (d_top_most || d_wrote_soi) {
00744         DBG(cerr << "Writing End of Sequence marker" << endl);
00745         write_end_of_sequence(m);
00746         d_wrote_soi = false;
00747     }
00748 
00749     return true;  // Signal errors with exceptions.
00750 }
00751 
00752 // If we are here then we know that this is 'parent sequence' and that the
00753 // leaf sequence has found valid data to send. We also know that
00754 // serialize_parent_part_one has been called so data are in the instance's
00755 // fields. This is where we send data. Whereas ..._part_one() contains a
00756 // loop to iterate over all of rows in a parent sequence, this does not. This
00757 // method assumes that the serialize_leaf() will call it each time it needs
00758 // to be called.
00759 //
00760 // NB: This code only works if the child sequences appear after all other
00761 // variables.
00762 void Sequence::serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
00763 {
00764     DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
00765 
00766     BaseType *btp = get_parent();
00767     if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
00768 
00769     if (d_unsent_data) {
00770         DBG(cerr << "Writing Start of Instance marker" << endl);
00771         d_wrote_soi = true;
00772         write_start_of_instance(m);
00773 
00774         // In this loop serialize will signal an error with an exception.
00775         for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
00776             // Send all the non-sequence variables
00777             DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
00778                     << (*iter)->name() << endl);
00779             if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
00780                 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
00781                 (*iter)->serialize(eval, dds, m, false);
00782             }
00783         }
00784 
00785         d_unsent_data = false;              // read should set this.
00786     }
00787 }
00788 
00789 // This code is only run by a leaf sequence. Note that a one level sequence
00790 // is also a leaf sequence.
00791 bool Sequence::serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
00792 {
00793     DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
00794     int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
00795 
00796     // read_row returns true if valid data was read, false if the EOF was
00797     // found. 6/1/2001 jhrg
00798     bool status = read_row(i, dds, eval, ce_eval);
00799     DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
00800 
00801     // Once the first valid (satisfies the CE) row of the leaf sequence has
00802     // been read, we know we're going to send data. Send the current instance
00803     // of the parent/ancestor sequences now, if there are any. We only need
00804     // to do this once, hence it's not inside the while loop, but we only
00805     // send the parent seq data _if_ there's data in the leaf to send, that's
00806     // why we wait until after the first call to read_row() here in the leaf
00807     // sequence.
00808     //
00809     // NB: It's important to only call serialize_parent_part_two() for a
00810     // Sequence that really is the parent of a leaf sequence.
00811     if (status && !is_end_of_rows(i)) {
00812         BaseType *btp = get_parent();
00813         if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
00814     }
00815 
00816     d_wrote_soi = false;
00817     while (status && !is_end_of_rows(i)) {
00818         i += d_row_stride;
00819 
00820         DBG(cerr << "Writing Start of Instance marker" << endl);
00821         d_wrote_soi = true;
00822         write_start_of_instance(m);
00823 
00824         // In this loop serialize will signal an error with an exception.
00825         for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
00826             DBG(cerr << "Sequence::serialize_leaf(), serializing "
00827                     << (*iter)->name() << endl);
00828             if ((*iter)->send_p()) {
00829                 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
00830                 (*iter)->serialize(eval, dds, m, false);
00831             }
00832         }
00833 
00834         set_read_p(false); // ...so this will read the next instance
00835 
00836         status = read_row(i, dds, eval, ce_eval);
00837         DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
00838     }
00839 
00840     // Only write the EOS marker if there's a matching Start Of Instance
00841     // Marker in the stream.
00842     if (d_wrote_soi || d_top_most) {
00843         DBG(cerr << "Writing End of Sequence marker" << endl);
00844         write_end_of_sequence(m);
00845     }
00846 
00847     return true;  // Signal errors with exceptions.
00848 }
00849 
00872 void Sequence::intern_data(ConstraintEvaluator &eval, DDS &dds)
00873 {
00874     DBG(cerr << "Sequence::intern_data - for " << name() << endl); DBG2(cerr << "    intern_data, values: " << &d_values << endl);
00875 
00876     // Why use a stack instead of return values? We need the stack because
00877     // Sequences nested three of more levels deep will loose the middle
00878     // instances when the intern_data_parent_part_two() code is run.
00879     sequence_values_stack_t sequence_values_stack;
00880 
00881     DBG2(cerr << "    pushing d_values of " << name() << " (" << &d_values
00882             << ") on stack; size: " << sequence_values_stack.size() << endl);
00883     sequence_values_stack.push(&d_values);
00884 
00885     intern_data_private(eval, dds, sequence_values_stack);
00886 }
00887 
00888 void Sequence::intern_data_private(ConstraintEvaluator &eval, DDS &dds, sequence_values_stack_t &sequence_values_stack)
00889 {
00890     DBG(cerr << "Entering intern_data_private for " << name() << endl);
00891 
00892     if (is_leaf_sequence())
00893         intern_data_for_leaf(dds, eval, sequence_values_stack);
00894     else
00895         intern_data_parent_part_one(dds, eval, sequence_values_stack);
00896 }
00897 
00898 void Sequence::intern_data_parent_part_one(DDS & dds, ConstraintEvaluator & eval,
00899         sequence_values_stack_t & sequence_values_stack)
00900 {
00901     DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
00902 
00903     int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
00904 
00905     // read_row returns true if valid data was read, false if the EOF was
00906     // found. 6/1/2001 jhrg
00907     // Since this is a parent sequence, read the row ignoring the CE (all of
00908     // the CE clauses will be evaluated by the leaf sequence).
00909     bool status = read_row(i, dds, eval, false);
00910 
00911     // Grab the current size of the value stack. We do this because it is
00912     // possible that no nested sequences for this row happened to be
00913     // selected because of a constraint evaluation or the last row is not
00914     // selected because of a constraint evaluation. In either case, no
00915     // nested sequence d_values are pushed onto the stack, so there is
00916     // nothing to pop at the end of this function. pcw 07/14/08
00917     SequenceValues::size_type orig_stack_size = sequence_values_stack.size();
00918 
00919     while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
00920         i += get_row_stride();
00921         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
00922             if ((*iter)->send_p()) {
00923                 switch ((*iter)->type()) {
00924                 case dods_sequence_c:
00925                     static_cast<Sequence&>(**iter).intern_data_private(eval, dds, sequence_values_stack);
00926                     break;
00927 
00928                 default:
00929                     (*iter)->intern_data(eval, dds);
00930                     break;
00931                 }
00932             }
00933         }
00934 
00935         set_read_p(false);      // ...so this will read the next instance
00936 
00937         status = read_row(i, dds, eval, false);
00938     }
00939 
00940     // Reset current row number for next nested sequence element.
00941     reset_row_number();
00942 
00943     // if the size of the stack is larger than the original size (retrieved
00944     // above) then pop the top set of d_values from the stack. If it's the
00945     // same, then no nested sequences, or possible the last nested sequence,
00946     // were pushed onto the stack, so there is nothing to pop.
00947     if (sequence_values_stack.size() > orig_stack_size) {
00948         DBG2(cerr << "    popping d_values (" << sequence_values_stack.top()
00949                 << ") off stack; size: " << sequence_values_stack.size() << endl);
00950         sequence_values_stack.pop();
00951     } DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
00952 }
00953 
00954 void Sequence::intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval,
00955         sequence_values_stack_t &sequence_values_stack)
00956 {
00957     DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
00958 
00959     BaseType *btp = get_parent();
00960     if (btp && btp->type() == dods_sequence_c) {
00961         static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
00962     }
00963 
00964     DBG2(cerr << "    stack size: " << sequence_values_stack.size() << endl);
00965     SequenceValues *values = sequence_values_stack.top();
00966     DBG2(cerr << "    using values = " << (void *)values << endl);
00967 
00968     if (get_unsent_data()) {
00969         BaseTypeRow *row_data = new BaseTypeRow;
00970 
00971         // In this loop transfer_data will signal an error with an exception.
00972         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
00973 
00974             if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
00975                 row_data->push_back((*iter)->ptr_duplicate());
00976             }
00977             else if ((*iter)->send_p()) { //Sequence; must be the last variable
00978                 Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
00979                 if (!tmp) {
00980                     delete row_data;
00981                     throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
00982                 }
00983                 row_data->push_back(tmp);
00984                 DBG2(cerr << "    pushing d_values of " << tmp->name()
00985                         << " (" << &(tmp->d_values)
00986                         << ") on stack; size: " << sequence_values_stack.size()
00987                         << endl);
00988                 // This pushes the d_values field of the newly created leaf
00989                 // Sequence onto the stack. The code then returns to intern
00990                 // _data_for_leaf() where this value will be used.
00991                 sequence_values_stack.push(&(tmp->d_values));
00992             }
00993         }
00994 
00995         DBG2(cerr << "    pushing values for " << name()
00996                 << " to " << values << endl);
00997         values->push_back(row_data);
00998         set_unsent_data(false);
00999     } DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
01000 }
01001 
01002 void Sequence::intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
01003 {
01004     DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
01005 
01006     int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
01007 
01008     DBG2(cerr << "    reading row " << i << endl);
01009     bool status = read_row(i, dds, eval, true);
01010     DBG2(cerr << "    status: " << status << endl); DBG2(cerr << "    ending row number: " << get_ending_row_number() << endl);
01011 
01012     if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
01013         BaseType *btp = get_parent();
01014         if (btp && btp->type() == dods_sequence_c) {
01015             // This call will read the values for the parent sequences and
01016             // then allocate a new instance for the leaf and push that onto
01017             // the stack.
01018             static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
01019         }
01020 
01021         // intern_data_parent_part_two pushes the d_values field of the leaf
01022         // onto the stack, so this operation grabs that value and then loads
01023         // data into it.
01024         SequenceValues *values = sequence_values_stack.top();
01025         DBG2(cerr << "    using values = " << values << endl);
01026 
01027         while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
01028             i += get_row_stride();
01029 
01030             // Copy data from the object's fields to this new BaeTypeRow instance
01031             BaseTypeRow *row_data = new BaseTypeRow;
01032             for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
01033                 if ((*iter)->send_p()) {
01034                     row_data->push_back((*iter)->ptr_duplicate());
01035                 }
01036             }
01037 
01038             DBG2(cerr << "    pushing values for " << name()
01039                     << " to " << values << endl);
01040             // Save the row_data to values().
01041             values->push_back(row_data);
01042 
01043             set_read_p(false);      // ...so this will read the next instance
01044             // Read the ith row into this object's fields
01045             status = read_row(i, dds, eval, true);
01046         }
01047 
01048         DBG2(cerr << "    popping d_values (" << sequence_values_stack.top()
01049                 << ") off stack; size: " << sequence_values_stack.size() << endl);
01050         sequence_values_stack.pop();
01051     } DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
01052 }
01053 
01074 bool Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
01075 {
01076     DataDDS *dd = dynamic_cast<DataDDS *>(dds);
01077     if (!dd) throw InternalErr("Expected argument 'dds' to be a DataDDS!");
01078 
01079     DBG2(cerr << "Reading from server/protocol version: "
01080             << dd->get_protocol_major() << "." << dd->get_protocol_minor()
01081             << endl);
01082 
01083     // Check for old servers.
01084     if (dd->get_protocol_major() < 2) {
01085         throw Error(
01086                 string("The protocl version (") + dd->get_protocol()
01087                         + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
01088     }
01089 
01090     while (true) {
01091         // Grab the sequence stream's marker.
01092         unsigned char marker = read_marker(um);
01093         if (is_end_of_sequence(marker))
01094             break;  // EXIT the while loop here!!!
01095         else if (is_start_of_instance(marker)) {
01096             d_row_number++;
01097             DBG2(cerr << "Reading row " << d_row_number << " of "
01098                     << name() << endl);
01099             BaseTypeRow *bt_row_ptr = new BaseTypeRow;
01100             // Read the instance's values, building up the row
01101             for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
01102                 BaseType *bt_ptr = (*iter)->ptr_duplicate();
01103                 bt_ptr->deserialize(um, dds, reuse);
01104                 DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
01105                         << bt_ptr << ") = "); DBG2(bt_ptr->print_val(stderr, ""));
01106                 bt_row_ptr->push_back(bt_ptr);
01107             }
01108             // Append this row to those accumulated.
01109             d_values.push_back(bt_row_ptr);
01110         }
01111         else
01112             throw Error("I could not read the expected Sequence data stream marker!");
01113     };
01114 
01115     return false;
01116 }
01117 
01118 // Return the current row number.
01119 
01131 int Sequence::get_starting_row_number()
01132 {
01133     return d_starting_row_number;
01134 }
01135 
01146 int Sequence::get_row_stride()
01147 {
01148     return d_row_stride;
01149 }
01150 
01162 int Sequence::get_ending_row_number()
01163 {
01164     return d_ending_row_number;
01165 }
01166 
01175 void Sequence::set_row_number_constraint(int start, int stop, int stride)
01176 {
01177     if (stop < start) throw Error(malformed_expr, "Starting row number must precede the ending row number.");
01178 
01179     d_starting_row_number = start;
01180     d_row_stride = stride;
01181     d_ending_row_number = stop;
01182 }
01183 
01184 void Sequence::print_one_row(FILE *out, int row, string space, bool print_row_num)
01185 {
01186     ostringstream oss;
01187     print_one_row(oss, row, space, print_row_num);
01188     fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
01189 }
01190 
01191 void Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num)
01192 {
01193     if (print_row_num) out << "\n" << space << row << ": ";
01194 
01195     out << "{ ";
01196 
01197     int elements = element_count();
01198     int j = 0;
01199     BaseType *bt_ptr = 0;
01200 
01201     // This version of print_one_row() works for both data read with
01202     // deserialize(), where each variable is assumed to have valid data, and
01203     // intern_data(), where some/many variables do not. Because of that, it's
01204     // not correct to assume that all of the elements will be printed, which
01205     // is what the old code did.
01206     // Print the first value
01207     while (j < elements && !bt_ptr) {
01208         bt_ptr = var_value(row, j++);
01209         if (bt_ptr) {  // data
01210             if (bt_ptr->type() == dods_sequence_c)
01211                 static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + "    ", false, print_row_num);
01212             else
01213                 bt_ptr->print_val(out, space, false);
01214         }
01215     }
01216 
01217     // Print the remaining values
01218     while (j < elements) {
01219         bt_ptr = var_value(row, j++);
01220         if (bt_ptr) {  // data
01221             out << ", ";
01222             if (bt_ptr->type() == dods_sequence_c)
01223                 static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + "    ", false, print_row_num);
01224             else
01225                 bt_ptr->print_val(out, space, false);
01226         }
01227     }
01228 
01229     out << " }";
01230 }
01231 
01232 void Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p, bool print_row_numbers)
01233 {
01234     ostringstream oss;
01235     print_val_by_rows(oss, space, print_decl_p, print_row_numbers);
01236     fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
01237 }
01238 
01239 void Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers)
01240 {
01241     if (print_decl_p) {
01242         print_decl(out, space, false);
01243         out << " = ";
01244     }
01245 
01246     out << "{ ";
01247 
01248     int rows = number_of_rows() - 1;
01249     int i;
01250     for (i = 0; i < rows; ++i) {
01251         print_one_row(out, i, space, print_row_numbers);
01252         out << ", ";
01253     }
01254     print_one_row(out, i, space, print_row_numbers);
01255 
01256     out << " }";
01257 
01258     if (print_decl_p) out << ";\n";
01259 }
01260 
01261 void Sequence::print_val(FILE *out, string space, bool print_decl_p)
01262 {
01263     print_val_by_rows(out, space, print_decl_p, false);
01264 }
01265 
01266 void Sequence::print_val(ostream &out, string space, bool print_decl_p)
01267 {
01268     print_val_by_rows(out, space, print_decl_p, false);
01269 }
01270 
01271 void Sequence::set_leaf_p(bool state)
01272 {
01273     d_leaf_sequence = state;
01274 }
01275 
01276 bool Sequence::is_leaf_sequence()
01277 {
01278     return d_leaf_sequence;
01279 }
01280 
01305 void Sequence::set_leaf_sequence(int lvl)
01306 {
01307     bool has_child_sequence = false;
01308 
01309     if (lvl == 1) d_top_most = true;
01310 
01311     DBG2(cerr << "Processing sequence " << name() << endl);
01312 
01313     for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
01314         // About the test for send_p(): Only descend into a sequence if it has
01315         // fields that might be sent. Thus if, in a two-level sequence, nothing
01316         // in the lower level is to be sent, the upper level is marked as the
01317         // leaf sequence. This ensures that values _will_ be sent (see the comment
01318         // in serialize_leaf() and serialize_parent_part_one()).
01319         if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
01320             if (has_child_sequence)
01321                 throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
01322 
01323             has_child_sequence = true;
01324             static_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
01325         }
01326         else if ((*iter)->type() == dods_structure_c) {
01327             static_cast<Structure&>(**iter).set_leaf_sequence(lvl);
01328         }
01329     }
01330 
01331     if (!has_child_sequence)
01332         set_leaf_p(true);
01333     else
01334         set_leaf_p(false);
01335 
01336     DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
01337 }
01338 
01347 void Sequence::dump(ostream &strm) const
01348 {
01349     strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl;
01350     DapIndent::Indent();
01351     Constructor::dump(strm);
01352     strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number << endl;
01353     strm << DapIndent::LMarg << "bracket notation information:" << endl;
01354     DapIndent::Indent();
01355     strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl;
01356     strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl;
01357     strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl;
01358     DapIndent::UnIndent();
01359 
01360     strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl;
01361     strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl;
01362     strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence << endl;
01363     strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most << endl;
01364     DapIndent::UnIndent();
01365 }
01366 
01367 } // namespace libdap
01368