libdap++  Updated for version 3.8.2
Sequence.cc
Go to the documentation of this file.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 
00036 #include "config.h"
00037 
00038 #include <algorithm>
00039 #include <string>
00040 #include <sstream>
00041 
00042 //#define DODS_DEBUG
00043 //#define DODS_DEBUG2
00044 
00045 #include "Byte.h"
00046 #include "Int16.h"
00047 #include "UInt16.h"
00048 #include "Int32.h"
00049 #include "UInt32.h"
00050 #include "Float32.h"
00051 #include "Float64.h"
00052 #include "Str.h"
00053 #include "Url.h"
00054 #include "Array.h"
00055 #include "Structure.h"
00056 #include "Sequence.h"
00057 #include "Grid.h"
00058 
00059 #include "debug.h"
00060 #include "Error.h"
00061 #include "InternalErr.h"
00062 #include "Sequence.h"
00063 #include "DDS.h"
00064 #include "DataDDS.h"
00065 #include "util.h"
00066 #include "InternalErr.h"
00067 #include "escaping.h"
00068 
00069 using namespace std;
00070 
00071 namespace libdap {
00072 
00073 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101
00074 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010
00075 
00076 // Private member functions
00077 
00078 void
00079 Sequence::_duplicate(const Sequence &s)
00080 {
00081     d_row_number = s.d_row_number;
00082     d_starting_row_number = s.d_starting_row_number;
00083     d_ending_row_number = s.d_ending_row_number;
00084     d_row_stride = s.d_row_stride;
00085     d_leaf_sequence = s.d_leaf_sequence;
00086     d_unsent_data = s.d_unsent_data;
00087     d_wrote_soi = s.d_wrote_soi;
00088     d_top_most = s.d_top_most;
00089 
00090     Sequence &cs = const_cast<Sequence &>(s);
00091 
00092     // Copy the template BaseType objects.
00093     for (Vars_iter i = cs.var_begin(); i != cs.var_end(); i++) {
00094         add_var((*i)) ;
00095     }
00096 
00097     // Copy the BaseType objects used to hold values.
00098     for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin();
00099          rows_iter != cs.d_values.end();
00100          rows_iter++) {
00101         // Get the current BaseType Row
00102         BaseTypeRow *src_bt_row_ptr = *rows_iter;
00103         // Create a new row.
00104         BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow;
00105         // Copy the BaseType objects from a row to new BaseType objects.
00106         // Push new BaseType objects onto new row.
00107         for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin();
00108              bt_row_iter != src_bt_row_ptr->end();
00109              bt_row_iter++) {
00110             BaseType *src_bt_ptr = *bt_row_iter;
00111             BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate();
00112             dest_bt_row_ptr->push_back(dest_bt_ptr);
00113         }
00114         // Push new row onto d_values.
00115         d_values.push_back(dest_bt_row_ptr);
00116     }
00117 }
00118 
00119 static void
00120 write_end_of_sequence(Marshaller &m)
00121 {
00122     m.put_opaque( (char *)&end_of_sequence, 1 ) ;
00123 }
00124 
00125 static void
00126 write_start_of_instance(Marshaller &m)
00127 {
00128     m.put_opaque( (char *)&start_of_instance, 1 ) ;
00129 }
00130 
00131 static unsigned char
00132 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
00141 is_start_of_instance(unsigned char marker)
00142 {
00143     return (marker == start_of_instance);
00144 }
00145 
00146 static bool
00147 is_end_of_sequence(unsigned char marker)
00148 {
00149     return (marker == end_of_sequence);
00150 }
00151 
00152 // Public member functions
00153 
00162 Sequence::Sequence(const string &n) : Constructor(n, dods_sequence_c),
00163         d_row_number(-1), d_starting_row_number(-1),
00164         d_row_stride(1), d_ending_row_number(-1),
00165         d_unsent_data(false), d_wrote_soi(false),
00166         d_leaf_sequence(false), d_top_most(false)
00167 {}
00168 
00179 Sequence::Sequence(const string &n, const string &d)
00180     : Constructor(n, d, dods_sequence_c),
00181       d_row_number(-1), d_starting_row_number(-1),
00182       d_row_stride(1), d_ending_row_number(-1),
00183       d_unsent_data(false), d_wrote_soi(false),
00184       d_leaf_sequence(false), d_top_most(false)
00185 {}
00186 
00188 Sequence::Sequence(const Sequence &rhs) : Constructor(rhs)
00189 {
00190     _duplicate(rhs);
00191 }
00192 
00193 BaseType *
00194 Sequence::ptr_duplicate()
00195 {
00196     return new Sequence(*this);
00197 }
00198 
00199 static inline void
00200 delete_bt(BaseType *bt_ptr)
00201 {
00202     DBG2(cerr << "In delete_bt: " << bt_ptr << endl);
00203     delete bt_ptr; bt_ptr = 0;
00204 }
00205 
00206 static inline void
00207 delete_rows(BaseTypeRow *bt_row_ptr)
00208 {
00209     DBG2(cerr << "In delete_rows: " << bt_row_ptr << endl);
00210 
00211     for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
00212 
00213     delete bt_row_ptr; bt_row_ptr = 0;
00214 }
00215 
00216 Sequence::~Sequence()
00217 {
00218     DBG2(cerr << "Entering Sequence::~Sequence" << endl);
00219     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00220         BaseType *btp = *i ;
00221         delete btp ; btp = 0;
00222     }
00223 
00224     for_each(d_values.begin(), d_values.end(), delete_rows);
00225     DBG2(cerr << "exiting Sequence::~Sequence" << endl);
00226 }
00227 
00228 Sequence &
00229 Sequence::operator=(const Sequence &rhs)
00230 {
00231     if (this == &rhs)
00232         return *this;
00233 
00234     dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
00235 
00236     _duplicate(rhs);
00237 
00238     return *this;
00239 }
00240 
00241 string
00242 Sequence::toString()
00243 {
00244     ostringstream oss;
00245 
00246     oss << BaseType::toString();
00247 
00248     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00249         oss << (*i)->toString();
00250     }
00251 
00252     oss << endl;
00253 
00254     return oss.str();
00255 }
00256 
00257 int
00258 Sequence::element_count(bool leaves)
00259 {
00260     if (!leaves)
00261         return _vars.size();
00262     else {
00263         int i = 0;
00264         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00265             i += (*iter)->element_count(true);
00266         }
00267         return i;
00268     }
00269 }
00270 
00271 bool
00272 Sequence::is_linear()
00273 {
00274     bool linear = true;
00275     bool seq_found = false;
00276     for (Vars_iter iter = _vars.begin(); linear && iter != _vars.end(); iter++) {
00277         if ((*iter)->type() == dods_sequence_c) {
00278             // A linear sequence cannot have more than one child seq. at any
00279             // one level. If we've already found a seq at this level, return
00280             // false.
00281             if (seq_found) {
00282                 linear = false;
00283                 break;
00284             }
00285             seq_found = true;
00286             linear = dynamic_cast<Sequence *>((*iter))->is_linear();
00287         }
00288         else if ((*iter)->type() == dods_structure_c) {
00289             linear = dynamic_cast<Structure*>((*iter))->is_linear();
00290         }
00291         else {
00292             // A linear sequence cannot have Arrays, Lists or Grids.
00293             linear = (*iter)->is_simple_type();
00294         }
00295     }
00296 
00297     return linear;
00298 }
00299 
00300 void
00301 Sequence::set_send_p(bool state)
00302 {
00303     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00304         (*i)->set_send_p(state);
00305     }
00306 
00307     BaseType::set_send_p(state);
00308 }
00309 
00310 void
00311 Sequence::set_read_p(bool state)
00312 {
00313     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00314         (*i)->set_read_p(state);
00315     }
00316 
00317     BaseType::set_read_p(state);
00318 }
00319 
00320 void
00321 Sequence::set_in_selection(bool state)
00322 {
00323     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00324         (*i)->set_in_selection(state);
00325     }
00326 
00327     BaseType::set_in_selection(state);
00328 }
00329 
00339 void
00340 Sequence::add_var(BaseType *bt, Part)
00341 {
00342     if (!bt)
00343         throw InternalErr(__FILE__, __LINE__,
00344                           "Cannot add variable: NULL pointer");
00345     // Jose Garcia
00346     // We append a copy of bt so the owner of bt is free to deallocate
00347 
00348     BaseType *bt_copy = bt->ptr_duplicate();
00349     bt_copy->set_parent(this);
00350     _vars.push_back(bt_copy);
00351 }
00352 
00364 void
00365 Sequence::add_var_nocopy(BaseType *bt, Part)
00366 {
00367     if (!bt)
00368         throw InternalErr(__FILE__, __LINE__,
00369                           "Cannot add variable: NULL pointer");
00370     bt->set_parent(this);
00371     _vars.push_back(bt);
00372 }
00373 
00374 // Deprecated
00375 BaseType *
00376 Sequence::var(const string &n, btp_stack &s)
00377 {
00378     string name = www2id(n);
00379 
00380     BaseType *btp = m_exact_match(name, &s);
00381     if (btp)
00382         return btp;
00383 
00384     return m_leaf_match(name, &s);
00385 }
00386 
00387 BaseType *
00388 Sequence::var(const string &name, bool exact_match, btp_stack *s)
00389 {
00390     string n = www2id(name);
00391 
00392     if (exact_match)
00393         return m_exact_match(n, s);
00394     else
00395         return m_leaf_match(n, s);
00396 }
00397 
00398 BaseType *
00399 Sequence::m_leaf_match(const string &name, btp_stack *s)
00400 {
00401     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00402         if ((*i)->name() == name) {
00403             if (s)
00404                 s->push(static_cast<BaseType *>(this));
00405             return *i;
00406         }
00407         if ((*i)->is_constructor_type()) {
00408             BaseType *btp = (*i)->var(name, false, s);
00409             if (btp) {
00410                 if (s)
00411                     s->push(static_cast<BaseType *>(this));
00412                 return btp;
00413             }
00414         }
00415     }
00416 
00417     return 0;
00418 }
00419 
00420 BaseType *
00421 Sequence::m_exact_match(const string &name, btp_stack *s)
00422 {
00423     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00424         if ((*i)->name() == name) {
00425             if (s)
00426                 s->push(static_cast<BaseType *>(this));
00427             return *i;
00428         }
00429     }
00430 
00431     string::size_type dot_pos = name.find("."); // zero-based index of `.'
00432     if (dot_pos != string::npos) {
00433         string aggregate = name.substr(0, dot_pos);
00434         string field = name.substr(dot_pos + 1);
00435 
00436         BaseType *agg_ptr = var(aggregate);
00437         if (agg_ptr) {
00438             if (s)
00439                 s->push(static_cast<BaseType *>(this));
00440             return agg_ptr->var(field, true, s); // recurse
00441         }
00442         else
00443             return 0;  // qualified names must be *fully* qualified
00444     }
00445 
00446     return 0;
00447 }
00448 
00453 BaseTypeRow *
00454 Sequence::row_value(size_t row)
00455 {
00456     if (row >= d_values.size())
00457         return 0;
00458     return d_values[row];
00459 }
00460 
00467 void
00468 Sequence::set_value(SequenceValues &values)
00469 {
00470     d_values = values;
00471 }
00472 
00475 SequenceValues
00476 Sequence::value()
00477 {
00478     return d_values;
00479 }
00480 
00486 BaseType *
00487 Sequence::var_value(size_t row, const string &name)
00488 {
00489     BaseTypeRow *bt_row_ptr = row_value(row);
00490     if (!bt_row_ptr)
00491         return 0;
00492 
00493     BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
00494     BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
00495     while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
00496         ++bt_row_iter;
00497 
00498     if (bt_row_iter == bt_row_end)
00499         return 0;
00500     else
00501         return *bt_row_iter;
00502 }
00503 
00509 BaseType *
00510 Sequence::var_value(size_t row, size_t i)
00511 {
00512     BaseTypeRow *bt_row_ptr = row_value(row);
00513     if (!bt_row_ptr)
00514         return 0;
00515 
00516     if (i >= bt_row_ptr->size())
00517         return 0;
00518 
00519     return (*bt_row_ptr)[i];
00520 }
00521 
00522 unsigned int
00523 Sequence::width()
00524 {
00525     unsigned int sz = 0;
00526 
00527     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00528         sz += (*i)->width();
00529     }
00530 
00531     return sz;
00532 }
00533 
00541 unsigned int
00542 Sequence::width(bool constrained)
00543 {
00544     unsigned int sz = 0;
00545 
00546     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00547         if (constrained) {
00548                 if ((*i)->send_p())
00549                         sz += (*i)->width(constrained);
00550         }
00551         else {
00552                 sz += (*i)->width(constrained);
00553         }
00554     }
00555 
00556     return sz;
00557 }
00558 
00559 // This version returns -1. Each API-specific subclass should define a more
00560 // reasonable version. jhrg 5/24/96
00561 
00577 int
00578 Sequence::length()
00579 {
00580     return -1;
00581 }
00582 
00583 
00584 int
00585 Sequence::number_of_rows()
00586 {
00587     return d_values.size();
00588 }
00589 
00593 void
00594 Sequence::reset_row_number()
00595 {
00596     d_row_number = -1;
00597 }
00598 
00599 // Notes:
00600 // Assume that read() is implemented so that, when reading data for a nested
00601 // sequence, only the outer most level is *actually* read.
00602 // This is a consequence of our current (12/7/99) implementation of
00603 // the JGOFS server (which is the only server to actually use nested
00604 // sequences). 12/7/99 jhrg
00605 //
00606 // Stop assuming this. This logic is being moved into the JGOFS server
00607 // itself. 6/1/2001 jhrg
00608 
00609 // The read() function returns a boolean value, with TRUE
00610 // indicating that read() should be called again because there's
00611 // more data to read, and FALSE indicating there's no more data
00612 // to read. Note that this behavior is necessary to properly
00613 // handle variables that contain Sequences. Jose Garcia If an
00614 // error exists while reading, the implementers of the surrogate
00615 // library SHOULD throw an Error object which will propagate
00616 // beyond this point to to the original caller.
00617 // Jose Garcia
00618 
00651 bool
00652 Sequence::read_row(int row, DDS &dds,
00653                    ConstraintEvaluator &eval, bool ce_eval)
00654 {
00655     DBG2(cerr << "Entering Sequence::read_row for " << name() << endl);
00656     if (row < d_row_number)
00657         throw InternalErr("Trying to back up inside a sequence!");
00658 
00659     DBG2(cerr << "read_row: row number " << row
00660               << ", current row " << d_row_number << endl);
00661     if (row == d_row_number)
00662     {
00663         DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
00664         return true;
00665     }
00666 
00667     dds.timeout_on();
00668 
00669     int eof = 0;  // Start out assuming EOF is false.
00670     while (!eof && d_row_number < row) {
00671         if (!read_p()) {
00672             eof = (read() == false);
00673         }
00674 
00675         // Advance the row number if ce_eval is false (we're not supposed to
00676         // evaluate the selection) or both ce_eval and the selection are
00677         // true.
00678         if (!eof && (!ce_eval || eval.eval_selection(dds, dataset())))
00679             d_row_number++;
00680 
00681         set_read_p(false); // ...so that the next instance will be read
00682     }
00683 
00684     // Once we finish the above loop, set read_p to true so that the caller
00685     // knows that data *has* been read. This is how the read() methods of the
00686     // elements of the sequence know to not call read() but instead look for
00687     // data values inside themselves.
00688     set_read_p(true);
00689 
00690     dds.timeout_off();
00691 
00692     // Return true if we have valid data, false if we've read to the EOF.
00693     DBG2(cerr << "Leaving Sequence::read_row for " << name()
00694               << " with " << (eof == 0) << endl);
00695     return eof == 0;
00696 }
00697 
00698 // Private. This is used to process constraints on the rows of a sequence.
00699 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
00700 // odd-looking logic first checks if d_ending_row_number is the sentinel
00701 // value of -1. If so, the sequence was not constrained by row number and
00702 // this method should never return true (which indicates that we're at the
00703 // end of a row-number constraint). If d_ending_row_number is not -1, then is
00704 // \e i at the end point? 6/1/2001 jhrg
00705 inline bool
00706 Sequence::is_end_of_rows(int i)
00707 {
00708     return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
00709 }
00710 
00771 bool
00772 Sequence::serialize(ConstraintEvaluator &eval, DDS &dds,
00773                     Marshaller &m, bool ce_eval)
00774 {
00775     DBG2(cerr << "Entering Sequence::serialize for " << name() << endl);
00776 
00777     // Special case leaf sequences!
00778     if (is_leaf_sequence())
00779         return serialize_leaf(dds, eval, m, ce_eval);
00780     else
00781         return serialize_parent_part_one(dds, eval, m);
00782 }
00783 
00784 // We know this is not a leaf Sequence. That means that this Sequence holds
00785 // another Sequence as one of its fields _and_ that child Sequence triggers
00786 // the actual transmission of values.
00787 
00788 bool
00789 Sequence::serialize_parent_part_one(DDS &dds,
00790                                     ConstraintEvaluator &eval, Marshaller &m)
00791 {
00792     DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
00793 
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     // Since this is a parent sequence, read the row ignoring the CE (all of
00799     // the CE clauses will be evaluated by the leaf sequence).
00800     bool status = read_row(i, dds, eval, false);
00801     DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
00802 
00803     while (status && !is_end_of_rows(i)) {
00804         i += d_row_stride;
00805 
00806         // DBG(cerr << "Writing Start of Instance marker" << endl);
00807         // write_start_of_instance(sink);
00808 
00809         // In this loop serialize will signal an error with an exception.
00810         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00811             // Only call serialize for child Sequences; the leaf sequence
00812             // will trigger the transmission of values for its parents (this
00813             // sequence and maybe others) once it gets soem valid data to
00814             // send.
00815             // Note that if the leaf sequence has no variables in the current
00816             // projection, its serialize() method will never be called and that's
00817             // the method that triggers actually sending values. Thus the leaf
00818             // sequence must be the lowest level sequence with values whose send_p
00819             // property is true.
00820             if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c)
00821                 (*iter)->serialize(eval, dds, m);
00822         }
00823 
00824         set_read_p(false); // ...so this will read the next instance
00825 
00826         status = read_row(i, dds, eval, false);
00827         DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
00828     }
00829     // Reset current row number for next nested sequence element.
00830     d_row_number = -1;
00831 
00832     // Always write the EOS marker? 12/23/04 jhrg
00833     // Yes. According to DAP2, a completely empty response is signalled by
00834     // a return value of only the EOS marker for the outermost sequence.
00835     if (d_top_most || d_wrote_soi) {
00836         DBG(cerr << "Writing End of Sequence marker" << endl);
00837         write_end_of_sequence(m);
00838         d_wrote_soi = false;
00839     }
00840 
00841     return true;  // Signal errors with exceptions.
00842 }
00843 
00844 // If we are here then we know that this is 'parent sequence' and that the
00845 // leaf seq has found valid data to send. We also know that
00846 // serialize_parent_part_one has been called so data are in the instance's
00847 // fields. This is wheree we send data. Whereas ..._part_one() contains a
00848 // loop to iterate over all of rows in a parent sequence, this does not. This
00849 // method assumes that the serialize_leaf() will call it each time it needs
00850 // to be called.
00851 //
00852 // NB: This code only works if the child sequences appear after all other
00853 // variables.
00854 void
00855 Sequence::serialize_parent_part_two(DDS &dds,
00856                                     ConstraintEvaluator &eval, Marshaller &m)
00857 {
00858     DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
00859 
00860     BaseType *btp = get_parent();
00861     if (btp && btp->type() == dods_sequence_c)
00862         dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
00863 
00864     if (d_unsent_data) {
00865         DBG(cerr << "Writing Start of Instance marker" << endl);
00866         d_wrote_soi = true;
00867         write_start_of_instance(m);
00868 
00869         // In this loop serialize will signal an error with an exception.
00870         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00871             // Send all the non-sequence variables
00872             DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
00873                 << (*iter)->name() << endl);
00874             if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
00875                 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
00876                 (*iter)->serialize(eval, dds, m, false);
00877             }
00878         }
00879 
00880         d_unsent_data = false;              // read should set this.
00881     }
00882 }
00883 
00884 // This code is only run by a leaf sequence. Note that a one level sequence
00885 // is also a leaf sequence.
00886 bool
00887 Sequence::serialize_leaf(DDS &dds,
00888                          ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
00889 {
00890     DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
00891     int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
00892 
00893     // read_row returns true if valid data was read, false if the EOF was
00894     // found. 6/1/2001 jhrg
00895     bool status = read_row(i, dds, eval, ce_eval);
00896     DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
00897 
00898     // Once the first valid (satisfies the CE) row of the leaf sequence has
00899     // been read, we know we're going to send data. Send the current instance
00900     // of the parent/ancestor sequences now, if there are any. We only need
00901     // to do this once, hence it's not inside the while loop, but we only
00902     // send the parent seq data _if_ there's data in the leaf to send, that's
00903     // why we wait until after the first call to read_row() here in the leaf
00904     // sequence.
00905     //
00906     // NB: It's important to only call serialize_parent_part_two() for a
00907     // Sequence that really is the parent of a leaf sequence. The fancy cast
00908     // will throw and exception if btp is not a Sequence, but doesn't test
00909     // that it's a parent sequence as we've defined them here.
00910     if (status && !is_end_of_rows(i)) {
00911         BaseType *btp = get_parent();
00912         if (btp && btp->type() == dods_sequence_c)
00913             dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds,
00914                                                                     eval, m);
00915     }
00916 
00917     d_wrote_soi = false;
00918     while (status && !is_end_of_rows(i)) {
00919         i += d_row_stride;
00920 
00921         DBG(cerr << "Writing Start of Instance marker" << endl);
00922         d_wrote_soi = true;
00923         write_start_of_instance(m);
00924 
00925         // In this loop serialize will signal an error with an exception.
00926         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00927             DBG(cerr << "Sequence::serialize_leaf(), serializing "
00928                 << (*iter)->name() << endl);
00929             if ((*iter)->send_p()) {
00930                 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
00931                 (*iter)->serialize(eval, dds, m, false);
00932             }
00933         }
00934 
00935         set_read_p(false); // ...so this will read the next instance
00936 
00937         status = read_row(i, dds, eval, ce_eval);
00938         DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
00939     }
00940 
00941     // Only write the EOS marker if there's a matching Start Of Instnace
00942     // Marker in the stream.
00943     if (d_wrote_soi || d_top_most) {
00944         DBG(cerr << "Writing End of Sequence marker" << endl);
00945         write_end_of_sequence(m);
00946     }
00947 
00948     return true;  // Signal errors with exceptions.
00949 }
00950 
00973 void
00974 Sequence::intern_data(ConstraintEvaluator &eval, DDS &dds)
00975 {
00976     DBG(cerr << "Sequence::intern_data - for " << name() << endl);
00977     DBG2(cerr << "    intern_data, values: " << &d_values << endl);
00978 
00979     // Why use a stack instead of return values? We need the stack because
00980     // Sequences neted three of more levels deep will loose the middle
00981     // instances when the intern_data_parent_part_two() code is run.
00982     sequence_values_stack_t sequence_values_stack;
00983 
00984     DBG2(cerr << "    pushing d_values of " << name() << " (" << &d_values
00985               << ") on stack; size: " << sequence_values_stack.size() << endl);
00986     sequence_values_stack.push(&d_values);
00987 
00988     intern_data_private(eval, dds, sequence_values_stack);
00989 }
00990 
00991 void
00992 Sequence::intern_data_private(ConstraintEvaluator &eval,
00993                               DDS &dds,
00994                               sequence_values_stack_t &sequence_values_stack)
00995 {
00996     DBG(cerr << "Entering intern_data_private for " << name() << endl);
00997 
00998     if (is_leaf_sequence())
00999         intern_data_for_leaf(dds, eval, sequence_values_stack);
01000     else
01001         intern_data_parent_part_one(dds, eval, sequence_values_stack);
01002 }
01003 
01004 void
01005 Sequence::intern_data_parent_part_one(DDS & dds,
01006                                       ConstraintEvaluator & eval,
01007                                       sequence_values_stack_t &
01008                                       sequence_values_stack)
01009 {
01010     DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
01011 
01012     int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
01013 
01014     // read_row returns true if valid data was read, false if the EOF was
01015     // found. 6/1/2001 jhrg
01016     // Since this is a parent sequence, read the row ignoring the CE (all of
01017     // the CE clauses will be evaluated by the leaf sequence).
01018     bool status = read_row(i, dds, eval, false);
01019 
01020     // Grab the current size of the value stack. We do this because it is
01021     // possible that no nested sequences for this row happened to be
01022     // selected because of a constract evaluation or the last row is not
01023     // selected because of a constraint evaluation. In either case, no
01024     // nested sequence d_values are pused onto the stack, so there is
01025     // nothing to pop at the end of this function. pcw 07/14/08
01026     SequenceValues::size_type orig_stack_size = sequence_values_stack.size() ;
01027 
01028     while (status
01029            && (get_ending_row_number() == -1
01030                || i <= get_ending_row_number()))
01031     {
01032         i += get_row_stride();
01033         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
01034             if ((*iter)->send_p()) {
01035                 switch ((*iter)->type()) {
01036                 case dods_sequence_c:
01037                     dynamic_cast<Sequence&>(**iter).intern_data_private(
01038                             eval, dds, sequence_values_stack);
01039                     break;
01040 
01041                 default:
01042                     (*iter)->intern_data(eval, dds);
01043                     break;
01044                 }
01045             }
01046         }
01047 
01048         set_read_p(false);      // ...so this will read the next instance
01049 
01050         status = read_row(i, dds, eval, false);
01051     }
01052 
01053     // Reset current row number for next nested sequence element.
01054     reset_row_number();
01055 
01056     // if the size of the stack is larger than the original size (retrieved
01057     // above) then pop the top set of d_values from the stack. If it's the
01058     // same, then no nested sequences, or possible the last nested sequence,
01059     // were pushed onto the stack, so there is nothing to pop.
01060     if( sequence_values_stack.size() > orig_stack_size )
01061     {
01062         DBG2(cerr << "    popping d_values (" << sequence_values_stack.top()
01063              << ") off stack; size: " << sequence_values_stack.size() << endl);
01064         sequence_values_stack.pop();
01065     }
01066     DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
01067 }
01068 
01069 void
01070 Sequence::intern_data_parent_part_two(DDS &dds,
01071                               ConstraintEvaluator &eval,
01072                               sequence_values_stack_t &sequence_values_stack)
01073 {
01074     DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
01075 
01076     BaseType *btp = get_parent();
01077     if (btp && btp->type() == dods_sequence_c) {
01078         dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two(
01079                                       dds, eval, sequence_values_stack);
01080     }
01081 
01082     DBG2(cerr << "    stack size: " << sequence_values_stack.size() << endl);
01083     SequenceValues *values = sequence_values_stack.top();
01084     DBG2(cerr << "    using values = " << (void *)values << endl);
01085 
01086     if (get_unsent_data()) {
01087         BaseTypeRow *row_data = new BaseTypeRow;
01088 
01089         // In this loop transfer_data will signal an error with an exception.
01090         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
01091 
01092             if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
01093                 row_data->push_back((*iter)->ptr_duplicate());
01094             }
01095             else if ((*iter)->send_p()) { //Sequence; must be the last variable
01096                 Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
01097                 if (!tmp) {
01098                         delete row_data;
01099                     throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
01100                 }
01101                 row_data->push_back(tmp);
01102                 DBG2(cerr << "    pushing d_values of " << tmp->name()
01103                      << " (" << &(tmp->d_values)
01104                      << ") on stack; size: " << sequence_values_stack.size()
01105                      << endl);
01106                 // This pushes the d_values field of the newly created leaf
01107                 // Sequence onto the stack. The code then returns to intern
01108                 // _data_for_leaf() where this value will be used.
01109                 sequence_values_stack.push(&(tmp->d_values));
01110             }
01111         }
01112 
01113         DBG2(cerr << "    pushing values for " << name()
01114                   << " to " << values << endl);
01115         values->push_back(row_data);
01116         set_unsent_data(false);
01117     }
01118     DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
01119 }
01120 
01121 void
01122 Sequence::intern_data_for_leaf(DDS &dds,
01123                                ConstraintEvaluator &eval,
01124                                sequence_values_stack_t &sequence_values_stack)
01125 {
01126     DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
01127 
01128     int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
01129 
01130     DBG2(cerr << "    reading row " << i << endl);
01131     bool status = read_row(i, dds, eval, true);
01132     DBG2(cerr << "    status: " << status << endl);
01133     DBG2(cerr << "    ending row number: " << get_ending_row_number() << endl);
01134 
01135     if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
01136         BaseType *btp = get_parent();
01137         if (btp && btp->type() == dods_sequence_c) {
01138             // This call will read the values for the parent sequences and
01139             // then allocate a new instance for the leaf and push that onto
01140             // the stack.
01141             dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two(
01142                                             dds, eval, sequence_values_stack);
01143         }
01144 
01145         // intern_data_parent_part_two pushes the d_values field of the leaf
01146         // onto the stack, so this operation grabs that value and then loads
01147         // data into it.
01148         SequenceValues *values = sequence_values_stack.top();
01149         DBG2(cerr << "    using values = " << values << endl);
01150 
01151         while (status && (get_ending_row_number() == -1
01152                           || i <= get_ending_row_number())) {
01153             i += get_row_stride();
01154 
01155             // Copy data from the object's fields to this new BaeTypeRow instance
01156             BaseTypeRow *row_data = new BaseTypeRow;
01157             for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
01158                 if ((*iter)->send_p()) {
01159                     row_data->push_back((*iter)->ptr_duplicate());
01160                 }
01161             }
01162 
01163             DBG2(cerr << "    pushing values for " << name()
01164                       << " to " << values << endl);
01165             // Save the row_data to values().
01166             values->push_back(row_data);
01167 
01168             set_read_p(false);      // ...so this will read the next instance
01169             // Read the ith row into this object's fields
01170             status = read_row(i, dds, eval, true);
01171         }
01172 
01173         DBG2(cerr << "    popping d_values (" << sequence_values_stack.top()
01174              << ") off stack; size: " << sequence_values_stack.size() << endl);
01175         sequence_values_stack.pop();
01176     }
01177     DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
01178 }
01179 
01200 bool
01201 Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
01202 {
01203     DataDDS *dd = dynamic_cast<DataDDS *>(dds);
01204     if (!dd)
01205         throw InternalErr("Expected argument 'dds' to be a DataDDS!");
01206 
01207     DBG2(cerr << "Reading from server/protocol version: "
01208          << dd->get_protocol_major() << "." << dd->get_protocol_minor()
01209          << endl);
01210 
01211     // Check for old servers.
01212     if (dd->get_protocol_major() < 2) {
01213         throw Error(string("The protocl version (") + dd->get_protocol()
01214                     + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
01215     }
01216 
01217     while (true) {
01218         // Grab the sequence stream's marker.
01219         unsigned char marker = read_marker(um);
01220         if (is_end_of_sequence(marker))
01221             break;  // EXIT the while loop here!!!
01222         else if (is_start_of_instance(marker)) {
01223             d_row_number++;
01224             DBG2(cerr << "Reading row " << d_row_number << " of "
01225                  << name() << endl);
01226             BaseTypeRow *bt_row_ptr = new BaseTypeRow;
01227             // Read the instance's values, building up the row
01228             for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
01229                 BaseType *bt_ptr = (*iter)->ptr_duplicate();
01230                 bt_ptr->deserialize(um, dds, reuse);
01231                 DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
01232                      << bt_ptr << ") = ");
01233                 DBG2(bt_ptr->print_val(stderr, ""));
01234                 bt_row_ptr->push_back(bt_ptr);
01235             }
01236             // Append this row to those accumulated.
01237             d_values.push_back(bt_row_ptr);
01238         }
01239         else
01240             throw Error("I could not read the expected Sequence data stream marker!");
01241     };
01242 
01243     return false;
01244 }
01245 
01246 // Return the current row number.
01247 
01259 int
01260 Sequence::get_starting_row_number()
01261 {
01262     return d_starting_row_number;
01263 }
01264 
01275 int
01276 Sequence::get_row_stride()
01277 {
01278     return d_row_stride;
01279 }
01280 
01292 int
01293 Sequence::get_ending_row_number()
01294 {
01295     return d_ending_row_number;
01296 }
01297 
01306 void
01307 Sequence::set_row_number_constraint(int start, int stop, int stride)
01308 {
01309     if (stop < start)
01310         throw Error(malformed_expr, "Starting row number must precede the ending row number.");
01311 
01312     d_starting_row_number = start;
01313     d_row_stride = stride;
01314     d_ending_row_number = stop;
01315 }
01316 
01319 unsigned int
01320 Sequence::val2buf(void *, bool)
01321 {
01322     throw InternalErr(__FILE__, __LINE__, "Never use this method; see the programmer's guide documentation.");
01323     return sizeof(Sequence);
01324 }
01325 
01330 unsigned int
01331 Sequence::buf2val(void **)
01332 {
01333     throw InternalErr(__FILE__, __LINE__, "Use Sequence::var_value() or Sequence::row_value() in place of Sequence::buf2val()");
01334     return sizeof(Sequence);
01335 }
01336 
01337 #if FILE_METHODS
01338 void
01339 Sequence::print_one_row(FILE *out, int row, string space,
01340                         bool print_row_num)
01341 {
01342     if (print_row_num)
01343         fprintf(out, "\n%s%d: ", space.c_str(), row) ;
01344 
01345     fprintf(out, "{ ") ;
01346 
01347     int elements = element_count() - 1;
01348     int j;
01349     BaseType *bt_ptr;
01350     // Print first N-1 elements of the row.
01351     for (j = 0; j < elements; ++j) {
01352         bt_ptr = var_value(row, j);
01353         if (bt_ptr) {  // data
01354             if (bt_ptr->type() == dods_sequence_c)
01355                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01356                 (out, space + "    ", false, print_row_num);
01357             else
01358                 bt_ptr->print_val(out, space, false);
01359             fprintf(out, ", ") ;
01360         }
01361     }
01362 
01363     // Print Nth element; end with a `}.'
01364     bt_ptr = var_value(row, j);
01365     if (bt_ptr) {  // data
01366         if (bt_ptr->type() == dods_sequence_c)
01367             dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01368             (out, space + "    ", false, print_row_num);
01369         else
01370             bt_ptr->print_val(out, space, false);
01371     }
01372 
01373     fprintf(out, " }") ;
01374 }
01375 #endif
01376 
01377 void
01378 Sequence::print_one_row(ostream &out, int row, string space,
01379                         bool print_row_num)
01380 {
01381     if (print_row_num)
01382         out << "\n" << space << row << ": " ;
01383 
01384     out << "{ " ;
01385 
01386     int elements = element_count();
01387     int j = 0;
01388     BaseType *bt_ptr = 0;
01389 
01390     // This version of print_one_row() works for both data read with
01391     // deserialize(), where each variable is assumed to have valid data, and
01392     // intern_data(), where some/many variables do not. Because of that, it's
01393     // not correct to assume that all of the elements will be printed, which
01394     // is what the old code did.
01395     // Print the first value
01396     while (j < elements && !bt_ptr) {
01397         bt_ptr = var_value(row, j++);
01398         if (bt_ptr) {  // data
01399             if (bt_ptr->type() == dods_sequence_c)
01400                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01401                      (out, space + "    ", false, print_row_num);
01402             else
01403                 bt_ptr->print_val(out, space, false);
01404         }
01405     }
01406 
01407     // Print the remaining values
01408     while (j < elements) {
01409         bt_ptr = var_value(row, j++);
01410         if (bt_ptr) {  // data
01411             out << ", ";
01412             if (bt_ptr->type() == dods_sequence_c)
01413                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01414                         (out, space + "    ", false, print_row_num);
01415             else
01416                 bt_ptr->print_val(out, space, false);
01417         }
01418     }
01419 
01420     out << " }" ;
01421 }
01422 
01423 #if FILE_METHODS
01424 void
01425 Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p,
01426                             bool print_row_numbers)
01427 {
01428     if (print_decl_p) {
01429         print_decl(out, space, false);
01430         fprintf(out, " = ") ;
01431     }
01432 
01433     fprintf(out, "{ ") ;
01434 
01435     int rows = number_of_rows() - 1;
01436     int i;
01437     for (i = 0; i < rows; ++i) {
01438         print_one_row(out, i, space, print_row_numbers);
01439         fprintf(out, ", ") ;
01440     }
01441     print_one_row(out, i, space, print_row_numbers);
01442 
01443     fprintf(out, " }") ;
01444 
01445     if (print_decl_p)
01446         fprintf(out, ";\n") ;
01447 }
01448 #endif
01449 
01450 void
01451 Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p,
01452                             bool print_row_numbers)
01453 {
01454     if (print_decl_p) {
01455         print_decl(out, space, false);
01456         out << " = " ;
01457     }
01458 
01459     out << "{ " ;
01460 
01461     int rows = number_of_rows() - 1;
01462     int i;
01463     for (i = 0; i < rows; ++i) {
01464         print_one_row(out, i, space, print_row_numbers);
01465         out << ", " ;
01466     }
01467     print_one_row(out, i, space, print_row_numbers);
01468 
01469     out << " }" ;
01470 
01471     if (print_decl_p)
01472         out << ";\n" ;
01473 }
01474 
01475 #if FILE_METHODS
01476 void
01477 Sequence::print_val(FILE *out, string space, bool print_decl_p)
01478 {
01479     print_val_by_rows(out, space, print_decl_p, false);
01480 }
01481 #endif
01482 
01483 void
01484 Sequence::print_val(ostream &out, string space, bool print_decl_p)
01485 {
01486     print_val_by_rows(out, space, print_decl_p, false);
01487 }
01488 
01489 
01490 bool
01491 Sequence::check_semantics(string &msg, bool all)
01492 {
01493     if (!BaseType::check_semantics(msg))
01494         return false;
01495 
01496     if (!unique_names(_vars, name(), type_name(), msg))
01497         return false;
01498 
01499     if (all)
01500         for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
01501             if (!(*i)->check_semantics(msg, true)) {
01502                 return false;
01503             }
01504         }
01505 
01506     return true;
01507 }
01508 
01509 void
01510 Sequence::set_leaf_p(bool state)
01511 {
01512     d_leaf_sequence = state;
01513 }
01514 
01515 bool
01516 Sequence::is_leaf_sequence()
01517 {
01518     return d_leaf_sequence;
01519 }
01520 
01545 void
01546 Sequence::set_leaf_sequence(int lvl)
01547 {
01548     bool has_child_sequence = false;
01549 
01550     if (lvl == 1) d_top_most = true;
01551 
01552     DBG2(cerr << "Processing sequence " << name() << endl);
01553 
01554     for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
01555         // About the test for send_p(): Only descend into a sequence if it has
01556         // fields that might be sent. Thus if, in a two-level sequence, nothing
01557         // in the lower level is to be sent, the upper level is marked as the
01558         // leaf sequence. This ensures that values _will_ be sent (see the comment
01559         // in serialize_leaf() and serialize_parent_part_one()).
01560         if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
01561             if (has_child_sequence)
01562                 throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
01563 
01564             has_child_sequence = true;
01565             dynamic_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
01566         }
01567         else if ((*iter)->type() == dods_structure_c) {
01568             dynamic_cast<Structure&>(**iter).set_leaf_sequence(lvl);
01569         }
01570     }
01571 
01572     if (!has_child_sequence)
01573         set_leaf_p(true);
01574     else
01575         set_leaf_p(false);
01576 
01577     DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
01578 }
01579 
01588 void
01589 Sequence::dump(ostream &strm) const
01590 {
01591     strm << DapIndent::LMarg << "Sequence::dump - ("
01592     << (void *)this << ")" << endl ;
01593     DapIndent::Indent() ;
01594     Constructor::dump(strm) ;
01595     strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number
01596          << endl ;
01597     strm << DapIndent::LMarg << "bracket notation information:" << endl ;
01598     DapIndent::Indent() ;
01599     strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number
01600          << endl ;
01601     strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl ;
01602     strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number
01603          << endl ;
01604     DapIndent::UnIndent() ;
01605 
01606     strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl ;
01607     strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl ;
01608     strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence
01609          << endl ;
01610     strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most
01611          << endl ;
01612     DapIndent::UnIndent() ;
01613 }
01614 
01615 } // namespace libdap
01616