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 "debug.h"
00046 #include "Error.h"
00047 #include "InternalErr.h"
00048 #include "Sequence.h"
00049 #include "DDS.h"
00050 #include "DataDDS.h"
00051 #include "util.h"
00052 #include "InternalErr.h"
00053 #include "escaping.h"
00054 
00055 using namespace std;
00056 
00057 namespace libdap {
00058 
00059 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101
00060 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010
00061 
00062 // Private member functions
00063 
00064 void
00065 Sequence::_duplicate(const Sequence &s)
00066 {
00067     d_row_number = s.d_row_number;
00068     d_starting_row_number = s.d_starting_row_number;
00069     d_ending_row_number = s.d_ending_row_number;
00070     d_row_stride = s.d_row_stride;
00071     d_leaf_sequence = s.d_leaf_sequence;
00072     d_unsent_data = s.d_unsent_data;
00073     d_wrote_soi = s.d_wrote_soi;
00074     d_top_most = s.d_top_most;
00075 
00076     Sequence &cs = const_cast<Sequence &>(s);
00077 
00078     // Copy the template BaseType objects.
00079     for (Vars_iter i = cs.var_begin(); i != cs.var_end(); i++) {
00080         add_var((*i)) ;
00081     }
00082 
00083     // Copy the BaseType objects used to hold values.
00084     for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin();
00085          rows_iter != cs.d_values.end();
00086          rows_iter++) {
00087         // Get the current BaseType Row
00088         BaseTypeRow *src_bt_row_ptr = *rows_iter;
00089         // Create a new row.
00090         BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow;
00091         // Copy the BaseType objects from a row to new BaseType objects.
00092         // Push new BaseType objects onto new row.
00093         for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin();
00094              bt_row_iter != src_bt_row_ptr->end();
00095              bt_row_iter++) {
00096             BaseType *src_bt_ptr = *bt_row_iter;
00097             BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate();
00098             dest_bt_row_ptr->push_back(dest_bt_ptr);
00099         }
00100         // Push new row onto d_values.
00101         d_values.push_back(dest_bt_row_ptr);
00102     }
00103 }
00104 
00105 static void
00106 write_end_of_sequence(Marshaller &m)
00107 {
00108     m.put_opaque( (char *)&end_of_sequence, 1 ) ;
00109 }
00110 
00111 static void
00112 write_start_of_instance(Marshaller &m)
00113 {
00114     m.put_opaque( (char *)&start_of_instance, 1 ) ;
00115 }
00116 
00117 static unsigned char
00118 read_marker(UnMarshaller &um)
00119 {
00120     unsigned char marker;
00121     um.get_opaque( (char *)&marker, 1 ) ;
00122 
00123     return marker;
00124 }
00125 
00126 static bool
00127 is_start_of_instance(unsigned char marker)
00128 {
00129     return (marker == start_of_instance);
00130 }
00131 
00132 static bool
00133 is_end_of_sequence(unsigned char marker)
00134 {
00135     return (marker == end_of_sequence);
00136 }
00137 
00138 // Public member functions
00139 
00148 Sequence::Sequence(const string &n) : Constructor(n, dods_sequence_c),
00149         d_row_number(-1), d_starting_row_number(-1),
00150         d_row_stride(1), d_ending_row_number(-1),
00151         d_unsent_data(false), d_wrote_soi(false),
00152         d_leaf_sequence(false), d_top_most(false)
00153 {}
00154 
00165 Sequence::Sequence(const string &n, const string &d)
00166     : Constructor(n, d, dods_sequence_c),
00167       d_row_number(-1), d_starting_row_number(-1),
00168       d_row_stride(1), d_ending_row_number(-1),
00169       d_unsent_data(false), d_wrote_soi(false),
00170       d_leaf_sequence(false), d_top_most(false)
00171 {}
00172 
00174 Sequence::Sequence(const Sequence &rhs) : Constructor(rhs)
00175 {
00176     _duplicate(rhs);
00177 }
00178 
00179 BaseType *
00180 Sequence::ptr_duplicate()
00181 {
00182     return new Sequence(*this);
00183 }
00184 
00185 static inline void
00186 delete_bt(BaseType *bt_ptr)
00187 {
00188     DBG2(cerr << "In delete_bt: " << bt_ptr << endl);
00189     delete bt_ptr; bt_ptr = 0;
00190 }
00191 
00192 static inline void
00193 delete_rows(BaseTypeRow *bt_row_ptr)
00194 {
00195     DBG2(cerr << "In delete_rows: " << bt_row_ptr << endl);
00196 
00197     for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
00198 
00199     delete bt_row_ptr; bt_row_ptr = 0;
00200 }
00201 
00202 Sequence::~Sequence()
00203 {
00204     DBG2(cerr << "Entering Sequence::~Sequence" << endl);
00205     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00206         BaseType *btp = *i ;
00207         delete btp ; btp = 0;
00208     }
00209 
00210     for_each(d_values.begin(), d_values.end(), delete_rows);
00211     DBG2(cerr << "exiting Sequence::~Sequence" << endl);
00212 }
00213 
00214 Sequence &
00215 Sequence::operator=(const Sequence &rhs)
00216 {
00217     if (this == &rhs)
00218         return *this;
00219 
00220     dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
00221 
00222     _duplicate(rhs);
00223 
00224     return *this;
00225 }
00226 
00227 string
00228 Sequence::toString()
00229 {
00230     ostringstream oss;
00231 
00232     oss << BaseType::toString();
00233 
00234     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00235         oss << (*i)->toString();
00236     }
00237 
00238     oss << endl;
00239 
00240     return oss.str();
00241 }
00242 
00243 int
00244 Sequence::element_count(bool leaves)
00245 {
00246     if (!leaves)
00247         return _vars.size();
00248     else {
00249         int i = 0;
00250         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00251             i += (*iter)->element_count(true);
00252         }
00253         return i;
00254     }
00255 }
00256 
00257 bool
00258 Sequence::is_linear()
00259 {
00260     bool linear = true;
00261     bool seq_found = false;
00262     for (Vars_iter iter = _vars.begin(); linear && iter != _vars.end(); iter++) {
00263         if ((*iter)->type() == dods_sequence_c) {
00264             // A linear sequence cannot have more than one child seq. at any
00265             // one level. If we've already found a seq at this level, return
00266             // false.
00267             if (seq_found) {
00268                 linear = false;
00269                 break;
00270             }
00271             seq_found = true;
00272             linear = dynamic_cast<Sequence *>((*iter))->is_linear();
00273         }
00274         else if ((*iter)->type() == dods_structure_c) {
00275             linear = dynamic_cast<Structure*>((*iter))->is_linear();
00276         }
00277         else {
00278             // A linear sequence cannot have Arrays, Lists or Grids.
00279             linear = (*iter)->is_simple_type();
00280         }
00281     }
00282 
00283     return linear;
00284 }
00285 
00286 void
00287 Sequence::set_send_p(bool state)
00288 {
00289     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00290         (*i)->set_send_p(state);
00291     }
00292 
00293     BaseType::set_send_p(state);
00294 }
00295 
00296 void
00297 Sequence::set_read_p(bool state)
00298 {
00299     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00300         (*i)->set_read_p(state);
00301     }
00302 
00303     BaseType::set_read_p(state);
00304 }
00305 
00306 void
00307 Sequence::set_in_selection(bool state)
00308 {
00309     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00310         (*i)->set_in_selection(state);
00311     }
00312 
00313     BaseType::set_in_selection(state);
00314 }
00315 
00325 void
00326 Sequence::add_var(BaseType *bt, Part)
00327 {
00328     if (!bt)
00329         throw InternalErr(__FILE__, __LINE__,
00330                           "Cannot add variable: NULL pointer");
00331     // Jose Garcia
00332     // We append a copy of bt so the owner of bt is free to deallocate
00333 
00334     BaseType *bt_copy = bt->ptr_duplicate();
00335     bt_copy->set_parent(this);
00336     _vars.push_back(bt_copy);
00337 }
00338 
00339 // Deprecated
00340 BaseType *
00341 Sequence::var(const string &n, btp_stack &s)
00342 {
00343     string name = www2id(n);
00344 
00345     BaseType *btp = m_exact_match(name, &s);
00346     if (btp)
00347         return btp;
00348 
00349     return m_leaf_match(name, &s);
00350 }
00351 
00352 BaseType *
00353 Sequence::var(const string &name, bool exact_match, btp_stack *s)
00354 {
00355     string n = www2id(name);
00356 
00357     if (exact_match)
00358         return m_exact_match(n, s);
00359     else
00360         return m_leaf_match(n, s);
00361 }
00362 
00363 BaseType *
00364 Sequence::m_leaf_match(const string &name, btp_stack *s)
00365 {
00366     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00367         if ((*i)->name() == name) {
00368             if (s)
00369                 s->push(static_cast<BaseType *>(this));
00370             return *i;
00371         }
00372         if ((*i)->is_constructor_type()) {
00373             BaseType *btp = (*i)->var(name, false, s);
00374             if (btp) {
00375                 if (s)
00376                     s->push(static_cast<BaseType *>(this));
00377                 return btp;
00378             }
00379         }
00380     }
00381 
00382     return 0;
00383 }
00384 
00385 BaseType *
00386 Sequence::m_exact_match(const string &name, btp_stack *s)
00387 {
00388     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00389         if ((*i)->name() == name) {
00390             if (s)
00391                 s->push(static_cast<BaseType *>(this));
00392             return *i;
00393         }
00394     }
00395 
00396     string::size_type dot_pos = name.find("."); // zero-based index of `.'
00397     if (dot_pos != string::npos) {
00398         string aggregate = name.substr(0, dot_pos);
00399         string field = name.substr(dot_pos + 1);
00400 
00401         BaseType *agg_ptr = var(aggregate);
00402         if (agg_ptr) {
00403             if (s)
00404                 s->push(static_cast<BaseType *>(this));
00405             return agg_ptr->var(field, true, s); // recurse
00406         }
00407         else
00408             return 0;  // qualified names must be *fully* qualified
00409     }
00410 
00411     return 0;
00412 }
00413 
00418 BaseTypeRow *
00419 Sequence::row_value(size_t row)
00420 {
00421     if (row >= d_values.size())
00422         return 0;
00423     return d_values[row];
00424 }
00425 
00432 void
00433 Sequence::set_value(SequenceValues &values)
00434 {
00435     d_values = values;
00436 }
00437 
00440 SequenceValues
00441 Sequence::value()
00442 {
00443     return d_values;
00444 }
00445 
00451 BaseType *
00452 Sequence::var_value(size_t row, const string &name)
00453 {
00454     BaseTypeRow *bt_row_ptr = row_value(row);
00455     if (!bt_row_ptr)
00456         return 0;
00457 
00458     BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
00459     BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
00460     while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
00461         ++bt_row_iter;
00462 
00463     if (bt_row_iter == bt_row_end)
00464         return 0;
00465     else
00466         return *bt_row_iter;
00467 }
00468 
00474 BaseType *
00475 Sequence::var_value(size_t row, size_t i)
00476 {
00477     BaseTypeRow *bt_row_ptr = row_value(row);
00478     if (!bt_row_ptr)
00479         return 0;
00480 
00481     if (i >= bt_row_ptr->size())
00482         return 0;
00483 
00484     return (*bt_row_ptr)[i];
00485 }
00486 
00487 unsigned int
00488 Sequence::width()
00489 {
00490     unsigned int sz = 0;
00491 
00492     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00493         sz += (*i)->width();
00494     }
00495 
00496     return sz;
00497 }
00498 
00499 // This version returns -1. Each API-specific subclass should define a more
00500 // reasonable version. jhrg 5/24/96
00501 
00517 int
00518 Sequence::length()
00519 {
00520     return -1;
00521 }
00522 
00523 
00524 int
00525 Sequence::number_of_rows()
00526 {
00527     return d_values.size();
00528 }
00529 
00533 void
00534 Sequence::reset_row_number()
00535 {
00536     d_row_number = -1;
00537 }
00538 
00539 // Notes:
00540 // Assume that read() is implemented so that, when reading data for a nested
00541 // sequence, only the outer most level is *actually* read.
00542 // This is a consequence of our current (12/7/99) implementation of
00543 // the JGOFS server (which is the only server to actually use nested
00544 // sequences). 12/7/99 jhrg
00545 //
00546 // Stop assuming this. This logic is being moved into the JGOFS server
00547 // itself. 6/1/2001 jhrg
00548 
00549 // The read() function returns a boolean value, with TRUE
00550 // indicating that read() should be called again because there's
00551 // more data to read, and FALSE indicating there's no more data
00552 // to read. Note that this behavior is necessary to properly
00553 // handle variables that contain Sequences. Jose Garcia If an
00554 // error exists while reading, the implementers of the surrogate
00555 // library SHOULD throw an Error object which will propagate
00556 // beyond this point to to the original caller.
00557 // Jose Garcia
00558 
00591 bool
00592 Sequence::read_row(int row, DDS &dds,
00593                    ConstraintEvaluator &eval, bool ce_eval)
00594 {
00595     DBG2(cerr << "Entering Sequence::read_row for " << name() << endl);
00596     if (row < d_row_number)
00597         throw InternalErr("Trying to back up inside a sequence!");
00598 
00599     DBG2(cerr << "read_row: row number " << row
00600               << ", current row " << d_row_number << endl);
00601     if (row == d_row_number)
00602     {
00603         DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
00604         return true;
00605     }
00606 
00607     dds.timeout_on();
00608 
00609     int eof = 0;  // Start out assuming EOF is false.
00610     while (!eof && d_row_number < row) {
00611         if (!read_p()) {
00612             eof = (read() == false);
00613         }
00614 
00615         // Advance the row number if ce_eval is false (we're not supposed to
00616         // evaluate the selection) or both ce_eval and the selection are
00617         // true.
00618         if (!eof && (!ce_eval || eval.eval_selection(dds, dataset())))
00619             d_row_number++;
00620 
00621         set_read_p(false); // ...so that the next instance will be read
00622     }
00623 
00624     // Once we finish the above loop, set read_p to true so that the caller
00625     // knows that data *has* been read. This is how the read() methods of the
00626     // elements of the sequence know to not call read() but instead look for
00627     // data values inside themselves.
00628     set_read_p(true);
00629 
00630     dds.timeout_off();
00631 
00632     // Return true if we have valid data, false if we've read to the EOF.
00633     DBG2(cerr << "Leaving Sequence::read_row for " << name()
00634               << " with " << (eof == 0) << endl);
00635     return eof == 0;
00636 }
00637 
00638 // Private. This is used to process constraints on the rows of a sequence.
00639 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
00640 // odd-looking logic first checks if d_ending_row_number is the sentinel
00641 // value of -1. If so, the sequence was not constrained by row number and
00642 // this method should never return true (which indicates that we're at the
00643 // end of a row-number constraint). If d_ending_row_number is not -1, then is
00644 // \e i at the end point? 6/1/2001 jhrg
00645 inline bool
00646 Sequence::is_end_of_rows(int i)
00647 {
00648     return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
00649 }
00650 
00711 bool
00712 Sequence::serialize(ConstraintEvaluator &eval, DDS &dds,
00713                     Marshaller &m, bool ce_eval)
00714 {
00715     DBG2(cerr << "Entering Sequence::serialize for " << name() << endl);
00716 
00717     // Special case leaf sequences!
00718     if (is_leaf_sequence())
00719         return serialize_leaf(dds, eval, m, ce_eval);
00720     else
00721         return serialize_parent_part_one(dds, eval, m);
00722 }
00723 
00724 // We know this is not a leaf Sequence. That means that this Sequence holds
00725 // another Sequence as one of its fields _and_ that child Sequence triggers
00726 // the actual transmission of values.
00727 
00728 bool
00729 Sequence::serialize_parent_part_one(DDS &dds,
00730                                     ConstraintEvaluator &eval, Marshaller &m)
00731 {
00732     DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
00733 
00734     int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
00735 
00736     // read_row returns true if valid data was read, false if the EOF was
00737     // found. 6/1/2001 jhrg
00738     // Since this is a parent sequence, read the row ignoring the CE (all of
00739     // the CE clauses will be evaluated by the leaf sequence).
00740     bool status = read_row(i, dds, eval, false);
00741     DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
00742 
00743     while (status && !is_end_of_rows(i)) {
00744         i += d_row_stride;
00745 
00746         // DBG(cerr << "Writing Start of Instance marker" << endl);
00747         // write_start_of_instance(sink);
00748 
00749         // In this loop serialize will signal an error with an exception.
00750         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00751             // Only call serialize for child Sequences; the leaf sequence
00752             // will trigger the transmission of values for its parents (this
00753             // sequence and maybe others) once it gets soem valid data to
00754             // send.
00755             // Note that if the leaf sequence has no variables in the current
00756             // projection, its serialize() method will never be called and that's
00757             // the method that triggers actually sending values. Thus the leaf
00758             // sequence must be the lowest level sequence with values whose send_p
00759             // property is true.
00760             if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c)
00761                 (*iter)->serialize(eval, dds, m);
00762         }
00763 
00764         set_read_p(false); // ...so this will read the next instance
00765 
00766         status = read_row(i, dds, eval, false);
00767         DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
00768     }
00769     // Reset current row number for next nested sequence element.
00770     d_row_number = -1;
00771 
00772     // Always write the EOS marker? 12/23/04 jhrg
00773     // Yes. According to DAP2, a completely empty response is signalled by
00774     // a return value of only the EOS marker for the outermost sequence.
00775     if (d_top_most || d_wrote_soi) {
00776         DBG(cerr << "Writing End of Sequence marker" << endl);
00777         write_end_of_sequence(m);
00778         d_wrote_soi = false;
00779     }
00780 
00781     return true;  // Signal errors with exceptions.
00782 }
00783 
00784 // If we are here then we know that this is 'parent sequence' and that the
00785 // leaf seq has found valid data to send. We also know that
00786 // serialize_parent_part_one has been called so data are in the instance's
00787 // fields. This is wheree we send data. Whereas ..._part_one() contains a
00788 // loop to iterate over all of rows in a parent sequence, this does not. This
00789 // method assumes that the serialize_leaf() will call it each time it needs
00790 // to be called.
00791 //
00792 // NB: This code only works if the child sequences appear after all other
00793 // variables.
00794 void
00795 Sequence::serialize_parent_part_two(DDS &dds,
00796                                     ConstraintEvaluator &eval, Marshaller &m)
00797 {
00798     DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
00799 
00800     BaseType *btp = get_parent();
00801     if (btp && btp->type() == dods_sequence_c)
00802         dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
00803 
00804     if (d_unsent_data) {
00805         DBG(cerr << "Writing Start of Instance marker" << endl);
00806         d_wrote_soi = true;
00807         write_start_of_instance(m);
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             // Send all the non-sequence variables
00812             DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
00813                 << (*iter)->name() << endl);
00814             if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
00815                 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
00816                 (*iter)->serialize(eval, dds, m, false);
00817             }
00818         }
00819 
00820         d_unsent_data = false;              // read should set this.
00821     }
00822 }
00823 
00824 // This code is only run by a leaf sequence. Note that a one level sequence
00825 // is also a leaf sequence.
00826 bool
00827 Sequence::serialize_leaf(DDS &dds,
00828                          ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
00829 {
00830     DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
00831     int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
00832 
00833     // read_row returns true if valid data was read, false if the EOF was
00834     // found. 6/1/2001 jhrg
00835     bool status = read_row(i, dds, eval, ce_eval);
00836     DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
00837 
00838     // Once the first valid (satisfies the CE) row of the leaf sequence has
00839     // been read, we know we're going to send data. Send the current instance
00840     // of the parent/ancestor sequences now, if there are any. We only need
00841     // to do this once, hence it's not inside the while loop, but we only
00842     // send the parent seq data _if_ there's data in the leaf to send, that's
00843     // why we wait until after the first call to read_row() here in the leaf
00844     // sequence.
00845     //
00846     // NB: It's important to only call serialize_parent_part_two() for a
00847     // Sequence that really is the parent of a leaf sequence. The fancy cast
00848     // will throw and exception if btp is not a Sequence, but doesn't test
00849     // that it's a parent sequence as we've defined them here.
00850     if (status && !is_end_of_rows(i)) {
00851         BaseType *btp = get_parent();
00852         if (btp && btp->type() == dods_sequence_c)
00853             dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds,
00854                                                                     eval, m);
00855     }
00856 
00857     d_wrote_soi = false;
00858     while (status && !is_end_of_rows(i)) {
00859         i += d_row_stride;
00860 
00861         DBG(cerr << "Writing Start of Instance marker" << endl);
00862         d_wrote_soi = true;
00863         write_start_of_instance(m);
00864 
00865         // In this loop serialize will signal an error with an exception.
00866         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00867             DBG(cerr << "Sequence::serialize_leaf(), serializing "
00868                 << (*iter)->name() << endl);
00869             if ((*iter)->send_p()) {
00870                 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
00871                 (*iter)->serialize(eval, dds, m, false);
00872             }
00873         }
00874 
00875         set_read_p(false); // ...so this will read the next instance
00876 
00877         status = read_row(i, dds, eval, ce_eval);
00878         DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
00879     }
00880 
00881     // Only write the EOS marker if there's a matching Start Of Instnace
00882     // Marker in the stream.
00883     if (d_wrote_soi || d_top_most) {
00884         DBG(cerr << "Writing End of Sequence marker" << endl);
00885         write_end_of_sequence(m);
00886     }
00887 
00888     return true;  // Signal errors with exceptions.
00889 }
00890 
00913 void
00914 Sequence::intern_data(ConstraintEvaluator &eval, DDS &dds)
00915 {
00916     DBG(cerr << "Sequence::intern_data - for " << name() << endl);
00917     DBG2(cerr << "    intern_data, values: " << &d_values << endl);
00918 
00919     // Why use a stack instead of return values? We need the stack because
00920     // Sequences neted three of more levels deep will loose the middle
00921     // instances when the intern_data_parent_part_two() code is run.
00922     sequence_values_stack_t sequence_values_stack;
00923 
00924     DBG2(cerr << "    pushing d_values of " << name() << " (" << &d_values
00925               << ") on stack; size: " << sequence_values_stack.size() << endl);
00926     sequence_values_stack.push(&d_values);
00927 
00928     intern_data_private(eval, dds, sequence_values_stack);
00929 }
00930 
00931 void
00932 Sequence::intern_data_private(ConstraintEvaluator &eval,
00933                               DDS &dds,
00934                               sequence_values_stack_t &sequence_values_stack)
00935 {
00936     DBG(cerr << "Entering intern_data_private for " << name() << endl);
00937 
00938     if (is_leaf_sequence())
00939         intern_data_for_leaf(dds, eval, sequence_values_stack);
00940     else
00941         intern_data_parent_part_one(dds, eval, sequence_values_stack);
00942 }
00943 
00944 void
00945 Sequence::intern_data_parent_part_one(DDS & dds,
00946                                       ConstraintEvaluator & eval,
00947                                       sequence_values_stack_t &
00948                                       sequence_values_stack)
00949 {
00950     DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
00951 
00952     int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
00953 
00954     // read_row returns true if valid data was read, false if the EOF was
00955     // found. 6/1/2001 jhrg
00956     // Since this is a parent sequence, read the row ignoring the CE (all of
00957     // the CE clauses will be evaluated by the leaf sequence).
00958     bool status = read_row(i, dds, eval, false);
00959 
00960     // Grab the current size of the value stack. We do this because it is
00961     // possible that no nested sequences for this row happened to be
00962     // selected because of a constract evaluation or the last row is not
00963     // selected because of a constraint evaluation. In either case, no
00964     // nested sequence d_values are pused onto the stack, so there is
00965     // nothing to pop at the end of this function. pcw 07/14/08
00966     SequenceValues::size_type orig_stack_size = sequence_values_stack.size() ;
00967 
00968     while (status
00969            && (get_ending_row_number() == -1
00970                || i <= get_ending_row_number()))
00971     {
00972         i += get_row_stride();
00973         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
00974             if ((*iter)->send_p()) {
00975                 switch ((*iter)->type()) {
00976                 case dods_sequence_c:
00977                     dynamic_cast<Sequence&>(**iter).intern_data_private(
00978                             eval, dds, sequence_values_stack);
00979                     break;
00980 
00981                 default:
00982                     (*iter)->intern_data(eval, dds);
00983                     break;
00984                 }
00985             }
00986         }
00987 
00988         set_read_p(false);      // ...so this will read the next instance
00989 
00990         status = read_row(i, dds, eval, false);
00991     }
00992 
00993     // Reset current row number for next nested sequence element.
00994     reset_row_number();
00995 
00996     // if the size of the stack is larger than the original size (retrieved
00997     // above) then pop the top set of d_values from the stack. If it's the
00998     // same, then no nested sequences, or possible the last nested sequence,
00999     // were pushed onto the stack, so there is nothing to pop.
01000     if( sequence_values_stack.size() > orig_stack_size )
01001     {
01002         DBG2(cerr << "    popping d_values (" << sequence_values_stack.top()
01003              << ") off stack; size: " << sequence_values_stack.size() << endl);
01004         sequence_values_stack.pop();
01005     }
01006     DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
01007 }
01008 
01009 void
01010 Sequence::intern_data_parent_part_two(DDS &dds,
01011                               ConstraintEvaluator &eval,
01012                               sequence_values_stack_t &sequence_values_stack)
01013 {
01014     DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
01015 
01016     BaseType *btp = get_parent();
01017     if (btp && btp->type() == dods_sequence_c) {
01018         dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two(
01019                                       dds, eval, sequence_values_stack);
01020     }
01021 
01022     DBG2(cerr << "    stack size: " << sequence_values_stack.size() << endl);
01023     SequenceValues *values = sequence_values_stack.top();
01024     DBG2(cerr << "    using values = " << (void *)values << endl);
01025 
01026     if (get_unsent_data()) {
01027         BaseTypeRow *row_data = new BaseTypeRow;
01028 
01029         // In this loop transfer_data will signal an error with an exception.
01030         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
01031 
01032             if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
01033                 row_data->push_back((*iter)->ptr_duplicate());
01034             }
01035             else if ((*iter)->send_p()) { //Sequence; must be the last variable
01036                 Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
01037                 if (!tmp)
01038                     throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
01039                 row_data->push_back(tmp);
01040                 DBG2(cerr << "    pushing d_values of " << tmp->name()
01041                      << " (" << &(tmp->d_values)
01042                      << ") on stack; size: " << sequence_values_stack.size()
01043                      << endl);
01044                 // This pushes the d_values field of the newly created leaf
01045                 // Sequence onto the stack. The code then returns to intern
01046                 // _data_for_leaf() where this value will be used.
01047                 sequence_values_stack.push(&(tmp->d_values));
01048             }
01049         }
01050 
01051         DBG2(cerr << "    pushing values for " << name()
01052                   << " to " << values << endl);
01053         values->push_back(row_data);
01054         set_unsent_data(false);
01055     }
01056     DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
01057 }
01058 
01059 void
01060 Sequence::intern_data_for_leaf(DDS &dds,
01061                                ConstraintEvaluator &eval,
01062                                sequence_values_stack_t &sequence_values_stack)
01063 {
01064     DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
01065 
01066     int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
01067 
01068     DBG2(cerr << "    reading row " << i << endl);
01069     bool status = read_row(i, dds, eval, true);
01070     DBG2(cerr << "    status: " << status << endl);
01071     DBG2(cerr << "    ending row number: " << get_ending_row_number() << endl);
01072 
01073     if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
01074         BaseType *btp = get_parent();
01075         if (btp && btp->type() == dods_sequence_c) {
01076             // This call will read the values for the parent sequences and
01077             // then allocate a new instance for the leaf and push that onto
01078             // the stack.
01079             dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two(
01080                                             dds, eval, sequence_values_stack);
01081         }
01082 
01083         // intern_data_parent_part_two pushes the d_values field of the leaf
01084         // onto the stack, so this operation grabs that value and then loads
01085         // data into it.
01086         SequenceValues *values = sequence_values_stack.top();
01087         DBG2(cerr << "    using values = " << values << endl);
01088 
01089         while (status && (get_ending_row_number() == -1
01090                           || i <= get_ending_row_number())) {
01091             i += get_row_stride();
01092 
01093             // Copy data from the object's fields to this new BaeTypeRow instance
01094             BaseTypeRow *row_data = new BaseTypeRow;
01095             for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
01096                 if ((*iter)->send_p()) {
01097                     row_data->push_back((*iter)->ptr_duplicate());
01098                 }
01099             }
01100 
01101             DBG2(cerr << "    pushing values for " << name()
01102                       << " to " << values << endl);
01103             // Save the row_data to values().
01104             values->push_back(row_data);
01105 
01106             set_read_p(false);      // ...so this will read the next instance
01107             // Read the ith row into this object's fields
01108             status = read_row(i, dds, eval, true);
01109         }
01110 
01111         DBG2(cerr << "    popping d_values (" << sequence_values_stack.top()
01112              << ") off stack; size: " << sequence_values_stack.size() << endl);
01113         sequence_values_stack.pop();
01114     }
01115     DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
01116 }
01117 
01138 bool
01139 Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
01140 {
01141     DataDDS *dd = dynamic_cast<DataDDS *>(dds);
01142     if (!dd)
01143         throw InternalErr("Expected argument 'dds' to be a DataDDS!");
01144 
01145     DBG2(cerr << "Reading from server/protocol version: "
01146          << dd->get_protocol_major() << "." << dd->get_protocol_minor()
01147          << endl);
01148 
01149     // Check for old servers.
01150     if (dd->get_protocol_major() < 2) {
01151         throw Error(string("The protocl version (") + dd->get_protocol()
01152                     + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
01153     }
01154 
01155     while (true) {
01156         // Grab the sequence stream's marker.
01157         unsigned char marker = read_marker(um);
01158         if (is_end_of_sequence(marker))
01159             break;  // EXIT the while loop here!!!
01160         else if (is_start_of_instance(marker)) {
01161             d_row_number++;
01162             DBG2(cerr << "Reading row " << d_row_number << " of "
01163                  << name() << endl);
01164             BaseTypeRow *bt_row_ptr = new BaseTypeRow;
01165             // Read the instance's values, building up the row
01166             for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
01167                 BaseType *bt_ptr = (*iter)->ptr_duplicate();
01168                 bt_ptr->deserialize(um, dds, reuse);
01169                 DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
01170                      << bt_ptr << ") = ");
01171                 DBG2(bt_ptr->print_val(stderr, ""));
01172                 bt_row_ptr->push_back(bt_ptr);
01173             }
01174             // Append this row to those accumulated.
01175             d_values.push_back(bt_row_ptr);
01176         }
01177         else
01178             throw Error("I could not read the expected Sequence data stream marker!");
01179     };
01180 
01181     return false;
01182 }
01183 
01184 // Return the current row number.
01185 
01197 int
01198 Sequence::get_starting_row_number()
01199 {
01200     return d_starting_row_number;
01201 }
01202 
01213 int
01214 Sequence::get_row_stride()
01215 {
01216     return d_row_stride;
01217 }
01218 
01230 int
01231 Sequence::get_ending_row_number()
01232 {
01233     return d_ending_row_number;
01234 }
01235 
01244 void
01245 Sequence::set_row_number_constraint(int start, int stop, int stride)
01246 {
01247     if (stop < start)
01248         throw Error(malformed_expr, "Starting row number must precede the ending row number.");
01249 
01250     d_starting_row_number = start;
01251     d_row_stride = stride;
01252     d_ending_row_number = stop;
01253 }
01254 
01257 unsigned int
01258 Sequence::val2buf(void *, bool)
01259 {
01260     throw InternalErr(__FILE__, __LINE__, "Never use this method; see the programmer's guide documentation.");
01261     return sizeof(Sequence);
01262 }
01263 
01268 unsigned int
01269 Sequence::buf2val(void **)
01270 {
01271     throw InternalErr(__FILE__, __LINE__, "Use Sequence::var_value() or Sequence::row_value() in place of Sequence::buf2val()");
01272     return sizeof(Sequence);
01273 }
01274 //#if FILE_METHODS
01275 void
01276 Sequence::print_one_row(FILE *out, int row, string space,
01277                         bool print_row_num)
01278 {
01279     if (print_row_num)
01280         fprintf(out, "\n%s%d: ", space.c_str(), row) ;
01281 
01282     fprintf(out, "{ ") ;
01283 
01284     int elements = element_count() - 1;
01285     int j;
01286     BaseType *bt_ptr;
01287     // Print first N-1 elements of the row.
01288     for (j = 0; j < elements; ++j) {
01289         bt_ptr = var_value(row, j);
01290         if (bt_ptr) {  // data
01291             if (bt_ptr->type() == dods_sequence_c)
01292                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01293                 (out, space + "    ", false, print_row_num);
01294             else
01295                 bt_ptr->print_val(out, space, false);
01296             fprintf(out, ", ") ;
01297         }
01298     }
01299 
01300     // Print Nth element; end with a `}.'
01301     bt_ptr = var_value(row, j);
01302     if (bt_ptr) {  // data
01303         if (bt_ptr->type() == dods_sequence_c)
01304             dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01305             (out, space + "    ", false, print_row_num);
01306         else
01307             bt_ptr->print_val(out, space, false);
01308     }
01309 
01310     fprintf(out, " }") ;
01311 }
01312 //#endif
01313 void
01314 Sequence::print_one_row(ostream &out, int row, string space,
01315                         bool print_row_num)
01316 {
01317     if (print_row_num)
01318         out << "\n" << space << row << ": " ;
01319 
01320     out << "{ " ;
01321 
01322     int elements = element_count();
01323     int j = 0;
01324     BaseType *bt_ptr = 0;
01325 
01326     // This version of print_one_row() works for both data read with
01327     // deserialize(), where each variable is assumed to have valid data, and
01328     // intern_data(), where some/many variables do not. Because of that, it's
01329     // not correct to assume that all of the elements will be printed, which
01330     // is what the old code did.
01331     // Print the first value
01332     while (j < elements && !bt_ptr) {
01333         bt_ptr = var_value(row, j++);
01334         if (bt_ptr) {  // data
01335             if (bt_ptr->type() == dods_sequence_c)
01336                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01337                      (out, space + "    ", false, print_row_num);
01338             else
01339                 bt_ptr->print_val(out, space, false);
01340         }
01341     }
01342 
01343     // Print the remaining values
01344     while (j < elements) {
01345         bt_ptr = var_value(row, j++);
01346         if (bt_ptr) {  // data
01347             out << ", ";
01348             if (bt_ptr->type() == dods_sequence_c)
01349                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01350                         (out, space + "    ", false, print_row_num);
01351             else
01352                 bt_ptr->print_val(out, space, false);
01353         }
01354     }
01355 
01356 #if 0
01357     // old version
01358     int elements = element_count() - 1;
01359     int j;
01360     BaseType *bt_ptr;
01361     // Print first N-1 elements of the row.
01362     for (j = 0; j < elements; ++j) {
01363         bt_ptr = var_value(row, j);
01364         if (bt_ptr) {  // data
01365             if (bt_ptr->type() == dods_sequence_c)
01366                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01367                      (out, space + "    ", false, print_row_num);
01368             else
01369                 bt_ptr->print_val(out, space, false);
01370             out << ", " ;
01371         }
01372     }
01373 
01374     // Print Nth element; end with a `}.'
01375     bt_ptr = var_value(row, j);
01376     if (bt_ptr) {  // data
01377         if (bt_ptr->type() == dods_sequence_c)
01378             dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01379             (out, space + "    ", false, print_row_num);
01380         else
01381             bt_ptr->print_val(out, space, false);
01382     }
01383 #endif
01384 
01385     out << " }" ;
01386 }
01387 
01388 //#if FILE_METHODS
01389 void
01390 Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p,
01391                             bool print_row_numbers)
01392 {
01393     if (print_decl_p) {
01394         print_decl(out, space, false);
01395         fprintf(out, " = ") ;
01396     }
01397 
01398     fprintf(out, "{ ") ;
01399 
01400     int rows = number_of_rows() - 1;
01401     int i;
01402     for (i = 0; i < rows; ++i) {
01403         print_one_row(out, i, space, print_row_numbers);
01404         fprintf(out, ", ") ;
01405     }
01406     print_one_row(out, i, space, print_row_numbers);
01407 
01408     fprintf(out, " }") ;
01409 
01410     if (print_decl_p)
01411         fprintf(out, ";\n") ;
01412 }
01413 //#endif
01414 void
01415 Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p,
01416                             bool print_row_numbers)
01417 {
01418     if (print_decl_p) {
01419         print_decl(out, space, false);
01420         out << " = " ;
01421     }
01422 
01423     out << "{ " ;
01424 
01425     int rows = number_of_rows() - 1;
01426     int i;
01427     for (i = 0; i < rows; ++i) {
01428         print_one_row(out, i, space, print_row_numbers);
01429         out << ", " ;
01430     }
01431     print_one_row(out, i, space, print_row_numbers);
01432 
01433     out << " }" ;
01434 
01435     if (print_decl_p)
01436         out << ";\n" ;
01437 }
01438 //#if FILE_METHODS
01439 void
01440 Sequence::print_val(FILE *out, string space, bool print_decl_p)
01441 {
01442     print_val_by_rows(out, space, print_decl_p, false);
01443 }
01444 //#endif
01445 void
01446 Sequence::print_val(ostream &out, string space, bool print_decl_p)
01447 {
01448     print_val_by_rows(out, space, print_decl_p, false);
01449 }
01450 
01451 
01452 bool
01453 Sequence::check_semantics(string &msg, bool all)
01454 {
01455     if (!BaseType::check_semantics(msg))
01456         return false;
01457 
01458     if (!unique_names(_vars, name(), type_name(), msg))
01459         return false;
01460 
01461     if (all)
01462         for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
01463             if (!(*i)->check_semantics(msg, true)) {
01464                 return false;
01465             }
01466         }
01467 
01468     return true;
01469 }
01470 
01471 void
01472 Sequence::set_leaf_p(bool state)
01473 {
01474     d_leaf_sequence = state;
01475 }
01476 
01477 bool
01478 Sequence::is_leaf_sequence()
01479 {
01480     return d_leaf_sequence;
01481 }
01482 
01507 void
01508 Sequence::set_leaf_sequence(int lvl)
01509 {
01510     bool has_child_sequence = false;
01511 
01512     if (lvl == 1) d_top_most = true;
01513 
01514     DBG2(cerr << "Processing sequence " << name() << endl);
01515 
01516     for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
01517         // About the test for send_p(): Only descend into a sequence if it has
01518         // fields that might be sent. Thus if, in a two-level sequence, nothing
01519         // in the lower level is to be sent, the upper level is marked as the
01520         // leaf sequence. This ensures that values _will_ be sent (see the comment
01521         // in serialize_leaf() and serialize_parent_part_one()).
01522         if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
01523             if (has_child_sequence)
01524                 throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
01525 
01526             has_child_sequence = true;
01527             dynamic_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
01528         }
01529         else if ((*iter)->type() == dods_structure_c) {
01530             dynamic_cast<Structure&>(**iter).set_leaf_sequence(lvl);
01531         }
01532     }
01533 
01534     if (!has_child_sequence)
01535         set_leaf_p(true);
01536     else
01537         set_leaf_p(false);
01538 
01539     DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
01540 }
01541 
01550 void
01551 Sequence::dump(ostream &strm) const
01552 {
01553     strm << DapIndent::LMarg << "Sequence::dump - ("
01554     << (void *)this << ")" << endl ;
01555     DapIndent::Indent() ;
01556     Constructor::dump(strm) ;
01557     strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number
01558          << endl ;
01559     strm << DapIndent::LMarg << "bracket notation information:" << endl ;
01560     DapIndent::Indent() ;
01561     strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number
01562          << endl ;
01563     strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl ;
01564     strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number
01565          << endl ;
01566     DapIndent::UnIndent() ;
01567 
01568     strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl ;
01569     strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl ;
01570     strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence
01571          << endl ;
01572     strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most
01573          << endl ;
01574     DapIndent::UnIndent() ;
01575 }
01576 
01577 } // namespace libdap
01578 

Generated on Mon May 18 10:25:03 2009 for libdap++ by  doxygen 1.4.7